文章目录
- 图像的算术与位运算
- 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()
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()
分子不为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()
分子分母均为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()
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()
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()
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()
智科专业小白,写博文不容易,如果喜欢的话可以点个赞哦!