像素值以矩阵方式保存,矩阵的大小取决于图像采用的颜色模型。
如果是灰度图,那么图像就是单通道的,图像中的每个像素只需要一个矩阵元素来保存,一般就是 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]]]
分别输出 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 通道灰度图送给蓝色,所以原来是红色的部分自然就是蓝色了。