灰度图像的阙值处理
在OpenCV中利用threshold()对灰度图像进行阙值处理,该函数通过将图像中的每个像素值与一个给定的阈值进行比较来工作。如果像素值超过这个阈值,那么像素值将被设置成指定的最大值;如果没有超过阈值,则根据不同的阈值类型,可能会被设置为0或者保持原值。其中有5中基本类型的阙值。
注:五种基本类型的阙值分别和作用分别为:
- cv2.THRESH_BINARY: 当像素值超过阈值时,设置像素值为最大值,否则设置为0。
- cv2.THRESH_BINARY_INV: 与cv.THRESH_BINARY相反,当像素值超过阈值时设置为0,否则设置为最大值。
- cv2.THRESH_TRUNC: 当像素值超过阈值时,设置像素值为阈值,而不是最大值。
- cv.THRESH_TOZERO: 当像素值超过阈值时保持不变,否则设置为0。
- cv2.THRESH_TOZERO_INV: 与cv.THRESH_TOZERO相反,当像素值超过阈值时设置为0,否则保持不变。
例如:
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread(r'D:\Photo\1.jpeg')
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5=cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
titles=['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images=[img,thresh1,thresh2,thresh3,thresh4,thresh5]
for i in range(6):
cv2.imshow(titles[i],images[i])
cv2.waitKey(0)
cv2.destroyAllWindows()
这段代码是使用OpenCV库对图像进行阈值处理,并显示处理后的图像。首先导入所需的库,然后读取一张图片并将其转换为灰度图像。接着使用不同的阈值处理方法对灰度图像进行处理,包括二值化、反二值化、截断和零处理等。最后将处理后的图像显示出来。
运行结果如下所示(六张图两两一组):
在上面所有的图片中,阙值被设定为了127。在TERESH_BINARY中,如果图像中的像素点超过127设置为最大值(白色部分),没超过则直接变为0(黑色部分);在TERESH_BINARY_INV中,如果图像的像素点超过127直接变为0(黑色部分),否则设置为最大值(白色部分),可以看到TERESH_BINARY_INV与TERESH_BINARY是内容黑白完全相反的;在TERESH_TRUNC中,超过阙值的部分设置为阙值大小(执行后图像内没有超过阙值的像素);在TERESH_TOZERO中,超过阙值的部分保持不变,其余部分变为0(黑色部分);TERESH_TOZERO_INV中,超过阙值的部分变为0(黑色部分),没超过的部分保持不变。
边界填充
在OpenCV中,使用copyMakeBorder()函数对于边界进行填充。在copyMakeBorder()函数中,需要有几个参数,基本形式是:cv2.copyMakeBorder(src, top, bottom, left, right, borderType, value),对其基本形式的解释是:
src
:输入图像。top
:上边框的宽度。bottom
:下边框的宽度。left
:左边框的宽度。right
:右边框的宽度。value
:当borderType
为cv2.BORDER_CONSTANT
时,用于填充边框的颜色值。borderType
:边框类型,可以是以下几种之一:
cv2.BORDER_REPLICATE
:复制最边缘的像素来填充边框。cv2.BORDER_REFLECT
:反射图像边界像素来填充边框。cv2.BORDER_REFLECT_101
:类似于cv2.BORDER_REFLECT
,但略有不同。cv2.BORDER_WRAP
:将图像边界像素循环复制到边框区域。cv2.BORDER_CONSTANT
:使用指定的常量值填充边框。
下面我们可以比较不同的情况下,不同的边框类型所产生的不同影响。如下这个示例:
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread(r'D:\Photo\1.jpeg')
top_size,botton_size,left_size,right_size=(50,50,50,50)
img_replicate=cv2.copyMakeBorder(img,top_size,botton_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE)
img_reflect=cv2.copyMakeBorder(img,top_size,botton_size,left_size,right_size,borderType=cv2.BORDER_REFLECT)
img_reflect101=cv2.copyMakeBorder(img,top_size,botton_size,left_size,right_size,borderType=cv2.BORDER_REFLECT_101)
img_wrap=cv2.copyMakeBorder(img,top_size,botton_size,left_size,right_size,borderType=cv2.BORDER_WRAP)
img_constant=cv2.copyMakeBorder(img,top_size,botton_size,left_size,right_size,borderType=cv2.BORDER_CONSTANT,value=0)
res=[img,img_replicate,img_reflect,img_reflect101,img_wrap,img_constant]
titles=['ORIGINAL','REPLICATE','REFLECT','REFLECT_101','WRAP','CONSTANT']
for i in range(6):
plt.subplot(2,3,i+1)
plt.imshow(res[i],'gray')
plt.title(titles[i])
plt.show()
运行结果如下所示:
可以看到图片1为原图;在图片2中直接是以图片的边框所在的像素内容为扩展(可以看到图片2中很多是直线形状的); 而图片3的内容,是通过映射原图像的内容(可以看到图3的内容有对称的部分);而图片4的的内容与图3类似;图片5就是循环填充,就是将像素平铺展示;而图片6就是将图片扩展的部分直接设置成了黑色。