OpenCV-Python学习(6)—— OpenCV 图像算术操作(cv.add、cv.subtract、cv.multiply、cv.divide)

1. 知识点

  1. 算术操作;
  2. 像素算术操作。

2. NumPy算术操作 和 OpenCV像素运算

2.1 加法
2.1.0 cv.add 函数
cv.add(src1,src2[,dst[,mask[,dtype]]])
2.1.1 代码测试
  1. 读取图片butterfly和lena;
  2. 获取两张图片[0,100]位置的像素值;
  3. 使用加法、np.add、cv.add进行算术操作。
import cv2 as cv
import numpy as np

def sums_add():
  img1 = cv.imread('./images/butterfly.jpg')
  img2 = cv.imread('./images/lena.jpg')
  print('img1',img1[0,100])
  print('img2',img2[0,100])
  print('加法',img2[0,100] + img1[0,100])
  print('np.add',np.add(img2[0,100], img1[0,100]))
  print('cv.add',cv.add(img2[0,100], img1[0,100]))
if __name__ == "__main__":
  sums_add()
2.1.2 测试结果

在这里插入图片描述

2.2 减法
2.2.0 cv.subtract 函数
cv.subtract(src1,src2[,dst[,mask[,dtype]]])
2.2.1 代码测试
import cv2 as cv
import numpy as np

def sums_subtract():
  img1 = cv.imread('./images/butterfly.jpg')
  img2 = cv.imread('./images/lena.jpg')
  print('img1',img1[0,100])
  print('img2',img2[0,100])
  print('减法',img2[0,100] - img1[0,100])
  print('np.subtract',np.subtract(img2[0,100], img1[0,100]))
  print('cv.subtract',cv.subtract(img2[0,100], img1[0,100]))
if __name__ == "__main__":
  sums_subtract()
2.2.2 测试结果

在这里插入图片描述

2.3 乘法
2.3.0 cv.multiply函数
cv.multiply(src1,src2[,dst[,scale[,dtype]]])
2.3.1 代码测试
import cv2 as cv
import numpy as np

def sums_multiply():
  img1 = cv.imread('./images/butterfly.jpg')
  img2 = cv.imread('./images/lena.jpg')
  print('img1',img1[0,100])
  print('img2',img2[0,100])
  print('乘法',img2[0,100] * img1[0,100])
  print('np.multiply',np.multiply(img2[0,100], img1[0,100]))
  print('cv.multiply',cv.multiply(img2[0,100], img1[0,100]))
if __name__ == "__main__":
  sums_multiply()
2.3.2 测试结果

在这里插入图片描述

2.4 除法
2.4.0 cv.divide 函数
cv.divide(src1,src2[,dst[,scale[,dtype]]])
2.4.1 代码测试
import cv2 as cv
import numpy as np

def sums_divide():
  img1 = cv.imread('./images/butterfly.jpg')
  img2 = cv.imread('./images/lena.jpg')
  print('img1',img1[0,100])
  print('img2',img2[0,100])
  print('除法',img2[0,100] * img1[0,100])
  print('np.divide',np.divide(img2[0,100], img1[0,100]))
  print('cv.divide',cv.divide(img2[0,100], img1[0,100]))
if __name__ == "__main__":
  sums_divide()
2.4.2 测试结果

在这里插入图片描述

2.5 注意

注意:

  1. OpenCV加法和Numpy加法之间有区别。OpenCV加法是饱和运算,而Numpy加法是模运算。
  2. 保证不越界,cv.add、cv.subtract、cv.multiply、cv.divide取值范围 [0,255]

3. 图像像素运算

3.1 实例
  1. 读取要图像像素运算的原图片 opencv-logo-white;
  2. 复制一个和原图形状一致的矩阵,数组元素以 0 来填充;由于图像像素运算两个图像必须是一样大小,所以直接复制一个形状一致的矩阵。
  3. 修改矩阵每个元素的颜色为 (110,0,250);
  4. 图像像素加法运算【cv.add】,由于保证不越界,因此相加大于255的值最后的值都是255,如果三通道都是255就是白色;
  5. 图像像素减法运算【cv.subtract】,由于保证不越界,因此相减小于0的值最后的值都是0,如果三通道都是0就是黑色;
  6. 图像像素乘法运算【cv.multiply】,由于保证不越界,因此相乘大于255的值最后的值都是255,如果三通道都是255就是白色,由于复制图片的颜色是(110,0,250),所以除黑色外的颜色就是(255,0,255);
  7. 图像像素除法运算【cv.divide】,由于保证不越界,同时元素的dtype=np.uint8,所以原图像除以(110,0,250),所有元素值都基本是(0,0,0)【黑色】。
import cv2 as cv
import numpy as np

def sums_image():
  image1 = cv.imread("./images/opencv-logo-white.png")
  image2 = np.zeros_like(image1)
  image2[:] = (110,0,250)
  cv.imshow('image1', image1)
  cv.imshow('image2', image2)
  
  # 图像像素加法运算
  add_img = cv.add(image1, image2)
  cv.imshow('add_img', add_img)

  # 图像像素减法运算
  subtract_img = cv.subtract(image1, image2)
  cv.imshow('subtract_img', subtract_img)

  # 图像像素乘法运算
  multiply_img = cv.multiply(image1, image2)
  cv.imshow('multiply_img', multiply_img)

  # 图像像素除法运算
  divide_img = cv.divide(image1, image2)
  cv.imshow('divide_img', divide_img)

  cv.waitKey(0)
  cv.destroyAllWindows()

if __name__ == "__main__":
  sums_image()
3.2 实例结果

在这里插入图片描述

4. NumPy 算术运算进行图像操作

4.1 实例
import cv2 as cv
import numpy as np

def numpy_image():
  image1 = cv.imread("./images/opencv-logo-white.png")
  image2 = np.zeros_like(image1)
  image2[:] = (110,0,250)
  cv.imshow('image1', image1)
  cv.imshow('image2', image2)
  
  # 图像像素加法运算
  add_img = np.add(image1, image2)
  cv.imshow('add_img', add_img)

  # 图像像素减法运算
  subtract_img = np.subtract(image1, image2)
  cv.imshow('subtract_img', subtract_img)

  # 图像像素乘法运算
  multiply_img = np.multiply(image1, image2)
  cv.imshow('multiply_img', multiply_img)

  # 图像像素除法运算
  divide_img = np.divide(image1, image2)
  cv.imshow('divide_img', divide_img)

  cv.waitKey(0)
  cv.destroyAllWindows()

if __name__ == "__main__":
  numpy_image()
4.2 实例结果

在这里插入图片描述

4.3 总结
  1. OpenCV和Numpy的加法运算不同,OpenCV的加法运算是饱和运算,而Numpy的加法运算是模运算。
  2. 饱和运算最大的特点是不讲究溢出位,执行结果与底层关系不大;假设变量的类型是8位无符号整型,那么最大数是255,如果在数学上相加的结果大于255,那么饱和运算返回结果就是255。
  3. 模运算考虑溢出位,执行结果需要向计算机底层原理——二进制的方面思考;假设变量的类型是8位无符号整型,那么最大数是255(对应二进制11111111),如果在数学上相加的结果大于255,那么就会发生溢出,仅仅保留容器范围内的二进制位。
  4. 由于饱和运算和模运算的不同,可以看到做相同操作后,两种运算得到的图像差距较大!

5. NumPy 数据类型

名称说明
bool_布尔型数据类型(True 或者 False)
int_默认的整数类型(类似于 C 语言中的 long,int32 或 int64)
intc与 C 的 int 类型一样,一般是 int32 或 int 64
intp用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)
int8字节(-128 to 127)
int16整数(-32768 to 32767)
int32整数(-2147483648 to 2147483647)
int64整数(-9223372036854775808 to 9223372036854775807)
uint8无符号整数(0 to 255)
uint16无符号整数(0 to 65535)
uint32无符号整数(0 to 4294967295)
uint64无符号整数(0 to 18446744073709551615)
float_float64 类型的简写
float16半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_complex128 类型的简写,即 128 位复数
complex64复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128复数,表示双 64 位浮点数(实数部分和虚数部分)

总结

  1. OpenCV加法和Numpy加法之间有区别。OpenCV加法是饱和运算,而Numpy加法是模运算。
  2. 饱和运算最大的特点是不讲究溢出位,执行结果与底层关系不大;假设变量的类型是8位无符号整型,那么最大数是255,如果在数学上相加的结果大于255,那么饱和运算返回结果就是255。
  3. 模运算考虑溢出位,执行结果需要向计算机底层原理——二进制的方面思考;假设变量的类型是8位无符号整型,那么最大数是255(对应二进制11111111),如果在数学上相加的结果大于255,那么就会发生溢出,仅仅保留容器范围内的二进制位。
  4. 保证不越界,cv.add、cv.subtract、cv.multiply、cv.divide取值范围 [0,255]
  5. 由于图像像素运算两个图像必须是一样大小。
  6. 注意:OpenCV 元素的 dtype 是 np.uint8【无符号整数(0 to 255)】;Numpy 直接定义整数元素的 dtype 是 np.int32【整数(-2147483648 to 2147483647)】。
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rattenking

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值