云南省滇中引水工程建设管理局网站,专业的医疗网站建设,软件开发各阶段时间比例,ui设计师mike个人网站文章结构 掩模图像的加法运算图像的位运算按位与运算按位或运算按位取反运算按位异或运算图像位运算的运用 合并图像加权和覆盖 掩模
当计算机处理图像时#xff0c;有些内容需要处理#xff0c;有些内容不需要处理。能够覆盖原始图像#xff0c;仅暴露原始图像“感兴趣区域… 文章结构 掩模图像的加法运算图像的位运算按位与运算按位或运算按位取反运算按位异或运算图像位运算的运用 合并图像加权和覆盖 掩模
当计算机处理图像时有些内容需要处理有些内容不需要处理。能够覆盖原始图像仅暴露原始图像“感兴趣区域”ROI的模板图像就叫做掩模。
掩模mask也叫做掩码在程序中用二值图像来表示0值纯黑区域表示被遮盖的部分255值纯白区域表示暴露的部分某些场景下也会用0和1当作掩模的值。示意图如下
在使用OpenCV处理图像时通常使用NumPy库提供的方法来创建掩模图像。 实例1 创建3通道掩模图像 利用NumPy库的zeros()方法创建一幅掩模图像 import cv2
import numpy as np# 创建宽150、高150、3通道、像素类型为无符号8位数字的零值图像
mask np.zeros((150, 150, 3), np.uint8)
mask[50:100, 20:80, :] 255; # 50~100行、20~80列的像素改为纯白像素
cv2.imshow(mask1, mask) # 展示掩模
mask[:, :, :] 255; # 全部改为纯白像素
mask[50:100, 20:80, :] 0; # 50~100行、20~80列的像素改为纯黑像素
cv2.imshow(mask2, mask) # 展示掩模
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下
图像的加法运算
图像中每一个像素都有用整数表示的像素值两幅图像相加就是让相同位置像素值相加最后将计算结果按照原位置组成一幅新图像。示意图如下
dst cv2.add(src1, src2, mask, dtype)src1 第一幅图像src2 第二幅图像mask可选掩模建议使用默认值dtype可选图像深度建议使用默认值dst 相加之后的结果图像。如果相加之后值的结果大于255则取255 实例2 分别使用“”和add()方法计算图像和 import cv2img cv2.imread(beach.jpg) # 读取原始图像
sum1 img img # 使用运算符相加
sum2 cv2.add(img, img) # 使用方法相加
cv2.imshow(img, img) # 展示原图
cv2.imshow(sum1, sum1) # 展示运算符相加结果
cv2.imshow(sum2, sum2) # 展示方法相加结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 从结果中可以看出“”运算符的计算结果如果超出了255就会取相加和除以255的余数也就是取模运算像素值相加之后反而变得更小了由浅色变成了深色而add()方法的计算结果如果超过了255就取值255很多浅颜色像素彻底变成了纯白色。
当使用与“”运算符相对的“-”运算符操作一幅图像时又会呈现怎样的视觉效果呢首先先来了解一下相片底片的颜色与图像的原色之间有哪些联系。
相片底片的颜色与图像的原色是正好相反的即反色又被称为补色红色的补色是绿色蓝色的补色是橙色黄色的补色是紫色。
下面通过一个实例演示如何使用“-”运算符得到图像底片的效果。 实例3 显示图像底片的效果 图像的反色与原色叠加后可以变为纯白色。因此为了得到一幅图像的底片效果只需用255纯白色减去这幅图像中的每一个像素的BGR值即可。 import cv2img cv2.imread(3.png) # 读取当前项目文件夹下的图像
cameraFilm 255 - img # 用纯白色减去图像的原色得到图像的反色从而得到这幅图像的底片效果
cv2.imshow(img, img) # 显示图像
cv2.imshow(cameraFilm, cameraFilm) # 窗口显示图像底片的效果
cv2.waitKey() # 按下键盘上的任意按键后
cv2.destroyAllWindows() # 销毁显示图像的所有窗口结果如下 下面通过一个实例演示如何使用加运算修改图像颜色。 实例4 模拟三色光叠加得白光 import cv2
import numpy as npimg1 np.zeros((150, 150, 3), np.uint8) # 创建150*150的0值图像
img1[:, :, 0] 255 # 蓝色通道赋予最大值
img2 np.zeros((150, 150, 3), np.uint8)
img2[:, :, 1] 255 # 绿色通道赋予最大值
img3 np.zeros((150, 150, 3), np.uint8)
img3[:, :, 2] 255 # 红色通道赋予最大值
cv2.imshow(1, img1) # 展示蓝色图像
cv2.imshow(2, img2) # 展示绿色图像
cv2.imshow(3, img3) # 展示红色图像
img cv2.add(img1, img2) # 蓝色 绿色 青色
cv2.imshow(12, img) # 展示蓝色加绿色的结果
img cv2.add(img, img3) # 红色 青色 白色
cv2.imshow(123, img) # 展示三色图像相加的结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 图像的加运算中也可以使用掩模。 实例5 利用掩模遮盖相加结果 创建纯蓝和纯红这两幅图像使用add()方法对两幅图像进行加运算并在方法中添加一个掩模。 import cv2
import numpy as npimg1 np.zeros((150, 150, 3), np.uint8) # 创建150*150的0值图像
img1[:, :, 0] 255 # 蓝色通道赋予最大值
img2 np.zeros((150, 150, 3), np.uint8)
img2[:, :, 2] 255 # 红色通道赋予最大值img cv2.add(img1, img2) # 蓝色 红色 洋红色
cv2.imshow(no mask, img) # 展示相加的结果m np.zeros((150, 150, 1), np.uint8) # 创建掩模
m[50:100, 50:100, :] 255 # 掩模中央位置为纯白色
cv2.imshow(mask, m) # 展示掩模img cv2.add(img1, img2, maskm) # 相加时使用掩模
cv2.imshow(use mask, img) # 展示相加的结果cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 图像的位运算
图像由像素组成每个像素可以用十进制整数表示十进制整数又可以转化为二进制数所以图像也可以做位运算。OpenCV提供了几种常用的位运算方法
方法含义cv2.bitwise_and()按位与cv2.bitwise_or()按位或cv2.bitwise_not()按位取反cv2.bitwise_xor()按位异或
按位与运算
与运算就是按照二进制位进行判断如果同一位的数字都是1则运算结果的相同位数字取1否则取0。OpenCV提供 bitwise_and() 方法来对图像做位与运算。
dst cv2.bitwise_and(src1, src2, mask)src1 第一幅图像src2 第二幅图像mask可选掩模dst 与运算之后的结果图像
图像做与运算时会把每一个像素值都转为二进制数然后让两幅图像相同位置的两个像素值做与运算最后把运算结果保存在新图像的相同位置上。运算过程如下 与运算有两个特点
如果某像素与纯白色像素做与运算结果仍然是某像素的原值如果某像素与纯黑色像素做与运算结果为纯黑像素
由此可以得出如果原图像与掩模进行与运算原图像仅会保留掩模中白色区域所覆盖的内容其他区域全部变成黑色。 实例6 花图像与十字掩模做与运算 创建一个掩模在掩模中央保留一个十字形的白色区域让掩模与花图像做与运算查看运算之后的结果。 import cv2
import numpy as npflower cv2.imread(3.png) # 花原始图像
mask np.zeros(flower.shape, np.uint8) # 与花图像大小相等的掩模图像
mask[135:235, :, :] 255 # 横着的白色区域
mask[:, 102:203, :] 255 # 竖着的白色区域
img cv2.bitwise_and(flower, mask) # 与运算
cv2.imshow(flower, flower) # 展示花图像
cv2.imshow(mask, mask) # 展示掩模图像
cv2.imshow(img, img) # 展示与运算结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下
按位或运算
如果同一位的数字都是0则运算结果的相同位数字取0否则取1。OpenCV提供bitwise_or()方法来对图像做或运算。
dst cv2.bitwise_or(src1, src2, mask)src1 第一幅图像src2 第二幅图像mask可选掩模dst 或运算之后的结果图像
运算过程如下 或运算有两个特点
如果某像素与纯白色像素做或运算结果为纯白色像素如果某像素与纯黑色像素做或运算结果仍然是某像素的原值
由此可以得出如果原图像与掩模进行或运算原图像仅会保留掩模中黑色区域所覆盖的内容其他区域全部变成白色。 实例7 花图像与十字掩模做或运算 创建一个掩模在掩模中央保留一个十字形的白色区域让掩模与花图像做或运算。 import cv2
import numpy as npflower cv2.imread(3.png) # 花原始图像
mask np.zeros(flower.shape, np.uint8) # 与花图像大小相等的掩模图像
mask[135:235, :, :] 255 # 横着的白色区域
mask[:, 102:203, :] 255 # 竖着的白色区域
img cv2.bitwise_or(flower, mask) # 或运算
cv2.imshow(flower, flower) # 展示花图像
cv2.imshow(mask, mask) # 展示掩模图像
cv2.imshow(img, img) # 展示或运算结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 按位取反运算
取反运算是一种单目运算仅需一个数字参与运算就可以得出结果。如果运算数某位上数字是0则运算结果的相同位的数字就取1如果这一位的数字是1则运算结果的相同为的数字取0。
dst cv2.bitwise_not(src, mask)src 参与运算的图像mask可选掩模dst 取反运算之后结果图像
运算过程如下 实例8 对花图像进行取反运算 import cv2flower cv2.imread(3.png) # 花原始图像
img cv2.bitwise_not(flower) # 取反运算
cv2.imshow(flower, flower) # 展示花图像
cv2.imshow(img, img) # 展示取反运算结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 按位异或运算
如果两个运算数同一位上的数字相同则运算结果的相同位数字取0否则取1。
dst cv2.bitwise_xor(src, mask)src 参与运算的图像mask可选掩模dst 异或运算之后的结果图像 异或运算有两个特点
如果某像素与纯白色像素做异或运算结果为原像素的取反结果如果某像素与纯黑色像素做异或运算结果仍然是某像素的原值
由此可以得出如果原图像与掩模进行异或运算掩模白色区域所覆盖的内容呈现取反结果黑色区域覆盖的内容保持不变。 实例9 花图像与十字掩模做异或运算 import cv2
import numpy as npflower cv2.imread(3.png) # 花原始图像
m np.zeros(flower.shape, np.uint8) # 与花图像大小相等的0值图像
m[135:235, :, :] 255 # 横着的白色区域
m[:, 102:203, :] 255 # 竖着的白色区域
img cv2.bitwise_xor(flower, m) # 两张图像做异或运算
cv2.imshow(flower, flower) # 展示花图像
cv2.imshow(mask, m) # 展示零值图像
cv2.imshow(img, img) # 展示异或运算结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 异或运算还有一个特点执行一次异或运算得到一个结果再对这个结果执行第二次异或运算则又会还原成最初的值。利用这个特点可以实现对图像内容的加密和解密。 实例10 对图像进行加密、解密 利用random.randint()方法创建一个随机像素值图像作为密钥图像让密钥图像与原始图像做异或运算得出加密运算再使用密钥图像对加密图像进行解密。 import cv2
import numpy as npdef encode(img, img_key): # 加密、解密方法result img cv2.bitwise_xor(img, img_key) # 两图像做异或运算return resultflower cv2.imread(3.png) # 花原始图像
rows, colmns, channel flower.shape # 原图像的行数、列数和通道数
# 创建与花图像大小相等的随机像素图像作为密钥图像
img_key np.random.randint(0, 256, (rows, colmns, 3), np.uint8)cv2.imshow(1, flower) # 展示花图像
cv2.imshow(2, img_key) # 展示秘钥图像result encode(flower, img_key) # 对花图像进行加密
cv2.imshow(3, result) # 展示加密图像
result encode(result, img_key) # 对花图像进行解密
cv2.imshow(4, result) # 展示加密图像
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 图像位运算的运用 实例11 粘贴带透明区域的图像 本实例要实现的是将一幅带透明区域的图像粘贴到一幅不透明图像的指定位置 要明确两个问题的处理方法一个是实现”粘贴“的效果后让图1中透明元素呈现纯黑色的视觉效果另一个是如果图1太大超出了图2的宽、高那么对超出的像素不做处理。
import cv2
import numpy as npdef overlay_img(background_img, prospect_img, img_over_x, img_over_y):back_r, back_c, _ background_img.shape # 背景图像行数、列数if img_over_xback_c or img_over_x0 or img_over_yback_r or img_over_y0:print(前景图不在背景图范围内)return background_imgpro_r, pro_c, _ prospect_img.shape # 前景图像行数、列数if img_over_x pro_c back_c: # 如果水平方向展示不全pro_c back_c - img_over_x # 截取前景图的列数prospect_img prospect_img[:, 0:pro_c, :] # 截取前景图if img_over_y pro_r back_r: # 如果垂直方向展示不全pro_r back_r - img_over_y # 截取前景图的行数prospect_img prospect_img[0:pro_r, :, :] # 截取前景图# 前景图转为4通道图像prospect_img cv2.cvtColor(prospect_img, cv2.COLOR_BGR2BGRA)# 与背景图像等大的临时前景图层prospect_tmp np.zeros((back_r, back_c, 4), np.uint8)# 前景图像放到前景图层里prospect_tmp[img_over_y:img_over_y pro_r,img_over_x: img_over_x pro_c, :] prospect_img# 前景图阈值处理_, binary cv2.threshold(prospect_img, 254, 255, cv2.THRESH_BINARY)prospect_mask np.zeros((pro_r, pro_c, 1), np.uint8) # 单通道前景图像掩模prospect_mask[:, :, 0] binary[:, :, 3] # 不透明像素的值作为掩模的值mask np.zeros((back_r, back_c, 1), np.uint8) # 单通道前景图层的掩模# 将前景图像掩模按照坐标参数放到前景图层掩模中mask[img_over_y:img_over_y prospect_mask.shape[0],img_over_x: img_over_x prospect_mask.shape[1]] prospect_maskmask_not cv2.bitwise_not(mask) # 前景图层掩模取反# 前景图层与前景掩模做与运算抠出前景图有效内容prospect_tmp cv2.bitwise_and(prospect_tmp, prospect_tmp, maskmask)# 背景图像与取反掩模做与运算清除前景图所占区域的像素值background_img cv2.bitwise_and(background_img, background_img, maskmask_not)# 前景图层转为三通道图像prospect_tmp cv2.cvtColor(prospect_tmp, cv2.COLOR_BGRA2BGR)return prospect_tmp background_img # 前景图层与背景图像相加合并img cv2.imread(beach.jpg) # 读取当前项目目录下的图像作为“背景图像”
img_over cv2.imread(star.png) # 读取带透明区域的图像作为“覆盖图像”
img_over_x 55 # 覆盖图像在背景图像上的横坐标
img_over_y 3 # 覆盖图像在背景图像上的纵坐标
# 显示粘贴“覆盖图像”后的“背景图像”
cv2.imshow(result, overlay_img(img, img_over, img_over_x, img_over_y))
cv2.waitKey() # 通过按下键盘上的按键
cv2.destroyAllWindows() # 销毁正在显示的窗口结果如下 合并图像
合并图像分两种情况
两幅图像融合在一起每幅图像提供一部分内容将这些内容拼接程一幅图像
OpenCV分别用加权和与覆盖两种方式来满足上述需求。
加权和
多次曝光技术是在一张胶片上拍摄几个影响最后冲印出的相片会同时具有多个影像的信息。
OpenCV通过计算加权和的方式按照不同的权重取两幅图像的像素之和最后组成新图像。加权和不会像纯加法运算那样让图像丢失信息而是尽量在保留原有图像信息的基础上把两幅图像融合到一起。
dst cv2.addWeighted(src1, alpha, src2, beta, gamma)src1 第一幅图像alpha 第一幅图像的权重src2 第二幅图像beta 第二幅图像的权重gamma 在和结果上添加的标量。该值越大结果图像越亮相反则越暗。可以是负数。dst 叠加之后的图像 实例12 利用计算加权和的方式实现多次曝光效果 读取两幅不同的风景图像使用addWeighted()方法计算两幅图像的加权和两幅图像的权重都为0.6标量为0查看处理之后的图像是否为多次曝光结果。 import cv2sun cv2.imread(sunset.jpg) # 日落原始图像
beach cv2.imread(beach.jpg) # 沙滩原始图像
rows, colmns, channel sun.shape # 日落图像的行数、列数和通道数
beach cv2.resize(beach, (colmns, rows)) # 沙滩图像缩放成日落图像大小
img cv2.addWeighted(sun, 0.6, beach, 0.6, 0) # 计算两幅图像加权和
cv2.imshow(sun, sun) # 展示日落图像
cv2.imshow(beach, beach) # 展示沙滩图像
cv2.imshow(addWeighted, img) # 展示加权和图像
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下 实例13 为图像添加水印效果 import cv2image cv2.imread(3.png) # 读取当前项目文件夹下的主图图像
website cv2.imread(website.png) # 读取当前项目文件夹下的网址图像
# 将网址图像由BGR色彩空间转换为GRAY色彩空间
website_gray cv2.cvtColor(website, cv2.COLOR_BGR2GRAY)
rows, cols website_gray.shape # 获取转换为GRAY色彩空间的网址图像的行像素和列像素
# 网址图像的左上角在主图图像内的位置
dx, dy 272, 71
# 根据网址图像的左上角在主图图像内的位置以及网址图像的行像素和列像素
# 把主图图像内的相应区域定义为感兴趣区域roi
roi image[dx:dx rows, dy:dy cols]
# 将网址图像与主图图像的感兴趣区域进行图像加权和运算
add cv2.addWeighted(website, 0.2, roi, 1.0, 1)
# 把进行图像加权和运算后的结果混合到主图图像内
image[dx:dx rows, dy:dy cols] add
cv2.imshow(result, image) # 窗口显示网址图像与主图图像混合后的图像
cv2.waitKey() # 按下键盘上的任意按键后
cv2.destroyAllWindows() # 销毁显示图像的所有窗口结果如下 覆盖
覆盖图像就是直接把前景图像显示在背景图像中前景图像会挡住背景图像。覆盖之后背景图像会丢失信息不会出现加权和那样的多次曝光的效果。
OpenCV没有提供覆盖操作的方法我们可以直接用修改图像像素值的方式实现图像的覆盖、拼接效果从A图像中取像素值直接复制给B图像的像素这样就能在B图像中看到A图像的信息了。实例13中的
image[dx:dx rows, dy:dy cols] add这行代码就是一个例子直接将像素赋值简单粗暴。
如果前景图像时4通道含alpha通道图像就不能使用上面例子中直接替换整个区域的方式覆盖背景图像了。因为前景图像中有透明的像素透明的像素不应该挡住背景所以在给背景图像像素赋值时应该排除所有透明的前景像素。 实例14 拼接禁止吸烟图像 不要把前景图像的透明像素覆盖到背景图像上。覆盖之前要遍历前景图像中的每一个像素如果像素的alpha通道值为0表示该像素是透明像素就要停止操作该像素。 import cv2# 拼接图像方法
def overlay_img(img, img_over, img_over_x, img_over_y):img_h, img_w, img_p img.shape # 背景图像宽、高、通道数img_over_h, img_over_w, img_over_c img_over.shape # 覆盖图像宽、高、通道数if img_over_c 3: # 通道数小于等于3img_over cv2.cvtColor(img_over, cv2.COLOR_BGR2BGRA) # 转换成4通道图像for w in range(0, img_over_w): # 遍历列for h in range(0, img_over_h): # 遍历行if img_over[h, w, 3] ! 0: # 如果不是全透明的像素for c in range(0, 3): # 遍历三个通道x img_over_x w # 覆盖像素的横坐标y img_over_y h # 覆盖像素的纵坐标if x img_w or y img_h: # 如果坐标超出最大宽高breakimg[y, x, c] img_over[h, w, c] # 覆盖像素return imgsmoking cv2.imread(smoking.png, cv2.IMREAD_UNCHANGED) # 吸烟图像保持原格式
no_img cv2.imread(no.png, cv2.IMREAD_UNCHANGED) # 禁止图像保持原格式
cv2.imshow(smoking, smoking) # 展示禁止图像
img overlay_img(smoking, no_img, 95, 90) # 将禁止图像覆盖到吸烟图像之上
cv2.imshow(no smoking, img) # 展示覆盖结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体结果如下;