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 cv2
import numpy as np

cv2.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()

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

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

1.2 图像的减法运算

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

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

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

# 减法运算
import cv2
import numpy as np

cv2.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, 统一变成0
print('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()

1.3 图像的乘法运算

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

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

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

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

    # 乘法运算
    import cv2
    import numpy as np
    
    cv2.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()
    

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

1.4 图像的除法运算

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

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

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

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

# 除法运算
import cv2
import numpy as np

cv2.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 cv2
import numpy as np

cv2.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[:] +255
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()

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

分子不为0,分母为0:

import cv2
import numpy as np

cv2.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[:] +255
print('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()

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

分子分母均为0:

import cv2
import numpy as np

cv2.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()

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

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 + bias
    import cv2
    import numpy as np
    
    cv2.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 + 0
    new_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 cv2
    import numpy as np
    
    cv2.namedWindow('not',cv2.WINDOW_NORMAL)
    cv2.resizeWindow('not',1200,400)
    
    # 读取图片
    cat = cv2.imread('./cat.jpeg')
    print('cat',cat[:2, :2])
    
    # 非操作 相当于 255 - cat
    cat_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()
    

2.2 与操作

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

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

    • src1 输入的第一个图像
    • src2 输入的第二个图像
    • dst 输出图像
    • mask 图像掩膜
    import cv2
    import numpy as np
    
    cv2.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()
    

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

2.3 或操作

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

  • cv2.bitwise_or(src1, src2[, dst[, mask]]
    • src1 输入的第一个图像
    • src2 输入的第二个图像
    • dst 输出图像
    • mask 图像掩膜
import cv2
import numpy as np

cv2.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()

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

2.4 异或操作

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

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

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

    • src1 输入的第一个图像
    • src2 输入的第二个图像
    • dst 输出图像
    • mask 图像掩膜
    import cv2
    import numpy as np
    
    cv2.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总目录学习笔记

智科专业小白,写博文不容易,如果喜欢的话可以点个赞哦!请添加图片描述

你可能感兴趣的:(机器视觉,计算机视觉,python,opencv,人工智能)