opencv图像阈值

1.简单阀值cv2.threshold()

当像素值高于阀值时,我们给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)。这个函数就是cv2.threshold()。函数的第一个参数就是原图像,原图像应该是灰度图。第二个参数就是用来对像素值进行分类的阀值,第三个参数就是当像素值高于(有时小于)阀值时,应该被赋予新的像素值。OpenCV提供了多种不同的阀值方法,这是由第四个参数来决定的。方法主要包括:

cv2.THRESH_BINARY

cv2.THRESH_BINARY_INV

cv2.THRESH_TRUNC

cv2.THRESH_TOZERO

cv2.THRESH_TOZERO_INV

opencv图像阈值_第1张图片

img = cv2.imread('NBA.png')

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):

    plt.subplot(2,3,i+1)

    plt.imshow(images[i],'gray')

    plt.title(titles[i])

    plt.xticks([])

    plt.yticks([])

plt.show()


opencv图像阈值_第2张图片

2.自适应阈值   cv2.adaptiveThreshold()

在上面,我们使用全局值作为阈值。但是图像在不同区域中具有不同亮度,用一样的阈值处理,结果是不太良好的。在这种情况下,我们进行自适应阈值处理。根据图像上的每一个小区域计算与其对应的阀值。因此在同一幅图像上的不同区域采用的是不同的阀值,从而使我们能在亮度不同的情况下得到更好的结果。

这种方法需要我们指定三个参数,返回值只有一个。

Adaptive Method 指定计算阀值的方法

    cv2.ADAPTIVE_THRESH_MEAN_C:阀值取自相邻区域的平均值

    cv2.ADAPTIVE_THRESH_GAUSSIAN_C:阀值取自相邻区域的加权和,权重为一个高斯窗口

Block Size 邻域大小(用来计算阀值的区域大小)

C这就是一个常数,阀值就等于的平均值或者加权平均值减去这个常数

img = cv2.imread('NBA.png',0)

img = cv2.medianBlur(img,5)   #中值滤波

ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)

# 11为block size,2为C值

th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)

th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)

titles = ['Original Image', 'Global Thresholding (v = 127)', 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']

images = [img, th1, th2, th3]

for i in range(4):

    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')

    plt.title(titles[i])

    plt.xticks([]),plt.yticks([])

plt.show()


opencv图像阈值_第3张图片

3.Otsu's二值化

我们前面说到,cv2.threshold函数是有两个返回值的,前面一直用的第二个返回值,也就是阈值处理后的图像,那么第一个返回值(得到图像的阈值)将会在这里用到。

前面对于阈值的处理上,我们选择的阈值都是127,那么实际情况下,怎么去选择这个127呢?有的图像可能阈值不是127得到的效果更好。那么这里我们需要算法自己去寻找到一个阈值,而Otsu’s就可以自己找到一个认为最好的阈值。并且Otsu’s非常适合于图像灰度直方图具有双峰的情况,他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。那么经过Otsu’s得到的那个阈值就是函数cv2.threshold的第一个参数了。因为Otsu’s方法会产生一个阈值,那么函数cv2.threshold的的第二个参数(设置阈值)就是0了,并且在cv2.threshold的方法参数中还得加上语句cv2.THRESH_OTSU

img = cv2.imread('rectangle.jpg',0)  #建议找一张简单点的图片,这样更容易看出不同的地方在哪里

# global thresholding

ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)

# Otsu's thresholding

ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Otsu's thresholding after Gaussian filtering

blur = cv2.GaussianBlur(img,(5,5),0)

ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# plot all the images and their histograms

images = [img, 0, th1, img, 0, th2, blur, 0, th3]

titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)', 'Original Noisy Image','Histogram',"Otsu's Thresholding", 'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]

for i in range(3):

    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')

    plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])

    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)

    plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])

    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')

    plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])

plt.show()


opencv图像阈值_第4张图片

上面演示Otsu二进制化的Python实现,以显示它实际上是如何工作的。如果你不感兴趣,你可以跳过这个。

由于我们正在处理双峰图像,Otsu的算法试图找到阈值( t ),该阈值最小化由以下关系式给出的加权类内方差:


opencv图像阈值_第5张图片

它实际上找到位于两个峰值之间的t值,使得两个类别的方差最小。它可以简单地用Python实现,如下所示:

img = cv2.imread('NBA.jpg',0)

blur = cv2.GaussianBlur(img,(5,5),0)

# find normalized_histogram, and its cumulative distribution function

hist = cv2.calcHist([blur],[0],None,[256],[0,256])

hist_norm = hist.ravel()/hist.max()

Q = hist_norm.cumsum()

bins = np.arange(256)

fn_min = np.inf

thresh = -1

for i in range(1,256):

    p1,p2 = np.hsplit(hist_norm,[i]) # probabilities

    q1,q2 = Q[i],Q[255]-Q[i] # cum sum of classes

    b1,b2 = np.hsplit(bins,[i]) # weights 

    # finding means and variances

    m1,m2 = np.sum(p1*b1)/q1, np.sum(p2*b2)/q2

    v1,v2 = np.sum(((b1-m1)**2)*p1)/q1,np.sum(((b2-m2)**2)*p2)/q2

    # calculates the minimization function

    fn = v1*q1 + v2*q2

    if fn < fn_min:

        fn_min = fn

        thresh = i

# find otsu's threshold value with OpenCV function

ret, otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

print(thresh,ret)

你可能感兴趣的:(opencv图像阈值)