天天看点

opencv学习——Otsu's二值化

简单来说就是对一幅双峰图像自动根据其直方图计算出一个阈值。(对于非双峰图像,这种方法得到的结果可能会不理想)。

这里用到到的函数还是 cv2.threshold(),但是需要多传入一个参数(flag):cv2.THRESH_OTSU。这时要把阈值设为 0。然后算法会找到最优阈值,这个最优阈值就是返回值 retVal。如果不使用 Otsu 二值化,返回的retVal 值与设定的阈值相等。

import cv2
import numpy as np
import matplotlib.pylab as plt
import scipy.misc as misc


img = cv2.imread('images/32.jpg',)
# global thresholding
ret1,th1 = cv2.threshold(img,,,cv2.THRESH_BINARY)
# Otsu's thresholding
ret2,th2 = cv2.threshold(img,,,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering

# ( 5,5 )为高斯核的大小, 0 为标准差
blur = cv2.GaussianBlur(img,(,),)
# 阈值一定要设为 0 !
ret3,th3 = cv2.threshold(blur,,,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# plot all the images and their histograms
images = [img, , th1,
          img, , th2,
          blur, , th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
'Original Noisy Image','Histogram',"Otsu's Thresholding",
'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
# 这里使用了 pyplot 中画直方图的方法, plt.hist, 要注意的是它的参数是一维数组
# 所以这里使用了( numpy ) ravel 方法,将多维数组转换成一维,也可以使用 flatten 方法
#ndarray.flat 1-D iterator over an array.
#ndarray.flatten 1-D array copy of the elements of an array in row-major order.
for i in range():
  plt.subplot(,,i*+),plt.imshow(images[i*],'gray')
  plt.title(titles[i*]), plt.xticks([]), plt.yticks([])
  plt.subplot(,,i*+),plt.hist(images[i* + ].flatten(),)
  plt.title(titles[i*+]),plt.xticks(np.linspace(,,))
  plt.subplot(,,i*+),plt.imshow(images[i*+],'gray')
  plt.title(titles[i*+]), plt.xticks([]), plt.yticks([])

plt.show()