在OpenCV中,可以对于图片进行算法运算。我们知道,图像的本质其实就是矩阵,因此对于图像的算数运算本质上就是对于矩阵的算术运算。在OpenCV可以对图像进行算术运算的操作有加、减、乘、除等操作。
图像的加、减、乘、除操作
两张图像可以进行算术运算操作,即对两图像的矩阵进行加减操作。例如,文件夹中有两张图片:
现在想把这两张图像加起来,首先先获取两张图片的行数和列数:
python
import cv2
import matplotlib.pyplot as plt
import numpy as np
img1=cv2.imread(r'D:\Photo\1.jpeg')
img2=cv2.imread(r'D:\Photo\2.jpeg')
print(img1.shape)
print(img2.shape)
运行结果如下所示:
python
(500, 500, 3)
(500, 667, 3)
可以看到两张图片的行数相等,但是列数第二张图片的列数较大,因此在如果两个图像要进行算术运算操作,需要行数和列数需要保持一致,因此只能将图像截取。
(1)将上面两张图片进行相加操作:
python
import cv2
import matplotlib.pyplot as plt
import numpy as np
image_dog=cv2.imread(r'D:\Photo\1.jpeg')
image_cat=cv2.imread(r'D:\Photo\2.jpeg')
image_cat=cv2.resize(image_cat,(500,500))
image_new=image_cat+image_dog
cv2.imshow('image_new',image_new)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如下所示:
可以看到,图片的所运行出来的结果就是每一个像素进行叠加,运行出来的结果为上图所示。
(2)同样,也可以进行相减的操作,只需要将上面代码中的image_new=image_cat-image_dog即可。即为:
python
image_new=image_cat-image_dog
运行结果如下所示:
(3)同样,也可以进行相乘的操作,只需要将上面代码中的image_new=image_cat*image_dog即可。
python
image_new=image_cat*image_dog
运行结果如下所示:
由于相乘结果数值相差较大,因此所得到的结果比较混乱。
(4)图像的算数操作同样可以对数进行操作,例如将图像所对应的矩阵里的数全部除以2,代码为:
python
import cv2
import matplotlib.pyplot as plt
import numpy as np
img_dog=cv2.imread(r'D:\Photo\1.jpeg')
res=img_dog//2
plt.imshow(res)
运行结果为:
通过图片可以看出图片整体变暗了,原因是图片对应的矩阵的值变为原来的一半。
图片的叠加
(1)图片不可以这样简单地进行算数运算,同时也可以进行叠加(即为图像的加权融合),在OpenCV使用cv2.addWeigthed()进行叠加。在cv2.addWeighted()中,至少需要输入四个参数,即为第一个需要加权融合的图片,第一个图片所占的权重,第二个需要加权融合的图片,第二个图片所占的权重,例如:
python
import cv2
import matplotlib.pyplot as plt
import numpy as np
img_dog=cv2.imread(r'D:\Photo\1.jpeg')
img_cat=cv2.imread(r'D:\Photo\2.jpeg')
img_cat=cv2.resize(img_cat,(500,500))
res=cv2.addWeighted(img_cat,0.5,img_dog,0.5,0)
plt.imshow(res)
运行效果如下所示:
(2)此时两张图片的权重各占0.5,如果修改权重,将image_cat改为0.7,image_dog改为0.3,那么只需修改代码:
python
res=cv2.addWeighted(img_cat,0.7,img_dog,0.3,0)
运行效果为:
可以看到,当image_cat为0.7,image_dog为0.3的时候,可以看到猫的图片占据了主导地位。
(3)需要说明的是,图片的叠加可以用图片的算术操作完成,例如加权融合的权重为0.5时,下面两句代码效果等效:
python
res=cv2.addWeighted(img_1,0.5,img_2,0.5,0)
res=img_1//2+img_1//2
用上面的例子进行验证:
python
import cv2
import matplotlib.pyplot as plt
import numpy as np
img_dog=cv2.imread(r'D:\Photo\1.jpeg')
img_cat=cv2.imread(r'D:\Photo\2.jpeg')
img_cat=cv2.resize(img_cat,(500,500))
res1=cv2.addWeighted(img_cat,0.5,img_dog,0.5,0)
res2=img_cat//2+img_dog//2
cv2.imshow('res1',res1)
cv2.imshow('res2',res2)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行效果如下所示:
可以看到完全相同,所以对图片进行融合的时候两种方法都可以。
多通道图像拆分为多个单通道图像
在OpenCV中利用cv2.split()将多个颜色通道图像(例如BGR格式的彩色图像)拆分为多个单独的灰色图像,每个灰度图像代表原图像的一个颜色通道。
注:split()函数需要完成三个任务:
- 通道分离:它可以将一个三通道的BGR图像分离成三个单通道的灰度图像,分别是蓝色、绿色和红色通道。
- 数据结构:
split()
函数可以接受两种类型的输出参数,一种是Mat
数组,另一种是std::vector<Mat>
。在Python中,通常使用numpy
数组来接收分离后的通道。- 使用方式:当你有一个
Mat
对象表示的图像时,可以调用split()
函数并传入该对象以及一个用于存放结果的数组或向量。这样,原图像的每个通道就会被提取出来并存储在指定的位置。
例如:
python
import cv2
import matplotlib.pyplot as plt
import numpy as np
#颜色通道提取
img=cv2.imread(r'D:\Photo\1.jpeg')
b,g,r=cv2.split(img)
print('b通道\n')
print(b)
print('g通道\n')
print(g)
print('r通道\n')
print(r)
运行结果为:
python
b通道
[[186 186 186 ... 30 41 34]
[186 186 186 ... 39 46 36]
[186 186 186 ... 39 41 29]
...
[160 161 165 ... 37 59 101]
[160 161 163 ... 42 39 62]
[154 155 157 ... 62 40 52]]
g通道
[[118 118 118 ... 51 61 54]
[118 118 118 ... 59 66 56]
[118 118 118 ... 59 61 49]
...
[177 178 181 ... 73 95 137]
[177 178 180 ... 76 72 96]
[171 172 173 ... 96 74 85]]
r通道
[[ 70 70 70 ... 45 55 48]
[ 70 70 70 ... 53 60 51]
[ 70 70 70 ... 53 55 44]
...
[188 189 192 ... 81 103 145]
[188 189 191 ... 84 81 104]
[182 183 184 ... 104 82 93]]
通过上面结果可以看到一张RGB图像分成了三个通道,每个通道有不同的数据内容。而不同颜色通道的图片是什么样子的呢?下面我们分别展示B、G、R通道:
python
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread(r'D:\Photo\1.jpeg')
#只保留R通道
cur_img1=img.copy()
cur_img1[:,:,0]=0
cur_img1[:,:,1]=0
#只保留G通道
cur_img2=img.copy()
cur_img2[:,:,0]=0
cur_img2[:,:,2]=0
#只保留B通道
cur_img3=img.copy()
cur_img3[:,:,1]=0
cur_img3[:,:,2]=0
cv2.imshow('R通道',cur_img1)
cv2.imshow('G通道',cur_img2)
cv2.imshow('B通道',cur_img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如下所示:
上面通道所展示的结果是B通道、G通道、R通道所呈现的内容。