视觉学习基础(二)图像分割:阈值化

说明:文章将包含简短的理论介绍,重点还是在具体的实践部分

1.理论介绍

阈值化

  • 基本概念:阈值、灰度直方图、全局阈值化、局部自适应阈值化、带阈值化、半阈值化
  • 阈值检测方法:P率阈值化、模式方法、直方图变换、Gauss最优阈值OTSU大津算法、 多光谱阈值化

Gauss最优阈值:

Gauss思想:

假设灰度直方图的概率分布模型可由两个不同的正态分布相加得到,那么两个正态分布的交点便为最优阈值点。

具体算法:

其中p(g)为灰度直方图,g为像素值。

视觉学习基础(二)图像分割:阈值化_第1张图片

(图片来源:http://blog.csdn.net/sky_in_my_mind/article/details/72730595)

OTSU大津算法:

思想:

是一种基于全局的二值化算法,它是根据图像的灰度特性,基于灰度直方图,将图像分为前景和背景两个部分,当取最佳阈值时,两部分之间的类间方差最大。

视觉学习基础(二)图像分割:阈值化_第2张图片

多光谱阈值化:

思想:

一种分割方法在每个谱段中(如R、G、B)独立地确定阈值,然后综合起来形成单一的分割图像。


2.具体的实践部分

使用OpenCV实现图像的阈值分割

具体的函数:

(1)cv2.threshold全局阈值化,需要给定阈值

double threshold(  
    InputArray src, // 输入图像  
    OutputArray dst, // 输出图像  
    double thresh, // 阈值  
    double maxValue, // 向上最大值  
    int thresholdType // 阈值化操作的类型 
);

二值化操作的类型,包含以下6种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV;

(补充)大津算法 cv2.THRESH_OTSU:输入任意阈值均无影响

 #-*- coding: utf-8 -*-  
""" 
实现大津法 
"""  
import cv2
import time  

img = cv2.imread("qipange.jpg", -1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
time0 = time.time()  
retval, dst = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)  
time1 = time.time()  
total = (time1 - time0)  
print("otsu need time: ",total,"s")  
  
cv2.imshow("src", img)  
cv2.imshow("gray", gray)  
cv2.imshow("dst", dst)  
cv2.waitKey(0) 

但是,这种方法由于是全局阈值,对于亮度分布差异较大的图像,常常无法找到一个合适的阈值。如下所示,对棋盘格进行二值化操作,由于图像右上角区域和图像下部的亮度差异较为大,无法找到一个合适的阈值,将棋盘上的所有棋盘格给区分开来。

视觉学习基础(二)图像分割:阈值化_第3张图片

因此,需要采用一种局部的自适应阈值化

(2)cv2.adaptiveThreshold

            局部自适应阈值二值化函数根据图片一小块区域的值来计算对应区域的阈值。支持两种自适应方法:平均和高斯。在两种情况下,自适应阈值T(x, y)通过计算每个像素周围bxb大小像素块的加权均值并减去常量C得到。其中,b由blockSize给出,大小必须为奇数;如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。

void adaptiveThreshold(  
    InputArray src, // 输入图像  
    OutputArray dst, // 输出图像  
    double maxValue, // 向上最大值  
    int adaptiveMethod, // 自适应方法,平均或高斯  
    int thresholdType, // 阈值化类型  
    int blockSize, // 块大小  
    double C // 常量  
); 
  • src: 输入图,只能输入单通道图像,通常来说为灰度图
  • dst: 输出图
  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • thresh_type: 阈值的计算方法,包含以下2种类型:cv2.ADAPTIVE_THRESH_MEAN_C; cv2.ADAPTIVE_THRESH_GAUSSIAN_C.
          ADAPTIVE_THRESH_MEAN_C的计算方法是计算出领域的平均值再减去第七个参数double C的值

          ADAPTIVE_THRESH_GAUSSIAN_C的计算方法是计算出领域的高斯均值再减去第七个参数double C的值

  • type:二值化操作的类型,与固定阈值函数相同,包含以下6种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV;cv2.THRESH_TRUNC;cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV;cv2.THRESH_OTSU
  • Block Size: 图片中分块的大小
  • C :阈值计算方法中的常数项

官方文档的参考代码:

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('qipange.jpg',0)
img = cv2.medianBlur(img,5)
ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
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 xrange(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()
结果:

                                      视觉学习基础(二)图像分割:阈值化_第4张图片

参考资料:

1.OpenCV官方教程:https://docs.opencv.org/3.2.0/d7/d4d/tutorial_py_thresholding.html

2.相关博客:http://blog.csdn.net/guduruyu/article/details/68059450

                 http://blog.csdn.net/sinat_21258931/article/details/61418681




你可能感兴趣的:(计算机视觉学习之旅)