这是对于 OpenCV 官方文档的 核心操作的学习笔记。学习笔记中会记录官方给出的例子,也会给出自己根据官方的例子完成的更改代码,同样彩蛋的实现也会结合多个知识点一起实现一些小功能,来帮助我们对学会的知识点进行结合应用。
如果有喜欢我笔记的请麻烦帮我关注、点赞、评论。谢谢诸位。
学习笔记:
学习笔记目录里面会收录我关于OpenCV系列学习笔记博文,大家如果有什么不懂的可以通过阅读我的学习笔记进行学习。
【OpenCV学习笔记】- 学习笔记目录
这里我们需要理解,图像的本质是多维数组组成。所以对于图像的算数运算和数组运算相同。一般图像的数据结构是 numpy 。在学习的过程中,我们需要了解 numpy 的基础。同样的 OpenCV 也提供了相应的计算方法。接下来就让我们一起来了解一下。
您可以通过 OpenCV 函数,cv.add() 或简单地通过 numpy 操作将两个图像相加,res = img1 + img2。两个图像应该具有相同的深度和类型,或者第二个图像可以是像素值,比如(255,255,255),白色值。
注意: OpenCV 相加操作和 Numpy 相加操作之间存在差异。OpenCV 添加是饱和操作,而 Numpy 添加是模运算。要注意的是,两种加法对于结果溢出的数据,会通过某种方法使其在限定的数据范围内。
示例代码:
# 图像的算术运算
import numpy as np
import cv2
# 图像加法
x = np.uint8([250])
y = np.uint8([10])
# 饱和度最高255,cv2计算的是饱和度操作
# 250 + 10 = 260 => 255
print('1: ' + str(cv2.add(x, y)))
print('1: ' + str(x + y))
x = np.uint8([100])
y = np.uint8([10])
# 100 + 10 = 110
print('2: ' + str(cv2.add(x, y)))
# 100 + 10 = 110
print('2: ' + str(x + y))
x = np.uint8([246])
y = np.uint8([10])
# cv2超限会被设置为限定值 255
# 246 + 10 = 255
print('3: ' + str(cv2.add(x, y)))
# numpy 超限会被设置为最小值 0
# 246 + 10 = 0
print('3: ' + str(x + y))
控制台/命令行输出:
1: [[255]]
1: [4]
2: [[110]]
2: [110]
3: [[255]]
3: [0]
通过触碰边界值,我们会发现 OpenCV 和 Numpy 的操作各不相同。
在将两个图象相加时会发现 OpenCV 函数能够提供更好的结果,所以尽可能地选择 OpenCV 函数。
这也是将图像相加,但是对图像赋予不同的权重,从而给出混合感或透明感。图像按以下等式添加:
通过在(0,1)之间改变的值, 可以用来对两幅图像或两段视频产生时间上的 画面叠化 (cross-dissolve)效果,就像在幻灯片放映和电影制作中那样(很酷吧?)(注:在幻灯片翻页时可以设置为前后页缓慢过渡以产生叠加效果,电影中经常在情节过渡时出现画面叠加效果)。
在这里,我拍了两张图片将它们混合在一起。第一图像的权重为 0.7,第二图像的权重为 0.3。cv.addWeighted() 在图像上应用以下等式。
示例代码:
# 图像的算术运算
import numpy as np
import cv2
# 图像混合
img1 = cv2.imread('../image/2.2.jpg')
print(img1.shape)
img2 = cv2.imread('../image/OpenCV.jpg')
print(img2.shape)
dst = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)
cv2.imshow('dst', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图:
注意: 这里两张图片必须要一样大小,才能够进行图像混合(图像叠加),否则会抛出:
dst = cv2. addWeighted(img1, 0.7, img2, 0.3, 0)
cv2. error: **/opencv-python/opencv-python/opencv/modules/core/src/arithm.cpp:650: error: (-209:Sizes of input arguments do not match) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function 'arithm_op'
这包括按位 AND,OR,NOT 和 XOR 运算。它们在提取图像的某一部分(我们将在后面的章节中看到)、定义和使用非矩形 ROI 等方面非常有用。下面我们将看到如何更改图像的特定区域的示例:
假如我想加一个OpenCV的 logo在一个图像上,如果只是简单的将两张图像想加,则会改变叠加处的颜色。如果进行上面所说的混叠操作,则会得到一个有透明效应的结果,但我希望得到一个不透明的logo。如果logo是一个矩形logo,那可以用上节所讲的ROI来做。但是OpenCV的logo是不规则形状的,所以用下面的bitwise操作来进行。
示例代码:
# 图像的算术运算
import numpy as np
import cv2
# 加载两张图片
img1 = cv2.imread('../image/1.jpg')
img2 = cv2.imread('../image/OpenCV.png')
# 我想在左上角放置一个logo,所以我创建了一个 ROI,并且这个ROI的宽和高为我想放置的logo的宽和高
rows, cols, channels = img2.shape
roi = img1[0:rows, 0:cols]
# 现在创建一个logo的掩码,通过对logo图像进行阈值,并对阈值结果并创建其反转掩码
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)
cv2.imshow('mask_inv', mask_inv)
cv2.waitKey(0)
# 现在使 ROI 中的徽标区域变黑
img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
cv2.imshow('img1_bg', img1_bg)
cv2.waitKey(0)
# 仅从徽标图像中获取徽标区域。
img2_fg = cv2.bitwise_and(img2, img2, mask=mask)
cv2.imshow('img2_fg', img2_fg)
cv2.waitKey(0)
# 在 ROI 中放置徽标并修改主图像
dst = cv2.add(img1_bg, img2_fg)
img1[0:rows, 0:cols] = dst
cv2.imshow('res', img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
原图:
img1:
img2:
效果图:
这里图标下面的文字是黑的,所以导致了文字在蒙版中未出现。