OpenCV竟然可以这样学!成神之路终将不远
Posted 满目星辰wwq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV竟然可以这样学!成神之路终将不远相关的知识,希望对你有一定的参考价值。
7 图像上的算术运算
7.1 目标
学习图像的几种算术运算,例如加法,减法,按位运算等。
您将学习以下功能:cv.add,cv.addWeighted等。
7.2 图像加法
您可以通过OpenCV函数cv.add() 或仅通过numpy操作res = img1 + img2 添加两个图像。两个图像应具有相同的深度和类型,或者第二个图像可以只是一个标量值。
注意:OpenCV加法和Numpy加法之间有区别。OpenCV加法是饱和运算,而Numpy加法是模运算。
示例如下:
x = np.uint8([250])
y = np.uint8([25])
print(cv.add(x, y)) # [[255]]:250+25=275=>255
print(x + y) # [19]:250+25=275%256=19
当添加两个图像时,它将更加可见。OpenCV功能将提供更好的结果。因此,始终最好坚持使用OpenCV功能。
7.3 图像融合
这也是图像加法,但是对图像赋予不同的权重,以使其具有融合或透明的感觉。根据以下等式添加图像:
通过从 从 更改,您可以在一个图像到另一个图像之间执行很酷的过渡,但是两个图像的宽高必须一致才行。
在这里,我拍摄了两个图像,将它们融合在一起。第一幅图像的权重为0.7,第二幅图像的权重为0.3。cv.addWeighted() 在图像上应用以下公式。
在这里, 被视为零。
import cv2 as cv
img1 = cv.imread('../girl02/05.jpg')
img2 = cv.imread('../girl02/06.jpg')
print('img1:{};img2:{}'.format(img1.shape, img2.shape)) # img1:(1080, 1920, 3);img2:(1080, 1920, 3)
cv.namedWindow('image', cv.WINDOW_NORMAL)
dst = cv.addWeighted(img1, 0.7, img2, 0.3, 0)
cv.imshow('image', dst)
cv.waitKey(0)
cv.destroyAllWindows()
融合结果如下:
7.4 按位运算
这包括按位 AND 、 OR 、NOT 和 XOR 操作。它们在提取图像的任何部分(我们将在后面的章节中看到)、定义和处理非矩形 ROI 等方面非常有用。 下面我们将看到一个例子,如何改变一个图像的特定区域。 我想把 OpenCV 的标志放在一个图像上面。如果我添加两个图像,它会改变颜色。如果我混合它,我得到一个透明的效果。但我希望它是不透明的。如果是一个矩形区域,我可以使用 ROI,就像我们在上一章中所做的那样。但是 OpenCV 的 logo 不是长方形的。所以你可以使用如下的按位操作来实现:
我想在图像上方放置OpenCV徽标。如果添加两个图像,它将改变颜色。如果混合它,我将获得透明效果。但我希望它不透明。如果是矩形区域,则可以像上一章一样使用ROI。但是OpenCV徽标不是矩形。因此,您可以按如下所示进行按位操作:
import cv2 as cv
import matplotlib.pyplot as plt
# 读取原图像
img = cv.imread('../girl6/14.jpg')
img = cv.cvtColor(img, cv.COLOR_BGR2RGB) # 因为opencv是BGR通道,而matplotlib是RGB通道
plt.subplot(331), plt.imshow(img, 'gray'), plt.title('img')
# 读取logo图像
logo = cv.imread('../girl6/opencv.png')
logo = cv.cvtColor(logo, cv.COLOR_BGR2RGB)
plt.subplot(332), plt.imshow(logo, 'gray'), plt.title('logo')
# 把logo放在左上角,所以创建了ROI
rows, cols, channels = logo.shape # 获取logo的行、列和通道数
roi = img[0:rows, 0:cols] # 在img图像上面截取roi大小的区域
plt.subplot(339), plt.imshow(roi, 'gray'), plt.title('roi')
# 现在创建logo的掩码,并同时创建其相反掩码
logo2gray = cv.cvtColor(logo, cv.COLOR_BGR2GRAY) # 将logo转换为灰度图像,以便二值化
plt.subplot(334), plt.imshow(logo2gray, 'gray'), plt.title('logo2gray')
# cv.threshold将灰度图二值化,ret为阈值,mask为二值化的图像,将低于第一个阈值的置为0,高于第二个阈值的置为255
ret, mask = cv.threshold(logo2gray, 200, 255, cv.THRESH_BINARY)
plt.subplot(335), plt.imshow(mask, 'gray'), plt.title('mask')
# bitwise_not是对二进制数据进行“非”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“非”操作
mask_inverse = cv.bitwise_not(mask) # cv.bitwise_not将掩码取反
plt.subplot(336), plt.imshow(mask_inverse, 'gray'), plt.title('mask_inverse')
# 现在将ROI中logo的区域涂黑
# bitwise_and是对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作
img_background = cv.bitwise_and(roi, roi, mask=mask_inverse)
plt.subplot(337), plt.imshow(img_background, 'gray'), plt.title('img_background')
# 仅从logo图像中提取logo区域
logo_foreground = cv.bitwise_and(logo, logo, mask=mask)
plt.subplot(338), plt.imshow(logo_foreground, 'gray'), plt.title('logo_foreground')
# 将logo放入ROI并修改主图像
dst = cv.add(img_background, logo_foreground)
img[0:rows, 0:cols] = dst
plt.subplot(333), plt.imshow(img, 'gray'), plt.title('dst')
plt.show()
请看下面的结果。为了更加直观的看清楚,我将其用matplotlib进行了排列,可以看清楚每一个图像的意思。
7.5 练习题
使用cv.addWeighted 函数在文件夹中创建图像的幻灯片放映,并在图像之间进行平滑过渡。
大家可以先自己想想应该怎么做,我这里做的是循环读取文件夹的图片,达到幻灯片放映效果,先上运行结果:
具体代码如下:
import cv2 as cv
import os
from PIL import Image
# 读取文件夹下图片的数量
image_dir = '../girl6/'
count = os.listdir(image_dir) # 读取image_dir文件夹中图片个数
print('count=', len(count)) # 打印文件夹中图片个数,我这里count=26
# 将图片裁剪成相同尺寸
for i in range(0, len(count)):
# 获取图片的尺寸
img = Image.open(image_dir + str(i).zfill(2) + '.jpg')
img_size = img.size # im_size[0]获取的是图片宽度,im_size[1]获取的是图片的高度
# print('图片宽度和高度分别是{}'.format(img_size))
img = img.resize((450, 288)) # 可以根据自己需求裁剪图片大小,第一个是宽度,第二个是高度
# 将裁剪的图片按照0~count保存,zfill(2)表示两位数,不够前面填0
img.save(image_dir + str(i).zfill(2) + '.jpg')
# 新建一个窗口
cv.namedWindow('image', cv.WINDOW_NORMAL)
a = 0 # 初始化权重系数
cv.waitKey(0) # 等待按键开始
# 遍历文件夹下所有图片
for i in range(0, len(count)):
image1 = cv.imread(image_dir + str(i).zfill(2) + '.jpg', 1)
image2 = cv.imread(image_dir + str(i + 1).zfill(2) + '.jpg', 1)
while a < 1.0:
dst = cv.addWeighted(image2, a, image1, 1 - a, -1)
cv.imshow('image', dst)
cv.waitKey(88) # 这里是自动跳转,也可以设置按键进行跳转
a += 0.1
a = 0 # 重新初始化权重系数
print(i)
i += 1
cv.waitKey(0) # 等待按键结束
cv.destroyAllWindows()
以上是关于OpenCV竟然可以这样学!成神之路终将不远的主要内容,如果未能解决你的问题,请参考以下文章