OpenCV竟然可以这样学!成神之路终将不远(七)

简介: OpenCV竟然可以这样学!成神之路终将不远(七)


返回目录

目录

7 图像上的算术运算

7 图像上的算术运算
7.1 目标
学习图像的几种算术运算,例如加法,减法,按位运算等。

您将学习以下功能:cv.add,cv.addWeighted等。

7.2 图像加法
您可以通过OpenCV函数cv.add() 或仅通过numpy操作res = img1 + img2 添加两个图像。两个图像应具有相同的深度和类型,或者第二个图像可以只是一个标量值。

示例如下:

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成神之路的奥秘。

顺便给我加个关注,点个赞,加个收藏,让我们一起登上神坛。

相关文章
|
机器学习/深度学习 编解码 计算机视觉
OpenCV竟然可以这样学!成神之路终将不远(十六)
OpenCV竟然可以这样学!成神之路终将不远(十六)
|
计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(十)
OpenCV竟然可以这样学!成神之路终将不远(十)
|
算法 计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(二十六)
OpenCV竟然可以这样学!成神之路终将不远(二十六)
|
算法 计算机视觉 索引
OpenCV竟然可以这样学!成神之路终将不远(二十五)
OpenCV竟然可以这样学!成神之路终将不远(二十五)
|
计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(二十四)
OpenCV竟然可以这样学!成神之路终将不远(二十四)
|
计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(二十三)
OpenCV竟然可以这样学!成神之路终将不远(二十三)
|
计算机视觉 索引 Python
OpenCV竟然可以这样学!成神之路终将不远(二十二)
OpenCV竟然可以这样学!成神之路终将不远(二十二)
|
安全 计算机视觉 索引
OpenCV竟然可以这样学!成神之路终将不远(二十一)
OpenCV竟然可以这样学!成神之路终将不远(二十一)
|
文字识别 计算机视觉 索引
OpenCV竟然可以这样学!成神之路终将不远(二十)
OpenCV竟然可以这样学!成神之路终将不远(二十)
|
定位技术 计算机视觉 Python
OpenCV竟然可以这样学!成神之路终将不远(十九)
OpenCV竟然可以这样学!成神之路终将不远(十九)