图像的算术与位运算
5.1 图像运算之加减乘除
图像的加法运算
- add(src1, src2[, dst[, mask[, dtype]]]):OpenCV使用add来执行图像的加法运算
图片就是矩阵,图片的加法运算就是矩阵的加法运算,这就要求加法运算的两张图片的shape必须是相同的。
代码语言:javascript复制# 图片加法
import cv2
import numpy as np
# 读取图片
cat = cv2.imread('./cat.jpg') # shape (100, 100, 3)
dog = cv2.imread('./dog.jpg') # shape (100, 100, 3)
# 加法要求两张图片大小一致
print(cat.shape)
print(dog.shape)
# 在做加法之前需要把图片的形状变为一致
# 可以通过ndarray的切片方式取出完全一样的形状
# 从0切到100可以用[0:100]或[:100]左闭右开
new_cat = cat[:100, :100]
# cv2.add 加法操作要求两个图片的长宽、通道数相同
new_img = cv2.add(new_cat, dog)
cv2.imshow('img', np.hstack((new_cat, dog, new_img)))
cv2.waitKey(0)
cv2.destroyAllWindows()
add的规则就是两个图对应位置的元素相加,如果超过255,则回滚至255。
图片还可以和单个数字进行运算:
代码语言:javascript复制# 单个数值加减
import cv2
import numpy as np
cat = cv2.imread('./cat.jpg') # shape (100, 100, 3)
dog = cv2.imread('./dog.jpg') # shape (100, 100, 3)
# 超出255的值,会使用 (dog 100) % 255 来计算
new_dog = dog 100
cv2.imshow('img', np.hstack((dog, new_dog)))
cv2.waitKey(0)
cv2.destroyAllWindows()
图像的减法运算
- subtract(src1, src2[, dst[, mask[, dtype]]]):OpenCV使用subtract来执行图像的减法运算
# 图片减法
import cv2
import numpy as np
# 读取图片
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
new_img = cv2.subtract(cat, dog)
cv2.imshow('img', np.hstack((cat, dog, new_img)))
cv2.waitKey(0)
cv2.destroyAllWindows()
subtract的规则就是两个图对应位置的元素相减,如果小于0,则回滚至0。
图像的乘法运算
- multiply(src1, src2)
# 图片乘法
import cv2
import numpy as np
# 读取图片
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
new_img = cv2.multiply(cat, dog)
cv2.imshow('img', np.hstack((cat, dog, new_img)))
cv2.waitKey(0)
cv2.destroyAllWindows()
图像的除法运算
- divide(src1, src2)
# 图片除法
import cv2
import numpy as np
# 读取图片
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
new_img = cv2.divide(cat, dog)
cv2.imshow('img', np.hstack((cat, dog, new_img)))
cv2.waitKey(0)
cv2.destroyAllWindows()
5.2 图片的融合
- cv2.addWeighted(src1, alpha, src2, beta, gamma)
- 图片的融合操作相当于对图片进行线性运算
α∗img1 β∗img2 γalpha * img_1 beta * img_2 gamma α∗img1 β∗img2 γ
- 其中alpha是第一个权重参数,beta是第二个权重参数,gamma是偏差(bias)
# 图像的融合
# 不是简单的加法运算,相当于将图片进行了一次线性运算
# 通过调整图片的权重来调整融合图片中哪一张图所占的比重更大一些
import cv2
import numpy as np
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
new_img = cv2.addWeighted(cat, 0.4, dog, 0.6, 0)
cv2.imshow('img', np.hstack((cat, dog, new_img)))
cv2.waitKey(0)
cv2.destroyAllWindows()
5.3 OpenCV的位运算
非操作
- bitwise_not(src)
# OpenCV的逻辑运算 —— 与或非 异或
# OpenCV中的逻辑运算就是对应位置的元素进行 与或非 异或 运算
import cv2
import numpy as np
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
# 非操作
cat_not = cv2.bitwise_not(cat)
cv2.imshow('not', np.hstack((cat, cat_not)))
print(cat[:2, :2])
print(cat_not[:2, :2])
cv2.waitKey(0)
cv2.destroyAllWindows()
非运算的本质就是用255去做减法得到黑白反转的图片:
代码语言:javascript复制output >>
[[[25 29 30]
[42 46 47]]
[[30 33 37]
[41 46 47]]]
[[[230 226 225]
[213 209 208]]
[[225 222 218]
[214 209 208]]]
与操作
- bitwise_and(src1, src2)
# 与操作
# 204 & 213 二进制后逻辑运算再转为十进制
# OpenCV中的非,0反过来是255
import cv2
import numpy as np
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
cat_and = cv2.bitwise_and(cat, dog)
cv2.imshow('not', np.hstack((cat, dog, cat_and)))
cv2.waitKey(0)
cv2.destroyAllWindows()
与操作的结果永远小于等于两个数,所以与操作后图片颜色会整体变暗。
或操作
- bitwise_or(src1, src2)
# 或操作
import cv2
import numpy as np
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
cat_or = cv2.bitwise_or(cat, dog)
cv2.imshow('not', np.hstack((cat, dog, cat_or)))
cv2.waitKey(0)
cv2.destroyAllWindows()
或操作的结果永远大于等于两个数,所以与操作后图片颜色会整体变亮,超过255则回滚至255。
异或操作
- bitwise_xor(src1, src2)
# 异或操作
import cv2
import numpy as np
cat = cv2.imread('./cat.jpg')
dog = cv2.imread('./dog.jpg')
cat_xor = cv2.bitwise_xor(cat, dog)
cv2.imshow('not', np.hstack((cat, dog, cat_xor)))
cv2.waitKey(0)
cv2.destroyAllWindows()
5.4 resize用法
图像的放大与缩小
- resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
- src:要放缩的图片;
- dsize:缩放之后的图片大小,元组或列表表示;
- dst:可选参数,缩放之后的输出图片;
- fx、fy:x轴和y轴的缩放比,即宽度和高度的缩放比;
- interpolation:插值算法,主要有以下几种:
- INTER_NEAREST:邻近插值,速度快,效果差(模糊、锯齿状);
- INTER_LINEAR:双线型插值,使用原图中的4个点进行插值,默认;
- INTER_CUBIC:三次插值,原图中的16个点;
- INTER_AREA:区域插值,效果最好,计算时间最长;
# 图像的放大与缩小
import cv2
import numpy as np
# 导入图片
dog = cv2.imread('./dog.jpg')
# x,y放大1.5倍
new_dog = cv2.resize(dog, dsize=(150, 150), interpolation=cv2.INTER_NEAREST)
new_dog2 = cv2.resize(dog, (150, 150), interpolation=cv2.INTER_LINEAR) # 默认效果
new_dog3 = cv2.resize(dog, (150, 150), interpolation=cv2.INTER_CUBIC)
new_dog4 = cv2.resize(dog, (150, 150), interpolation=cv2.INTER_AREA)
# 横向纵向拉伸
new_dog_xy = cv2.resize(dog, dsize=None, fx=0.5, fy=0.5, interpolation=cv2.INTER_LINEAR)
cv2.imshow('dog', np.hstack((new_dog, new_dog2, new_dog3, new_dog4)))
cv2.imshow('dog_xy', new_dog_xy)
cv2.waitKey(0)
cv2.destroyAllWindows()
6.1 习题讲解
例题:
- 引入一张图片
- 设计一个Logo图片
- 规划Logo的位置,在添加的位置变成黑色
- 利用add方法,把Logo和图片叠加在一起
import cv2
import numpy as np
# 导入图片
dog = cv2.imread('./dog.jpg') # (100, 100, 3)
# 创建LOGO,两个纯色矩形
logo = np.zeros((80, 80, 3), np.uint8)
# 绘制LOGO
logo[10:30, 10:30] = [0,0,255] # 红
logo[20:40, 20:40] = [0,255,0] # 绿
# 构造掩码 mask 作为一个抠取部分来抠取LOGO
mask = np.zeros((80, 80), np.uint8)
mask[10:30, 10:30] = 255
mask[20:40, 20:40] = 255
m = cv2.bitwise_not(mask)
cv2.imshow('logo_mask', np.hstack((mask, m)))
# 选取dog添加LOGO的位置
roi = dog[0:80, 0:80]
# roi与m进行与操作,先roi和roi做与运算,再喝mask做与运算
# 如果结果是True返回原图的像素,否则返回0(255和任何颜色与都是True,0和任何颜色与都是0)
temp = cv2.bitwise_and(roi, roi, mask=m)
# 求和叠加图片
dst = cv2.add(temp, logo)
# 在dog上还原
dog[:80, :80] = dst
cv2.imshow('roi_temp_dst', np.hstack((roi, temp, dst)))
cv2.imshow('result', dog)
cv2.waitKey(0)
cv2.destroyAllWindows()