OpenCV - day02 Image_Threshold

167 阅读3分钟

图像阈值

一、ret,dst = cv2.threshold(src, thresh, maxval, type)

  • src:输入图,只输入单通道图像,通常来说是灰度图(也可以是B、G、R)

  • dst:输出图

  • thresh:阈值

  • maxval:当像素值超过了阈值(或者小于阈值,这是由type决定的),所赋予的值,一般是255(白色)

  • type:二值化操作的类型,包括以下五种类型

    1. cv2.THRESH_BINARY:超过阈值就取maxval,否则取0 ——二元取值
    2. cv2.THRESH_BINAY_INV:上面的翻转,即不超过的取maxval,超过就0 —— 同样也是二元取值
    3. cv2.THRESH_TRUNC:超过阈值就设为阈值,否则不变
    4. cv2.THRESH_TOZERO:超过阈值不变,否则为0
    5. cv2.THRESH_BINAY_INV:上面的翻转,即超过为0,不超过不变
 import cv2
 import matplotlib
 import matplotlib.pyplot as plt #取别名(用于绘图展示)
 import numpy as np #取别名,下面是notepad专用,立即显示图像
 %matplotlib inline 
 def cv_show(name, img): #定义函数用于显示图片,此处name为窗口名,img为cv2调用imread方法的返回值
     cv2.imshow(name,img)
     cv2.waitKey(0)
     cv2.destroyAllWindows()
 img_gray = cv2.imread('sys.jpg', cv2.IMREAD_GRAYSCALE) #彩色图像的可以不加参数,也可加上IMREAD_COLOR
 # cv_show('Test', img_gray)
 img = cv2.imread('sys.jpg')
 cv_show('Test', img)
 ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
 ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)  
 ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
 ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
 ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)  
 ​
 titles = ['Original Image','Gray Image','BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
 images = [img, img_gray, thresh1, thresh2, thresh3, thresh4, thresh5]
 for i in range(7):
     plt.subplot(2, 4 , i + 1), # 前面是行数,后面是列数,i+1的值应该在 [1 - 行*列] 之间
     plt.imshow(images[i], 'gray') 
     plt.title(titles[i])
     plt.xticks([]), plt.yticks([])
 plt.show()

output_4_0.png

二、图像平滑

  • 也就是进行各种滤波操作
  • 卷积就是根据邻域像素值得出中心点的像素值
 img = cv2.imread('sys.jpg')
 ​
 cv_show('sys', img)

三、滤波的用法

  • 均值滤波(blur)

    把包括中心点和D8领域的一共九个像素点的灰度值求平均,命为处理后的中心点值      

  • 方框滤波(boxFilter)

    和均值滤波大致一致,重点在于最后一个参数normalize的取值,若为True则和均值滤波一致,若为False则不会取平均,直接累加,越界就取最大值      

  • 高斯滤波(GaussianBlur):

    卷积核里的数值满足高斯分布,相当于更重视中心像素值,D4领域比较近就赋予更大权值,(D8-D4)领域比较远,权值比较小,最后除数是各权值之和      

  • 中值滤波(medianBlur):

    对N * N个元素进行排序,取中间值为中心点像素值,能一次性把所有噪音点都去除

## 均值滤波
## 简单的平均卷积操作

# 第一个参数是待处理图像,第二个参数是方阵大小(一般奇数)
blur = cv2.blur(img, (3, 3)) 

cv_show('Blur', blur)
## 方框滤波
## 基本和均值一样,可以选择归一化

#传入-1表示自动计算,normalize的值为True则会归一化(平均)使得结果和均值滤波一致

box = cv2.boxFilter(img, -1, (3, 3), normalize = True) 
#若normalize为False,则会累加不会平均,越界出去就直接赋最大值

cv_show('Box', box)
## 方框滤波
## 不进行归一
box = cv2.boxFilter(img, -1, (3, 3), normalize = False) 

cv_show('Box', box)
## 高斯滤波
## 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中心值

# 最后一个参数是中心像素值所占权重,会进行矩阵处理
aussian = cv2.GaussianBlur(img, (5, 5), 1) 

cv_show('Gassian', aussian)
## 中值滤波
## 相当于使用中值代替
## 非线性操作
median = cv2.medianBlur(img, 5) # 后面参数是矩阵阶数

cv_show('Median', median)
# 拼接所有展示结果

#vstack - vertical, hstack - horizontal
res = np.hstack([blur, aussian, box, median]) 

print(res)
cv_show('Component', res)
[[[ 8 17  7]
  [13 22 12]
  [21 30 20]

  [57 45 62]
  [58 46 63]
  [61 46 62]]

 ...

 [[ 3  3 19]
  [ 5  5 21]
  [16 16 31]

  [59 64 67]
  [59 62 66]
  [59 62 66]]]
## 使用plt
plt.imshow(res)
<matplotlib.image.AxesImage at 0x296bc1d3340>

output_14_1.png

  • 效果演示 从左至右依次为:均值滤波、高斯滤波、无归一化的方框滤波、中值滤波。 归一化的方框和均值效果等价。
def winds(images):
    for i in range(len(images)):
        images[i] = cv2.resize(images[i], (0, 0), fx = 0.7, fy = 0.7)
        # 注意下面这一句的神来之笔
        images[i][ :,-2:,:] = 255
    res = np.hstack(images)
    cv_show('Compare', res)
    
winds([blur, aussian, box, median])

各滤波对比图.PNG