学过线性代数的对矩阵并不陌生。一般来说,图像是一个标准的矩形,有着宽度(width)和高度(height)。而矩阵有着行(row)和列(column),矩阵的操作在数学和计算机中的处理都很常见且成熟,于是很自然的就把图像作为一个矩阵,把对图像的操作转换成对矩阵的操作,实际上所有的图像处理工具都是这么做的。
我们看看下面这张图像:
用opencv读取:
import cv2
mountain = cv2.imread('mountain.bmp', 0) # 读取为灰度图
print("shape=", mountain.shape)
print("type=", type(mountain))
输出结果:
type= <class 'numpy.ndarray'>
shape= (480, 640)
可以看出,图像在读取后,存在了一个ndarray中,这是numpy中的矩阵类型。
源图像的宽度是640,高度是480,我们一般习惯上依次用高度、宽度的顺序。在矩阵中,高度对应的是多少行(row),宽度对应的是多少列(column),而矩阵的顺序是(row,column),所以输出的shape是(480, 640)。
把图像作为矩阵,可以很方便的进行一些操作,例如取图像中某个区域的值,也就是所谓的crop(裁剪)操作。
print(mountain[9:12, 9:12])
输出结果:
[[244 244 244]
[244 236 244]
[244 244 236]]
取大一些的区域,并显示出来。
cv2.imshow("crop", mountain[200:400, 200:600])
print(mountain[200:400, 200:600].shape)
cv2.waitKey()
输出结果:
(200, 400)
对于如下的彩色图像:
fruits = cv2.imread('fruits.bmp')
print("type=", type(fruits))
print("shape=", fruits.shape)
print(fruits[100, 100])
输出结果:
type= <class 'numpy.ndarray'>
shape= (480, 512, 3)
[ 52 96 116]
可以看出,彩色图像同样是一个矩阵,只是矩阵中的每一个点不是一个值,而是包含3个值的数组,这3个值就是RGB值,下面的代码查看RGB3通道的图像(注意,opencv的顺序是BGR)。
import matplotlib.pyplot as plt
fruits = cv2.cvtColor(fruits, cv2.COLOR_BGR2RGB)
fruits_all = [fruits, fruits[:, :, 0], fruits[:, :, 1], fruits[:, :, 2]]
channels = ["RGB", "red", "green", "blue"]
for i in range(4):
plt.subplot(2, 2, i + 1)
plt.imshow(fruits_all[i], cmap=plt.cm.gray)
plt.title(channels[i])
plt.show()
for fruit in fruits_all:
print(fruit.shape)
(480, 512, 3)
(480, 512)
(480, 512)
(480, 512)
可以看出,每一个RGB通道都是一个矩阵。这3个RGB通道叠在一起形成了彩色图像。
你还可以方便的得到某一行图像的值。
fruit_red = fruits[:, :, 0]
plt.plot(fruit_red[200, :])
plt.show()
输出结果:
那么,到底是把图像看作函数,还是看作矩阵?都可以,看你要干什么了,2个不同的角度而已。