图像二值化处理

图像二值化处理

Tags
OpenCV
Computer Vision
Published
July 6, 2018
Author
yanbc

Overview

二值化是常用的图像处理手段之一,通过二值化处理我们可以突出图像中感兴趣的部分,过滤掉多余的部分(比如噪音)。OpenCV 中二值化处理主要是调用这两个函数:
下面对不同的二值化方法进行详细说明。注意,下面的讨论都是对灰度图进行二值化处理,但这种方法可以很容易地移植到多通道图像上。

简单二值化

最直接的二值化是这个样子的:对每一个像素点采用相同的二值化阈值,当像素值小于这个阈值时,像素值设为0,相反,设为255。这时,我们调用cv.threshold这个方法,它总共接受4个输入:第一个是要处理的图像;第二个是二值化阈值;第三个是像素取值的最大值,一般是255;第四个是二值化的类型。第四个输入有下面五个选择。对于这五种选择的差别详见OpenCV文档
  1. cv.THRESH_BINARY
  1. cv.THRESH_BINARY_INV
  1. cv.THRESH_TRUNC
  1. cv.THRESH_TOZERO
  1. cv.THRESH_TOZERO_INV

代码例子

import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread('gradient.png',0) ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY) ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV) ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC) ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO) ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV) titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV'] images = [img, thresh1, thresh2, thresh3, thresh4, thresh5] for i in xrange(6): plt.subplot(2,3,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
notion image

自适应二值化(Adaptive Threshold)

在简单二值化处理中,我们对整张图片采用了一样的阈值,但很多时候,我们会想对图片中不同的地方采用不同的阈值。比如一张图片不同区域的光照条件不一样,这时我们就会用到自适应二值化(cv.adaptiveThreshold)。在这种方法中,算法基于一个像素点周围的区域决定这个像素点的二值化阈值。除了简单二值化中提到的输入参数,cv.adaptiveThreshold还有自己的三个参数:
  1. adaptiveMethod 告诉函数该使用哪一种自适应方法:
      • cv.ADAPTIVE_THRESH_MEAN_C 阈值是周围区域的平均值减去一个常量 C
      • cv.ADAPTIVE_THRESH_GAUSSIAN_C 阈值是周围区域的高斯平均值减去一个常量
  1. block 周围区域的大小
  1. C 减去的常量

代码例子

import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread('sudoku.png',0) img = cv.medianBlur(img,5) ret,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY) th2 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,\ cv.THRESH_BINARY,11,2) th3 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\ cv.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 xrange(4): plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
notion image

大津二值化(Otsu's Binarization)

别猜了,大津是一个日本名字。大津二值化是由大津展之发明的,所以就用他的名字命名了。和简单二值化相似,大津二值化也是一个全局二值化的方法,也就是对整张图片采用同一样的阈值。但和简单二值化不同的是,大津二值化不用人为地提供一个阈值,它根据整张图片的像素点的直方图分布计算合适的阈值。
这样说可能比较抽象,想象一张图片,它由两种不同的像素点组成,比如说0和128。相应的,它的像素点直方图只有两个峰值,分别位于0和128。一个好的阈值应该在0和128的中间,也就是64,这样就可以把这张图片上的像素点分开了。相似的,大津二值化先计算一个这样的合适的阈值,然后用这个阈值对整张照片进行二值化。
由于是全局二值化,我们还是使用cv.threshold()这个方法,同时我们需要在最后一个输入参数中添加cv.THRESH_OTSU。输入的阈值参数将会被忽略,取而代之的是大津二值化计算出来的阈值。

代码例子

import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread('noisy2.png',0) # global thresholding ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY) # Otsu's thresholding ret2,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU) # Otsu's thresholding after Gaussian filtering blur = cv.GaussianBlur(img,(5,5),0) ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.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 xrange(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()
notion image