OpenCV-Python学习(6)—— OpenCV 图像算术操作

2022-10-24 15:59:28 浏览数 (1)

1. 知识点

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

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

2.1 加法
2.1.0 cv.add 函数
代码语言:javascript复制
cv.add(src1,src2[,dst[,mask[,dtype]]])
2.1.1 代码测试
  1. 读取图片butterfly和lena;
  2. 获取两张图片[0,100]位置的像素值;
  3. 使用加法、np.add、cv.add进行算术操作。
代码语言:javascript复制
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 函数
代码语言:javascript复制
cv.subtract(src1,src2[,dst[,mask[,dtype]]])
2.2.1 代码测试
代码语言:javascript复制
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函数
代码语言:javascript复制
cv.multiply(src1,src2[,dst[,scale[,dtype]]])
2.3.1 代码测试
代码语言:javascript复制
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 函数
代码语言:javascript复制
cv.divide(src1,src2[,dst[,scale[,dtype]]])
2.4.1 代码测试
代码语言:javascript复制
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)【黑色】。
代码语言:javascript复制
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 实例
代码语言:javascript复制
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)】。

0 人点赞