CV6 图像的算术运算(以简单的抠图为例)

简介: 功能:裁剪图片,使得两张图片的shape(或者是大小)相同。否则,会出现报错

一 图像加法


OpenCV加法和Numpy加法之间有区别。OpenCV加法是饱和运算(无论多大都只能加到max值),而Numpy加法是模运算


>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> print( cv.add(x,y) ) # 250+10 = 260 => 255
[[255]]
>>> print( x+y ) # 250+10 = 260 % 256 = 4
[4]


建议使用Opencv去添加两个图像


二 图像融合


这也是图像加法,但是对图像赋予不同的权重,以使其具有融合或透明的感觉


下面这段代码,我将两个图像融合在一起;第一幅的图像权重为0.4,第二幅图像的权重为0.6


import cv2
import numpy as np
img1 = cv2.imread('rose.jpg')
img2 = cv2.imread('homework.jpg')
img1 = cv2.resize(img1,(600,600))
dst = cv2.addWeighted(img1,0.4,img2,0.6,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()


  • cv2.resize函数

功能:裁剪图片,使得两张图片的shape(或者是大小)相同。否则,会出现报错


输入参数:1.图像名 2.想要裁剪的大小


  • cv2.addWeighted函数


功能:图片融合


输入参数:1.图像1 2.图像1的权重 3.图像2 4.图像2的权重 5.融合后,每个像素点加的标量


三 按位运算(抠图)


包括按位 AND 、 OR 、 NOT 和 XOR 操作


下面我们将看到一个例子,如何改变一个图像的特定区域。 例如:把 OpenCV 的标志放在一个图像上面


怎么实现?


在我们的PS中,如果想要将一张图片的特定部分截取出来,剪切到另外一张图片上,我们需要抠图;同样在OpenCV中,我们也需要抠图


抠图完整代码:


import cv2
import numpy as np
# 加载图片
img1 = cv2.imread('rose.jpg')
img2 = cv2.imread('homework.jpg')
# 创建ROI
rows,cols,channels = img2.shape
roi = img1[0:rows,0:cols]
# 现在创建logo的掩码,并同时创建其相反的反码
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
ret,mask = cv2.threshold(img2gray,245,255,cv2.THRESH_BINARY)
mask = cv2.bitwise_not(mask)
mask_inv = cv2.bitwise_not(mask)
# 现在将ROI中的logo涂黑
img1_bg = cv2.bitwise_and(roi,roi,mask=mask_inv)
# 仅从logo图像中提取logo区域
img2_fg = cv2.bitwise_and(img2,img2,mask = mask)
# 将logo放入ROI并修改图像
dst = cv2.add(img1_bg,img2_fg)
img1[0:rows,0:cols] = dst
cv2.imshow('res',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()


下面我们分析一下这段代码


  • 首先取出图片的shape,方便定义roi(此时两张图片的shape可以不同)


rows,cols,channels = img2.shape


  • 然后将图片灰度化,创建蒙版(官方文档上是掩码,但由于PS先入为主的关系,我更愿意叫它蒙版)


#功能:一刀切,将通道>245的像素点,置为255;反之,都置0
#输入参数:1.原图像 2.进行分类的阈值 3.高于(低于)阈值时赋予的新值 4.一个方法选择参数
mask = cv2.threshold(img2gray,245,255,cv2.THRESH_BINARY)


常用的参数有:


• cv2.THRESH_BINARY(黑白二值)

• cv2.THRESH_BINARY_INV(黑白二值反转)

• cv2.THRESH_TRUNC (得到的图像为多像素值)

• cv2.THRESH_TOZERO

• cv2.THRESH_TOZERO_INV


  • 取反操作


mask = cv2.bitwise_not(mask)
mask_inv = cv2.bitwise_not(mask)


mask的图像


e3516755509db77f.png


mask_isv的图像


d54693ec08b81b2b.png


  • 与运算


# 现在将ROI中的logo涂黑
img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)
# 仅从logo图像中提取logo区域
img2_fg = cv2.bitwise_and(img2,img2,mask = mask)


我们重点对**cv2.bitwise_and(src1,src2,dst,mask)**分析


  • src1、src2:为输入图像或标量,标量可以为单个数值或一个四元组
  • dst:可选输出变量,如果需要使用非None则要先定义,且其大小与输入变量相同
  • mask:图像蒙版,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0


img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv) 将图像涂黑,表明,这块底盘属于OpenCV Logo了。在mask_inv中,logo处的像素都是黑色的(0),与运算的时候,该像素点始终为0,所以呈现黑色


9d266a0663757a0c.png


img2_fg = cv2.bitwise_and(img2,img2,mask = mask)将图1的logo颜色抠出来;在前面的mask中,logo处的像素都是白色的,即保留输出


70c960418a026d15.png


  • 拼接


dst = cv2.add(img1_bg,img2_fg)


即将两个像素的B/G/R相加


个人感悟:OpenCV中的抠图,需要利用好蒙版,把想要抠出来的roi的蒙版都涂黑,不需要的就涂白,然后再与运算一下,就能抠出想要的地方


效果图


2dece50c123a44bea27286b1d32be148.png


还是非常的nice的~~~


截至目前,基本的图片操作已经学完了,明天开始真正入门图像处理~


代码仓库:计算机视觉OpenCV代码仓库

相关文章
|
10月前
|
存储 Cloud Native Linux
OpenCV 图像像素运算操作
OpenCV 图像像素运算操作
|
10月前
|
机器学习/深度学习 算法 计算机视觉
基于FPGA的RGB图像转化为灰度图实现,通过MATLAB进行辅助验证
基于FPGA的RGB图像转化为灰度图实现,通过MATLAB进行辅助验证
|
4月前
|
监控 算法 计算机视觉
探索图像边缘:使用Python进行轮廓检测
探索图像边缘:使用Python进行轮廓检测
95 3
|
4月前
|
计算机视觉 Python
【python版CV】图像轮廓&模板匹配
【python版CV】图像轮廓&模板匹配
|
4月前
|
计算机视觉
OpenCV图像混合
OpenCV图像混合
24 0
|
4月前
|
计算机视觉
OpenCV(十一):图像仿射变换
OpenCV(十一):图像仿射变换
94 0
|
11月前
|
C++
C++-基于参考灰度图上色GrayToColorFromOther
C++-基于参考灰度图上色GrayToColorFromOther
|
API 数据安全/隐私保护 计算机视觉
Opencv(图像处理)-基于Python-图像的基本运算-给图片加水印
Opencv(图像处理)-基于Python-图像的基本运算-给图片加水印
172 0
Opencv(图像处理)-基于Python-图像的基本运算-给图片加水印
|
计算机视觉 Python
OpenCV_03 图像的算数操作:图像的加法+图像的混合
你可以使用OpenCV的cv.add()函数把两幅图像相加,或者可以简单地通过numpy操作添加两个图像,如res = img1 + img2。两个图像应该具有相同的大小和类型,或者第二个图像可以是标量值。
77 0
|
计算机视觉
三、OpenCV之图像的混合
f0(x)、f1(x)相当于图片,通过上面的线性函数分别给两个图片的矩阵中的每个元素乘以对应的系数然后相加,即为混合后的图片。
140 0
三、OpenCV之图像的混合