OpenCV图像IO
读取图像
cv2.imread(‘图片路径’,’读取图片的方式’)
读取图片方式:
①读取灰度图像数据 cv2.IMREAD_GRAYSCALE
eg:
img_gray_data = cv2.imread('./images/messi.jpg', cv2.IMREAD_GRAYSCALE)
要想获得图片的其他信息
print('数据类型:', type(img_gray_data))
print('数组类型:', img_gray_data.dtype)
print('数组形状:', img_gray_data.shape)
print('数组最大值:{},最小值:{}'.format(img_gray_data.max(), img_gray_data.min()))
从结果可以看出
1.type(img_gray_data)
图片的数据类型为numpy也就是说使用numpy的多维数组ndarray保存图片的矩阵的。
2.img_gray_data.dtype
数组类型是无符号8位整数,所以像素值最大是255=2的8次方-1
3.img_gray_data.shape
数组形状是说她是342*548的二维数组,因为这是灰度图像所以是二维数组
4.img_gray_data.max() img_gray_data.min()
像素的最大值为253,最小值为0
②读取彩色图像数据 cv2.IMREAD_COLOR
eg:
img_rgb_data = cv2.imread('./images/messi.jpg', cv2.IMREAD_COLOR)
可以输出彩色图像数据的信息和上面的灰度图比较一下
print('数据类型:', type(img_rgb_data))
print('数组类型:', img_rgb_data.dtype)
print('数组形状:', img_rgb_data.shape)
print('数组最大值:{},最小值:{}'.format(img_rgb_data.max(), img_rgb_data.min()))
可以从结果看出彩色图像和灰度图最大的不同时,彩色图是3维的,第三个维度为通道
显示图像
cv2.imshow(‘输出窗口的名字’,输出的图片) #显示图像
参数:
- 输出窗口的名字
自行定义,如果第二次输出图片的窗口名与第一次输出的一致则第二张图会覆盖掉第一张图,因为你指定的是从同一个窗口显示出来。 - 输出的图片
输出的图片即读取的图片名称
cv2.waitKey(0) #图像显示事件,0表示不消失
cv2.destroyAllWindows()
eg:把上面读取的图像显示出来
cv2.imshow('gray', img_gray_data) #显示读取的灰度图
cv2.imshow('rgb', img_rgb_data) #显示读取的RGB图
cv2.waitKey(0)
cv2.destroyAllWindows()
保存图像
cv2.imwrite()
像素值访问
通道分割
OpenCV库方法 cv2.split
cv2.split()
返回值为三个通道的图片数据,因为OpenCV读取的图像顺序为BGR,所以返回值的顺序也是BGR
# 使用split进行通道分割
b_data, g_data, r_data = cv2.split(img_rgb_data)
cv2.imshow('B', b_data)
cv2.imshow('G', g_data)
cv2.imshow('R', r_data)
cv2.waitKey(0)
cv2.destroyAllWindows()
通过切片操作进行分割
要特别注意的是OpenCV读取的图像数据通道排序为 BGR,所以进行切片操作的时候,0代表B,1代表G,2代表R
# 通过切片操作只显示某个通道上的图像数据
# OpenCV读取的图像数据通道排序为 BGR
cv2.imshow('B', img_rgb_data[:, :, 0]) # 颜色越接近蓝色,数值越大,亮度越亮
cv2.imshow('G', img_rgb_data[:, :, 1])
cv2.imshow('R', img_rgb_data[:, :, 2])
cv2.waitKey(0)
cv2.destroyAllWindows()
合并通道 merge
cv2.merge((b_data, g_data, r_data)
注意参数顺序为b,g,r
合并后的结果即彩色图像
bgr_data = cv2.merge((b_data, g_data, r_data))
cv2.imshow('color', bgr_data)
cv2.waitKey(0)
cv2.destroyAllWindows()
ROI 感兴趣区域
ROI 就是我们要操作的区域,找到我们感兴趣的区域再对此区域进行操作。
下面的例子是直接通过像素点的位置得到的感兴趣区域,注意280:340是图片的高,330:390是图片的宽。
# ROI
ball = img_rgb_data[280:340, 330:390, :]
cv2.imshow('ball', ball)
cv2.waitKey(0)
cv2.destroyAllWindows()
在图片上叠加蓝色方块
也就是选择位置,然后给他赋值为一个像素或者一张图片
注意:图片的位置范围表示第一个位置上为高度H,是我们平常理解的Y值;
第二个位置上的值为宽度W,为我们平常理解的X值;
# 在图片上叠加一个蓝色方块
img_rgb_data[10:110, 10:110, :] = [255, 0, 0] #这里选择图片img_rgb_data的X,Y范围都为10:110的区域,将他的像素赋值为[255,0,0],因为第一个通道代表B,B为255则是蓝色。
cv2.imshow('color with red box', img_rgb_data)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像融合
图像融合就是把两张图片融合成一张图片
NumPy加法和OpenCV中加法的区别
因为图像融合要使用到OPenCV的加法,我们首先来看一下Numpy加法和OPenCV加法的区别
因为图像中像素都是用8为无符号整数表示的,所以最大值为255.
所以当越界时,numpy的加法是取模256,结果为余数。而OPenCV是只要超过255则结果就为255
# 先设置两个8位无符号整数x和y
x = np.uint8([250])
y = np.uint8([10])
print(cv2.add(x, y)) # 250 + 10 = 260 => 255
print(x + y) # 250 + 10 = 260 % 256 = 4
通过OPenCV的加法实现图片融合
不带权重直接相加
cv2.add
带权重相加,想让哪张图片更清晰就赋予更大的权重
cv2.addWeighted
因为要使用加法,则两种图片的大小必须相同,当图片大小不同时要使用resize将其中的一个图片转成另一个图片的大小。
cv2.resize(img2, (img1.shape[1], img1.shape[0]))
img1 = cv2.imread('./images/python_ai.png')
img2 = cv2.imread('./images/python_logo.png')
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) #把图片2设置成和图片1一样大,便于相加
dst = cv2.addWeighted(img1, 0.7, img2, 0.3, 0) #有权重的相加
cv2.imshow('dst', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('./output/python_ai_logo.png', dst) #将结果保存
因为resize对图片进行拉伸,这可能会导致图片的特征改变。我们可以通过crop对图片进行裁剪,避免把图片的特征变了。
crop就是找到所有图片中长和宽最小的那张图,然后把其他图片按照这个最小的图片大小进行裁剪,因为裁剪可以从左上角裁剪也可以从右上角进行裁剪等,所以可以达到图像增强的作用。
如果我们用4中裁剪方法,则把原来一张图片变成了4张,这样就增多了样本数,我们知道CNN较之机器学习的其他算法训练效果比较好的基础是要有足够多的样本数,我们通过crop这样的方法是可以增多图片的数量的。