> 文档中心 > OpenCV学习笔记6-图像的运算与位运算(附代码实现)

OpenCV学习笔记6-图像的运算与位运算(附代码实现)

文章目录

  • 图像的算术与位运算
  • 1 图像的算术运算
    • 1.1 图像的加法运算
    • 1.2 图像的减法运算
    • 1.3 图像的乘法运算
    • 1.4 图像的除法运算
    • 1.5 图像的融合
  • 2 OpenCV的位运算
    • 2.1 非操作
    • 2.2 与操作
    • 2.3 或操作
    • 2.4 异或操作

图像的算术与位运算

1 图像的算术运算

1.1 图像的加法运算

  • 加法运算:cv2.add(src1, src2[, dst[, mask[, dtype]]])
    • src1: 第一个图像
    • src2: 第二个图像
    • dst: 输出图像,大小和通道数与输入图像相同
    • mask: 图像掩膜
    • dtype: 输出图像数组的位深

add的规则就是两个图的对应位置元素相加,如果加完超过255,则全部变成255

图片就是矩阵, 图片的加法运算就是矩阵的加法运算, 这就要求加法运算的两张图shape必须是相同的.可以通过ndarray的切片方式取出完全一样的形状(大的切出小的形状)

# 加法运算import cv2import numpy as npcv2.namedWindow('cat_dog',cv2.WINDOW_NORMAL)cv2.resizeWindow('cat_dog',1200,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')# 查看猫狗的形状print(f'猫的形状:{cat.shape}')print(f'狗的形状:{dog.shape}')# 在做加法之前需要把图片的形状变得完全一致才行.# 可以通过ndarray的切片方式取出完全一样的形状.# 猫更大, 所以从猫里面切出狗的形状new_cat = cat[0:360, :499]print(f'猫的新形状:{new_cat.shape}')# cv2.add 加法操作要求两个图片的长宽相同, 通道数相同. (黑白图片的通道数是1,彩色图片的通道数是3)# add的规则就是两个图对应位置的元素相加, 如果超过255, 全部变成255.print('new_cat',new_cat[:3, :3])print('-------------------')print('dog',dog[:3, :3])new_img = cv2.add(new_cat, dog)print('--------------------')print('new_img',new_img[:3, :3])# cv2.imshow('new_img', new_img)cv2.imshow('cat_dog',np.hstack((new_cat,dog,new_img)))cv2.waitKey(0)cv2.destroyAllWindows()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BHDKoI3T-1648818429671)(.\img\image-20211029170232494.png)]

图片还可以和单个数字进行运算

# 图片还可以和单个数字进行运算# 每个和100进行加法运算, 超出255的数字, 会被截断, 相当于 % 256dog += 100print(dog[:3, :3])

1.2 图像的减法运算

  • 减法运算:cv2.subtract(src1, src2[, dst[, mask[, dtype]]])
    • src1: 第一个图像
    • src2: 第二个图像
    • dst: 输出图像,大小和通道数与输入图像相同
    • mask: 图像掩膜
    • dtype: 输出图像数组的位深

subtract的规则就是两个图的对应位置元素相减,如果减完小于0,则全部变成0

图片就是矩阵, 图片的减法运算就是矩阵的减法运算, 这就要求减法运算的两张图shape必须是相同的.可以通过ndarray的切片方式取出完全一样的形状(大的切出小的形状)

# 减法运算import cv2import numpy as npcv2.namedWindow('cat_dog',cv2.WINDOW_NORMAL)cv2.resizeWindow('cat_dog',1200,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')# 查看猫狗的形状print(f'猫的形状:{cat.shape}')print(f'狗的形状:{dog.shape}')# 在做减法之前需要把图片的形状变得完全一致才行.# 可以通过ndarray的切片方式取出完全一样的形状.# 猫更大, 所以从猫里面切出狗的形状new_cat = cat[0:360, :499]print(f'猫的新形状:{new_cat.shape}')# cv2.subtract 减法操作要求两个图片的长宽相同, 通道数相同. (黑白图片的通道数是1,彩色图片的通道数是3)# 减法 subtract, 对应位置的元素相减, 减完小于0, 统一变成0print('new_cat',new_cat[:3, :3])print('-------------------')print('dog',dog[:3, :3])new_img = cv2.subtract(new_cat, dog)print('--------------------')print('new_img',new_img[:3, :3])# cv2.imshow('new_img', new_img)cv2.imshow('cat_dog',np.hstack((new_cat,dog,new_img)))cv2.waitKey(0)cv2.destroyAllWindows()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2UVlb56V-1648818429672)(.\img\image-20211029170841172.png)]

1.3 图像的乘法运算

  • 乘法运算:cv2.multiply(src1, src2[, dst[, scale[, dtype]]])

    • src1: 第一个图像
    • src2: 第二个图像
    • dst: 输出图像,大小和通道数与输入图像相同
    • scale: 缩放比例
    • dtype: 输出图像数组的位深

    multiply的规则就是两个图的对应位置元素相乘,如果乘完大于255,则全部变成255

    图片就是矩阵, 图片的乘法运算就是矩阵的乘法运算, 这就要求乘法运算的两张图shape必须是相同的.可以通过ndarray的切片方式取出完全一样的形状(大的切出小的形状)

    # 乘法运算import cv2import numpy as npcv2.namedWindow('cat_dog',cv2.WINDOW_NORMAL)cv2.resizeWindow('cat_dog',1200,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')# 查看猫狗的形状print(f'猫的形状:{cat.shape}')print(f'狗的形状:{dog.shape}')# 在做乘法之前需要把图片的形状变得完全一致才行.# 可以通过ndarray的切片方式取出完全一样的形状.# 猫更大, 所以从猫里面切出狗的形状new_cat = cat[0:360, :499]print(f'猫的新形状:{new_cat.shape}')# cv2.subtract 乘法操作要求两个图片的长宽相同, 通道数相同. (黑白图片的通道数是1,彩色图片的通道数是3)print('new_cat',new_cat[:3, :3])print('-------------------')print('dog',dog[:3, :3])new_img = cv2.multiply(new_cat, dog)print('--------------------')print('new_img',new_img[:3, :3])# cv2.imshow('new_img', new_img)cv2.imshow('cat_dog',np.hstack((new_cat,dog,new_img)))cv2.waitKey(0)cv2.destroyAllWindows()

在这里插入图片描述

1.4 图像的除法运算

除法运算:cv2.divide(src1, src2[, dst[, scale[, dtype]]])

  • src1: 第一个图像
  • src2: 第二个图像
  • dst: 输出图像,大小和通道数与输入图像相同
  • scale: 缩放比例
  • dtype: 输出图像数组的位深

divide的规则就是两个图的对应位置元素相除,如果相除完的数字是小数,则进行四舍五入。

图片就是矩阵, 图片的除法运算就是矩阵的除法运算, 这就要求除法运算的两张图shape必须是相同的.可以通过ndarray的切片方式取出完全一样的形状(大的切出小的形状)

# 除法运算import cv2import numpy as npcv2.namedWindow('cat_dog',cv2.WINDOW_NORMAL)cv2.resizeWindow('cat_dog',1200,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')# 查看猫狗的形状print(f'猫的形状:{cat.shape}')print(f'狗的形状:{dog.shape}')# 在做除法之前需要把图片的形状变得完全一致才行.# 可以通过ndarray的切片方式取出完全一样的形状.# 猫更大, 所以从猫里面切出狗的形状new_cat = cat[0:360, :499]print(f'猫的新形状:{new_cat.shape}')# cv2.divide 除法操作要求两个图片的长宽相同, 通道数相同. (黑白图片的通道数是1,彩色图片的通道数是3)print('new_cat',new_cat[:3, :3])print('-------------------')print('dog',dog[:3, :3])# 除法 divide, 对应位置的元素相除new_img = cv2.divide(new_cat, dog)print('--------------------')print('new_img',new_img[:3, :3])# cv2.imshow('new_img', new_img)cv2.imshow('cat_dog',np.hstack((new_cat,dog,new_img)))cv2.waitKey(0)cv2.destroyAllWindows()

在这里插入图片描述

关于除法的0:当有元素为0且作为被除数时,divide的计算仍是有实际意义的,这点和常规的理解存在差异。

当除数为0时,其计算结果为0;如果被除数和除数都为0,结果也仍为0,有0参与的除法运算都为0。

分子为0,分母不为0:

import cv2import numpy as npcv2.namedWindow('new_img',cv2.WINDOW_NORMAL)cv2.resizeWindow('new_img',1200,400)# 全黑图片img1 = np.zeros((360,499),dtype = np.uint8)print('img1',img1[:3])# 全白图片img2 = img1[:] +255print('img2',img2[:3])img =cv2.divide(img1,img2)print('img',img[:3])cv2.imshow('new_img',np.hstack((img1,img2,img)))cv2.waitKey()cv2.destroyAllWindows()

在这里插入图片描述

分子不为0,分母为0:

import cv2import numpy as npcv2.namedWindow('new_img',cv2.WINDOW_NORMAL)cv2.resizeWindow('new_img',1200,400)# 全黑图片img1 = np.zeros((360,499),dtype = np.uint8)print('img1',img1[:3])# 全白图片img2 = img1[:] +255print('img2',img2[:3])img =cv2.divide(img2,img1)print('img',img[:3])cv2.imshow('new_img',np.hstack((img1,img2,img)))cv2.waitKey()cv2.destroyAllWindows()

在这里插入图片描述

分子分母均为0:

import cv2import numpy as npcv2.namedWindow('new_img',cv2.WINDOW_NORMAL)cv2.resizeWindow('new_img',1200,400)# 全黑图片img1 = np.zeros((360,499),dtype = np.uint8)print('img1',img1[:3])# 全白图片img2 = img1[:]print('img2',img2[:3])img =cv2.divide(img1,img2)print('img',img[:3])cv2.imshow('new_img',np.hstack((img1,img2,img)))cv2.waitKey()cv2.destroyAllWindows()

在这里插入图片描述

1.5 图像的融合

  • cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])

    • src1,src2 需要融合相加的两个大小和通道数相等的图像
    • alpha src1的权重
    • beta src2的权重
    • gamma 是偏差
    • dst 输出图像
    • dtype 输出图像数组的位深
  • 图片的融合操作不是简单的运算,而是相当于对图片进行线性运算 ,即w1* x1 + w2 * x2 + b. 其中alpha是第一个图像的权重参数, beta是第二个图像的权重参数, gamma是偏差.

    # 图像的融合# 不是简单的加法了. 相当于拿图片做了线性运算. new_img = img1 * w1 + img2 * w2 + biasimport cv2import numpy as npcv2.namedWindow('new_img',cv2.WINDOW_NORMAL)cv2.resizeWindow('new_img',1200,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')new_cat = cat[0:360, :499]# 相当于new_img = new_cat * 0.4 + dog * 0.6 + 0new_img = cv2.addWeighted(new_cat, 0.4, dog, 0.6, 0)cv2.imshow('new_img', np.hstack((new_cat,dog,new_img)))cv2.waitKey(0)cv2.destroyAllWindows()

在这里插入图片描述

2 OpenCV的位运算

2.1 非操作

非操作的效果就相当于是用 255 - img

  • cv2.bitwise_not(src[, dst[, mask]])

    • src 输入图像
    • dst 输出图像
    • mask 图像掩膜
    import cv2import numpy as npcv2.namedWindow('not',cv2.WINDOW_NORMAL)cv2.resizeWindow('not',1200,400)# 读取图片cat = cv2.imread('./cat.jpeg')print('cat',cat[:2, :2])# 非操作 相当于 255 - catcat_not = cv2.bitwise_not(cat)print('cat_not',cat_not[:2, :2])# 再做一次非操作 相当于回到原图cat_not_not = cv2.bitwise_not(cat_not)print('cat_not_not',cat_not_not[:2,:2])cv2.imshow('not', np.hstack((cat, cat_not,cat_not_not)))cv2.waitKey(0)cv2.destroyAllWindows()

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-amBryCqg-1648818429673)(.\img\image-20211029173229993.png)]

2.2 与操作

与操作就是图片对应位置元素进行与操作. 表现出来的效果就是黑和黑与还是黑, 白和白与还是白.(要转换成二进制来算,1&1=1,1&0=0,0&0=0)

  • cv2.bitwise_and(src1, src2[, dst[, mask]]

    • src1 输入的第一个图像
    • src2 输入的第二个图像
    • dst 输出图像
    • mask 图像掩膜
    import cv2import numpy as npcv2.namedWindow('and',cv2.WINDOW_NORMAL)cv2.resizeWindow('and',800,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')print('dog',dog[:2,:2])new_cat = cat[0:360, :499]print('new_cat',new_cat[:2, :2])# 两个图片对应位置的元素进行与操作.cat_and_dog = cv2.bitwise_and(new_cat, dog)print('cat_and_dog',cat_and_dog[:2,:2])cv2.imshow('and', np.hstack((new_cat,cat_and_dog)))cv2.waitKey(0)cv2.destroyAllWindows()

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZaUWntuw-1648818429673)(.\img\image-20211029173259558.png)]

2.3 或操作

或操作就是图片对应位置元素进行或操作. (要转换成二进制来算,1|1=1,1|0=1,0|0=0)

  • cv2.bitwise_or(src1, src2[, dst[, mask]]
    • src1 输入的第一个图像
    • src2 输入的第二个图像
    • dst 输出图像
    • mask 图像掩膜
import cv2import numpy as npcv2.namedWindow('or',cv2.WINDOW_NORMAL)cv2.resizeWindow('or',800,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')print('dog',dog[:2,:2])new_cat = cat[0:360, :499]print('new_cat',new_cat[:2, :2])# 两个图片对应位置的元素进行与操作.cat_or_dog = cv2.bitwise_or(new_cat, dog)print('cat_or_dog',cat_or_dog[:2,:2])cv2.imshow('or', np.hstack((new_cat,cat_or_dog)))cv2.waitKey(0)cv2.destroyAllWindows()

在这里插入图片描述

2.4 异或操作

异或操作就是图片对应位置元素进行异或操作. (要转换成二进制来算,对应元素相同取0,相异取1)

例如:4 = 0100;3 = 0011。4 ^ 3 = 0111 = 7

  • cv2.bitwise_xor(src1, src2[, dst[, mask]]

    • src1 输入的第一个图像
    • src2 输入的第二个图像
    • dst 输出图像
    • mask 图像掩膜
    import cv2import numpy as npcv2.namedWindow('xor',cv2.WINDOW_NORMAL)cv2.resizeWindow('xor',800,400)# 读取图片cat = cv2.imread('./cat.jpeg')dog = cv2.imread('./dog.jpeg')print('dog',dog[:2,:2])new_cat = cat[0:360, :499]print('new_cat',new_cat[:2, :2])# 两个图片对应位置的元素进行与操作.cat_xor_dog = cv2.bitwise_xor(new_cat, dog)print('cat_xor_dog',cat_xor_dog[:2,:2])cv2.imshow('xor', np.hstack((new_cat,cat_xor_dog)))cv2.waitKey(0)cv2.destroyAllWindows()

在这里插入图片描述
附OpenCV目录:OpenCV总目录学习笔记

智科专业小白,写博文不容易,如果喜欢的话可以点个赞哦!OpenCV学习笔记6-图像的运算与位运算(附代码实现)

神唱ktv下载