dtype参数不是用numpy的uint8,float32等数据类型,而是采用OpenCV的CV_8UC1、CV_32FC1等数据类型。
图像相加
1.add()
img = cv2.imread('..\\lena.jpg')[0:512,0:512] #截取部分,保证大小一致
img2 = cv2.imread('..\\opencv-logo.png' )[0:512,0:512]
img3 = cv2.add(img,img2)
cv2.imshow('add',img3)
cv2.waitKey(0)
在OpenCV中图像的算术运算遵循“饱和运算”的规则,如果计算的结果超过了阈值范围,则就近进行截断,比如unit8类型的数据范围是【0,255】,如果2个数值直接相加的结果大于255就会赋值为255.
2.+运算符
+运算符将2个图像相加,当2个值相加大于255时,会将这个值对256求余得到新的像素值。
3.addWeighted()
加权加法
第1个参数是图像1 src;
第2个参数是图像1的权值 alpha;
第3个参数为图像2 dst;
第4个参数为图像2的权值 beta;
第5个参数附加数值gamma,单个数值,即使是多通道图像也使用单个数值;
第6个参数可选,返回图像的实例,等同于函数返回结果
第7个参数可选,dtype,表示像素值的数据类型
alpha和beta的关系并不要求二者的和为1,新图像的结果可以表示为:dst(I)=saturate(src1(I)∗alpha+src2(I)∗beta+gamma)
。
import cv2
img = cv2.imread('..\\lena.jpg')[0:512,0:512] #截取部分,保证大小一致
img2 = cv2.imread('..\\opencv-logo.png' )[0:512,0:512]
img3 = cv2.addWeighted(img,0.5,img2,0.2,10)
print('img[161,199]:',img[161,199])
print('img2[161,199]:',img2[161,199])
print('img3[161,199]:',img3[161,199])
cv2.imshow('addWeighted-0.5-0.2',img3)
img3 = cv2.addWeighted(img,0.2,img2,0.5,10)
print('img[161,199]:',img[161,199])
print('img2[161,199]:',img2[161,199])
print('img3[161,199]:',img3[161,199])
cv2.imshow('addWeighted-0.2-0.5',img3)
cv2.waitKey(0)
同样加权addWeighted() 也是饱和运算.
图像相减
1.subtract()
2个图像相减仍然要求通道数一样,图像尺寸一样,同样遵守饱和运算,相减小于0的用0补。
import cv2
img = cv2.imread('..\\lena.jpg')[0:512,0:512] #截取部分,保证大小一致
img2 = cv2.imread('..\\opencv-logo.png' )[0:512,0:512]
img3 = cv2.subtract(img,img2)
print('img[161,199]:',img[162,200])
print('img2[161,199]:',img2[162,200])
print('img3[161,199]:',img3[162,200])
cv2.imshow('subtract(img,img2)',img3)
img3 = cv2.subtract(img2,img)
print('img2[161,199]:',img2[162,200])
print('img[161,199]:',img[162,200])
print('img3[161,199]:',img3[162,200])
cv2.imshow('subtract(img2,img)',img3)
cv2.waitKey(0)
- -运算符
如果得到的结果小于0,得到的结果不会出现负数,而是在这个负数的基础上加上256。
import cv2
img = cv2.imread('..\\lena.jpg')[0:512,0:512] #截取部分,保证大小一致
img2 = cv2.imread('..\\opencv-logo.png' )[0:512,0:512]
img3 = img-img2
cv2.imshow('img-img2',img3)
img4 = img2 - img
cv2.imshow('img2 - img',img4)
cv2.waitKey(0)
3.绝对值减法absdiff()
absdiff()得到的是2个图像间像素的绝对差值,二者对调减数和被减数时效果是一样的。
4.图像与标量
img3 = cv2.add(img,50)
#第1通道加一个标量值
img3 = cv2.subtract(img,(50,50,50,0))
#3个通道减一个标量值
图像和标量加减运算时,多通道的标量值用一个4元组表示。
当标量值只是1个数值时,只会对多通道图像的第1个通道进行运算,如果要进行多通道运算,标量值则使用一个包含4个数值的元组表示,即使是3通道的彩色图像也要用4元组表示这个标量值。下面这个例子对图像进行第1通道和3个通道的加减运算:
图像乘法
1.multiply()
multiply()遵守饱和运算
2. *
乘法
数值类型表示范围的上限加1取模,比如uint8类型的数据对256取模。
图像除法
1.divide()
divide()有2种用法:
dst = cv2.divide( src1, src2, dst, scale, dtype)
:第1个和第2个位置参数都是图像对象,可选参数scale参数指定src1的放大倍数,dst=saturate(src1*scale/src2);在cv2.divide( src1, src2[, dst[, scale[, dtype]]] )中的scale参数必须是数值型数据,先用src1乘以scale再除以src2,如果src1是多通道图像,scale会作用到src1的所有通道上。
dst = cv2.divide( scale, src2, dst, dtype)
:第1个位置参数为数值类型,第2个位置参数为图像对象,dst=saturate(scale/src2)。要想实现scale/src2的用法,必须显式地声明形参的名称。img_ret = cv2.divide(scale=250.0,src2=img)
如果是uint8等整数类型的除法,运算后的结果会做四舍五入取整。divide()除法也遵守“饱和运算规则”。
如果要调用第2种形式的接口必须显式地写明形参变量的名称。
2. /
符号除法实际就是numpy数组的除法。
imread()读入图像默认的数据类型为uint8,符号除法得到的数据类型发生了改变,变成了float64。
当除数为0时,numpy除法打印了告警信息:divide by zero encountered in true_divide,直接计算结果为inf,但是转换为OpenCV的图像是有实际意义的0。