您当前的位置:首页 > 计算机 > 精彩资源

关于三通道彩色图像的存储方式理解

时间:01-28来源:作者:点击数:
图像像素在内存中的保存方式

像素值以矩阵方式保存,矩阵的大小取决于图像采用的颜色模型。

如果是灰度图,那么图像就是单通道的,图像中的每个像素只需要一个矩阵元素来保存,一般就是 0~255 的值。

保存灰度图的矩阵长这样:

在这里插入图片描述

其中 Row0 和 Column0 的交点上的元素值就代表了图像上对应位置的像素的灰度值。

如果是彩色图,那么图像就是多通道的,一个像素需要多个矩阵元素来保存,矩阵中的列会包含多个子列,且子列数和通道数相等。

保存 RGB 图像的矩阵长这样:

在这里插入图片描述
图像存储为矩阵

看看一个三通道的彩色图像是怎么组织为矩阵形式的。

原图:

在这里插入图片描述

注:opencv 里图像的存储为BGR 格式,刚好和现在流行的 RGB 反过来了。

看一下图像的 shape 和矩阵存储形式:

import cv2
import numpy as np

img = cv2.imread('Touka.jpg')
cv2.imshow('src', img)  # src为标题,表示原图
print(img.shape)
print(img.size)
print(img.dtype)
print(img)
cv2.waitKey()
# img.shape
(1080, 1920, 3)
# img.size
6220800
# img.dtype
uint8
# img
[[[255 255 255]
  [255 255 255]
  [255 255 255]
  ...
  [199 185 251]
  [205 186 255]
  [209 187 255]]

 [[255 255 255]
  [255 255 255]
  [255 255 255]
  ...
  [190 179 251]
  [190 177 251]
  [192 177 251]]

 [[255 255 255]
  [255 255 255]
  [255 255 255]
  ...
  [179 177 253]
  [174 171 250]
  [174 169 248]]

 ...

 [[255 255 255]
  [255 255 255]
  [255 255 255]
  ...
  [255 255 255]
  [255 255 255]
  [255 255 255]]

 [[255 255 255]
  [255 255 255]
  [255 255 255]
  ...
  [255 255 255]
  [255 255 255]
  [255 255 255]]

 [[255 255 255]
  [255 255 255]
  [255 255 255]
  ...
  [255 255 255]
  [255 255 255]
  [255 255 255]]]
  1. 输出是三维矩阵,这个判断比较简单,从第一个 “[” 开始数,直到第一个 “]” 时,有几个 “[” 就是几维的,这和输出的 img.shape 也肯定是对应的。
  2. 输出的图像 shape 为 H * W * 3,即 高度 * 宽度 * 3通道 或者 行数 * 列数 * 3通道。
  3. 图像的 shape 为 (1080, 1920, 3),第一维 1080 表示有 1080 行,所以有 1080 个小的二维矩阵,每个二维矩阵是三通道图像中的一行。
    在这里插入图片描述
  4. 在每一个小矩阵中,有 1920 行,每一行有 3 列,每一行的三个像素值就对应当前位置的 B G R 三个通道。这列能够看出,虽然按照行来分块,但实际上列方向才是位置上相邻的像素点。
    在这里插入图片描述
  5. 再从通道的角度看,BGR 是三通道,第一整列对应的就是一幅图所有的 B 通道灰度值(更准确一些应该叫亮度值),第二、第三就分别是 G 和 R 通道对应的灰度值。下图只截取了一部分,知道什么意思就行。
    在这里插入图片描述

分别输出 B G R 三个通道看看:

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib qt5

img = cv2.imread('Touka.jpg')
channels = ["B", "G", "R"] # 注意通道顺序

for i in range(3):
	print("channel: " + channels[i])
    print(img[:,:,i])
    plt.subplot(1, 3, i+1)
    plt.imshow(img[:,:,i], cmap=plt.cm.gray)
    plt.title(channels[i])
    
print(img[:,:,0].shape)
plt.show()
# 输出
channel: B
[[255 255 255 ... 199 205 209]
 [255 255 255 ... 190 190 192]
 [255 255 255 ... 179 174 174]
 ...
 [255 255 255 ... 255 255 255]
 [255 255 255 ... 255 255 255]
 [255 255 255 ... 255 255 255]]
channel: G
[[255 255 255 ... 185 186 187]
 [255 255 255 ... 179 177 177]
 [255 255 255 ... 177 171 169]
 ...
 [255 255 255 ... 255 255 255]
 [255 255 255 ... 255 255 255]
 [255 255 255 ... 255 255 255]]
channel: R
[[255 255 255 ... 251 255 255]
 [255 255 255 ... 251 251 251]
 [255 255 255 ... 253 250 248]
 ...
 [255 255 255 ... 255 255 255]
 [255 255 255 ... 255 255 255]
 [255 255 255 ... 255 255 255]]

# shape
(1080, 1920)

要知道将 RGB 图像拆开,每个通道单独拿出来都是一个与原图大小相同的灰度图,灰度图中像素的灰度值越大,该像素的颜色就越浅,灰度值越小颜色就越深。

注意这里的深和浅说的是灰度图中的像素,和彩色图没有关系,当要显示彩色图像时,将 R G B 三个分量分别放入红色、绿色和蓝色通道里,经过处理后就得到了彩色图像。

所以我们想要什么颜色深一些,只需要将它对应的灰度图中的灰度值设置大一些就好了。

对于一张彩色图中越红的部分,在它的 R 通道灰度图上对应区域的像素灰度值越大,灰度图像素的颜色越浅。下面第 3 张是 R 分量的灰度图,可以观察到在原图中越红的部分在这张灰度图中的颜色就越浅,因为灰度值大。

在这里插入图片描述

其实 R G B 三个通道的灰度图和颜色没有关系,如果愿意它们还可以随便定义为红橙黄绿青蓝紫…

交换一下 R 和 B 通道,也就是把 R 分量送给蓝色通道,把 B 分量送给红色通道,就得到下面的结果:

在这里插入图片描述

这样就能看出,其实 B G R 三通道灰度图与颜色没有关系,它们相当于”颜料“,想要蓝色多一些就加”颜料“,也就是把蓝色对应的灰度图的灰度值调大,上面将灰度值较大的 R 通道灰度图送给蓝色,所以原来是红色的部分自然就是蓝色了。

在这里插入图片描述
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门