opencv图像阈值分割

图像阈值

基本概念:图像阈值一般用于图像阈值分割,图像阈值即图像分割的基准,一般对象为灰度图像,基于此可完成图像的二值化。


全局阈值分割

opencv中提供了不同的阈值准则,以python操作opencv为例:
ret, dst = cv2.threshold(src, thresh, maxval, type)

  • src:输入图,只能输入单通道图像,通常来说为灰度图
  • dst:输出图,一般为二值图像
  • thresh:阈值
  • maxval:当像素值超过了阈值(或者小于阈值,根据type来决定)所赋予的值
  • type:二值化操作的类型,包含以下5种类型:cv2.THRESH_BINARY;cv2.THRESH_BINARY_INV;cv2.THRESH_TRUNC;cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
  • cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
  • cv2.THRESH_BINARY_INV THRESH_BINARY的反转
  • cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
  • cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
  • cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

另外,type值还有两个选择,为自适应阈值算法,不是固定阈值,此时传入参数thresh不会起作用。

cv2.THRESH_OTSU 使用大津法选择最优的thresh;

cv2.THRESH_TRIANGLE 使用三角法确定thresh;

大津算法(自适应阈值算法)

  • 确定最佳阈值,使背景和目标之间的类间方差最大(因为二者差异最大)
    opencv图像阈值分割_第1张图片
    μ \mu μ为整张图片的灰度均值, μ 0 \mu_0 μ0 μ 1 \mu_1 μ1分别为背景和目标两类的灰度均值, ω 0 \omega_0 ω0 ω 1 \omega_1 ω1分别代表两类的面积,在灰度直方图中即每一类像素的个数占所有像素个数的比例, ω 0 + ω 1 = 1 \omega_0+\omega_1=1 ω0+ω1=1 g g g为两类间的方差。
    μ = ω 0 μ 0 + ω 1 μ 1 g = ω 0 ( μ 0 − μ ) 2 + ω 1 ( μ 1 − μ ) 2 g = ω 0 ω 1 ( μ 0 − μ 1 ) 2 \mu = \omega_0\mu_0 + \omega_1\mu_1 \\ g = \omega_0(\mu_0-\mu)^2+\omega_1(\mu_1-\mu)^2 \\ g = \omega_0\omega_1(\mu_0-\mu_1)^2 μ=ω0μ0+ω1μ1g=ω0(μ0μ)2+ω1(μ1μ)2g=ω0ω1(μ0μ1)2
  • 算法实现:遍历所有灰度后,计算并取最大g值所对应的灰度作为最佳阈值。

下面看看不同阈值分割准则的效果:
代码:

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline 

img=cv2.imread('cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

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)
ret, thresh6 = cv2.threshold(img_gray, 0, 255, cv2.THRESH_OTSU)
ret, thresh7 = cv2.threshold(img_gray, 0, 255, cv2.THRESH_TRIANGLE)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV', 'OTSU', 'TRIANGLE']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5, thresh6, thresh7]

for i in range(8):
    plt.subplot(2, 4, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

运行效果:
opencv图像阈值分割_第2张图片

你可能感兴趣的:(计算机视觉)