今天学习的是图像数值计算。
直接上干货
图像数值计算
图像阈值
给图像设定一个阈值,本质上就是给像素矩阵设置一个阈值,矩阵中每一个元素都会和这个阈值进行比较。超过阈值做什么操作,不超过阈值的数又去什么操作。
OpenCV中已经提供了阈值函数:
ret,dst = cv2.threshold(src,thresh,maxval,type)
dst:表示返回的图形矩阵
src:表示输入的图像
thresh:表示阈值
maxval:像素值超过阈值后或赋予的数,不一定派上用场
type:二值化操作类型。
其中,最重要的参数就是type,表示你需要对图形进行一个什么样的操作。
type参数有:
cv2.THRESH_BINARY: 超过阈值的部分取maxval,其余取0
cv2.THRESH_BINARY_INV: 和THRESH_BINARY相反
cv2.THRESH_TRUNC: 大于阈值的部分取thresh,其余不变
cv2.THRESH_TOZERO:大于阈值的不变,其余为0
cv2.THRESH.TOZERO_INV: THRESH_TOZERO的反转
由此可以看出,maxval这个参数有些时候用不到,比如type = cv2.THRESH_TRUNC时。但是maxval作为一个位置参数,在调用这个方法的时候还是必须得穿这个参数进去,尽管可能用不到,不然会报错。
那么直接上代码看看运行结果:
import cv2 #opencv读取BGR文件
import matplotlib.pyplot as plt
#读取bird图像
bird = cv2.imread('bird.jpg')
#各种type都试一下
ret,thresh1 = cv2.threshold(bird,15,200,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(bird,15,200,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(bird,15,200,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(bird,15,200,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(bird,15,200,cv2.THRESH_TOZERO_INV)
#把所有的type返回的图像矩阵都放在一个list中,好出图
img = [bird,thresh1,thresh2,thresh3,thresh4,thresh5]
#展示图形的title
title = ['bird','THRESH_BINARY','THRESH_BINARY_INV','THRESH_TRUNC','THRESH_TOZERO','THRESH_TOZERO_INV']
#写一个for循环用来展示图形
for i in range(6):
plt.subplot(2,3,i+1)#设置画布为两行三列出图,第一张图在两行三列第0+1张图中
plt.imshow(img[i])#plt出图的基本操作,不要再问我这是啥意思了,前几章已经讲过
plt.title(title[i])#设置每张图的title
出图:
第一张图就是原图,由于我是用plt出的图,所以和opencv的图片颜色通道相反,plt是RGB类型的颜色通道,opencv是BGR类型的,如果要正常显示图形颜色看上一张,这里其实无所谓
第二张图:像素值超过15的都取200,其余都取0
第三张图:和第二张图相反,超过15的都取0,其余取200
第四张图:超过15的都取15,其余不变。这里基本都超过15.所以基本都是15,颜色太深了看不出来
第五张图:超过15的不变,其余取0
第六张图:第五张图反过来,超过15都取0,其余不变
当然,我们在做一些遥感影像或者做一些其他学科的东西的时候需要对图像的某个波段进行单独处理,这边就可以联动上一节课讲的内容:
直接上代码
import cv2 #opencv读取BGR文件
import matplotlib.pyplot as plt
#这边把六个type的阈值函数写进一个方法里,把出图的方法也写进去
def threshold_function(img):
ret,thresh1 = cv2.threshold(img,15,200,cv2.THRESH_BINARY)#大于15取200,其余取0
ret,thresh2 = cv2.threshold(img,15,200,cv2.THRESH_BINARY_INV)#与小于15取200,其余取0
ret,thresh3 = cv2.threshold(img,100,200,cv2.THRESH_TRUNC)#大于100取100,其余不变
ret,thresh4 = cv2.threshold(img,100,200,cv2.THRESH_TOZERO)#大于100不变,其余取0
ret,thresh5 = cv2.threshold(img,100,200,cv2.THRESH_TOZERO_INV)#大于100取0,其余不变
pic = [img,thresh1,thresh2,thresh3,thresh4,thresh5]
title = ['original','THRESH_BINARY','THRESH_BINARY_INV','THRESH_TRUNC','THRESH_TOZERO','THRESH_TOZERO_INV']
#写个for循环用于出图
for i in range(6):
plt.subplot(2,3,i+1)
plt.imshow(pic[i],'gray')#plt中的imshow方法可以输入'gray'参数表示输出灰度图
plt.title(title[i])
return
#复习一下之前的split操作,分离单个波段
r,g,b = cv2.split(bird)
#对单个通道进行处理
threshold_function(r)
返回
这边对r波段进行了单独的处理,小伙伴们也可以试试对g波段或者b波段单独处理,最后可以根据需要输出单个波段的灰度图也可以merge在一起输出三通道或者多通道的图片,复习一下上一张的内容。
img = cv2.merge((b,g,r))
图像叠加
我们由两张图,一张cat,一张bird,现在我要把这两张图片叠加在一起。应该怎么做呢?
第一步:看一下两张图像的shape
import cv2
#读取图像
cat = cv2.imread('cat.jpg')
bird = cv2.imread('bird.jpg')
#输出shape
print('cat',cat.shape,'bird',bird.shape)
返回
cat (2657, 1771, 3) bird (427, 640, 3)
发现cat和bird的图像的shape不同,没法直接相加
利用resize函数可以修改图像的大小。注意resize函数是修改大小而不是剪裁图像
cat_change = cv2.resize(cat,(640,427))#这边的size要反过来写,因为这边表示的是x,y,而之前咱们看的shape属性代表的是矩阵的行,列,维,行数其实代表的是y轴,列数代表的是x轴
#修改前后的图像输出对比一下
plt.subplot(121),plt.imshow(cat),plt.title('cat')
plt.subplot(122),plt.imshow(cat_change),plt.title('cat_change')
返回的图像可以说明resize函数是修改大小和尺寸而不是剪裁图像的某一部分
resize方法如果size设为(0,0)的话,输入fx,fy的参数的意思是x轴,y轴变为原来的多少倍的意思。
cat = cv2.imread('cat.jpg')
#x变为原来的5倍,y变为原来的两倍
cat_change = cv2.resize(cat,(0,0),fx = 5,fy = 2)
plt.subplot(121),plt.imshow(cat),plt.title('cat')
plt.subplot(122),plt.imshow(cat_change),plt.title('cat_change')
图像叠加:
cv2.addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None)
src1:需要叠加的图像1
alpha:图像1 的透明度(像素值的权重)
src2:需要叠加的图像2
beta:图像2的透明度
gamma:伽马矫正
其中伽马矫正如果不需要就设为0。伽马矫正就是由于图像显示的和人眼感知的不匹配。可能在计算机眼中两个是不一样的颜色但是人眼无法分别,这时就需要伽马矫正让计算机输出的图像符合人眼的感知。有点类似于改变对比度。这个值越大对比度越小。
此方法不存在什么图像在上层或在下层,本质上就是像素值的相加
结果: