CV8 OpenCV环境下实现大津算法

简介: 大津算法最终的目的,就是求一个标准的全局阈值区分前景和背景(小于该阈值的为前景。大于该阈值的为背景),使得前景和背景像素的灰度值方差之和最大。因为方差越大,相关性越小,黑白越分明。

一 大津算法简介


大津算法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。


  • 大津算法最终的目的,就是求一个标准的全局阈值区分前景和背景(小于该阈值的为前景。大于该阈值的为背景),使得前景和背景像素的灰度值方差之和最大。因为方差越大,相关性越小,黑白越分明。


  • 大津算法的优势及劣势:对于一些光照变化的图像有较好的滤除性,但需注意,光照部分需影响图像的每一个像素,而不是渐变式影响。这里说的有些抽象,下面我将用图片去解释。


二 理论分析


我们知道,数学中方差公式为:


image.png


如果我们想求整张图像的灰度值方差,那么xi就是各个像素的灰度值,x0就是整张图像的平均灰度值


但在大津算法中,我们默认将图像分为前景和背景,所以方差公式也有一定的变化


大津算法核心公式:

image.png


化简后:


image.png


分析这段公式前,我们不妨设几个参数


h:图像的高度(已知)


w:图像的宽度(已知)(h*w 得到图像的像素数量)


t :灰度阈值(我们要求的值,大于这个值的像素我们将它的灰度设置为255,小于的设置为0)


n0:小于阈值的像素,前景


n1:大于等于阈值的像素,背景


图像像素的个数


image.png


w0:前景像素占总像素的比例


image.png


w1:背景像素占总像素的比例


image.png


u0:前景平均灰度


image.png


u1:背景平均灰度


image.png


u:平均灰度


image.png


最后,标准阈值u从0到255遍历,使得方差最大,并且找出最大方差对应得阈值


三 代码实现


  • 算法库的Python实现


import cv2
import numpy as np
# 大津二值化算法
def otsu(gray_img):
    h = gray_img.shape[0]
    w = gray_img.shape[1]
    threshold_t = 0
    max_g =0
    # 遍历每一个灰度层
    for t in range(255):
        # 使用numpy直接对数组进行运算
        n0 = gray_img[np.where(gray_img <t)]
        n1 = gray_img[np.where(gray_img >=t)]
        w0 = len(n0)/(h*w)
        w1 = len(n1)/(h*w)
        u0 = np.mean(n0) if len(n0) >0 else 0.
        u1 = np.mean(n1) if len(n1) >0 else 0.
        g = w0*w1*(u0-u1)**2
        if g>max_g:
            max_g=g
            threshold_t = t
    print('类间最大方差的阈值:',threshold_t)
    gray_img[gray_img < threshold_t] = 0
    gray_img[gray_img >= threshold_t] =255
    return gray_img
img = cv2.imread('c2.png',0)
otsu_img = otsu(img)
cv2.imshow('otsu_img',otsu_img)
cv2.waitKey(0)
cv2.destroyAllWindows()


  • 大津算法优劣对比


import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('p4.png',0)
#不使用大津算法
ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
#使用大津算法
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#使用了大津算法+高斯滤波器
blur = cv2.GaussianBlur(img,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# 绘制所有图像及其直方图
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()


效果图


532285074d8f65264238f6dfc0f27ebb.png


右边依次是不使用大津算法,使用大津算法,使用了大津算法+高斯滤波器的图像处理结果,也许你看不出来有什么区别


假设现在图像环境的光照减小,亮度变低了(这里我添加一个黑色,透明度为50%的图层模拟)


369fae947b7793355ef98bab0ee58866.png


使用大津算法有着较好的处理结果,这是它最大的优势:可以滤除光照影响


但是,光照若是斜射的(下面我用渐变模拟),那么大津算法将不适用


743ba7aeac723b2033e1ce38d79184de.png

相关文章
|
5月前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
199 7
|
9天前
|
Ubuntu Linux 编译器
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
通过以上步骤,您已经成功在Ubuntu系统下的VS Code中配置了C/C++项目环境,并能够调用OpenCV库进行开发。请确保每一步都按照您的系统实际情况进行适当调整。
114 3
|
9天前
|
算法 计算机视觉 Python
圆形检测算法-基于颜色和形状(opencv)
该代码实现了一个圆检测算法,用于识别视频中的红色、白色和蓝色圆形。通过将图像从RGB转换为HSV颜色空间,并设置对应颜色的阈值范围,提取出目标颜色的区域。接着对这些区域进行轮廓提取和面积筛选,使用霍夫圆变换检测圆形,并在原图上绘制检测结果。
14 0
|
18天前
|
存储 算法 C语言
MacOS环境-手写操作系统-17-内存管理算法实现
MacOS环境-手写操作系统-17-内存管理算法实现
27 0
|
2月前
|
算法 定位技术 vr&ar
一文了解PnP算法,python opencv中的cv2.solvePnP()的使用,以及使用cv2.sovlePnP()方法标定相机和2D激光雷达
一文了解PnP算法,python opencv中的cv2.solvePnP()的使用,以及使用cv2.sovlePnP()方法标定相机和2D激光雷达
294 0
一文了解PnP算法,python opencv中的cv2.solvePnP()的使用,以及使用cv2.sovlePnP()方法标定相机和2D激光雷达
|
4月前
|
机器学习/深度学习 算法 计算机视觉
基于opencv的SVM算法的车牌识别系统设计与实现
基于opencv的SVM算法的车牌识别系统设计与实现
110 2
基于opencv的SVM算法的车牌识别系统设计与实现
|
5月前
|
算法 计算机视觉 Docker
Docker容器中的OpenCV:轻松构建可移植的计算机视觉环境
Docker容器中的OpenCV:轻松构建可移植的计算机视觉环境
Docker容器中的OpenCV:轻松构建可移植的计算机视觉环境
|
4月前
|
移动开发 算法 计算机视觉
技术笔记:openCV特征点识别与findHomography算法过滤
技术笔记:openCV特征点识别与findHomography算法过滤
85 0
|
4月前
|
机器学习/深度学习 编译器 算法框架/工具
OpenCV算法库
numba是一个用于编译Python数组和数值计算函数的编译器,这个编译器能够大幅提高直接使用Python编写的函数的运算速度。
|
5月前
|
算法 计算机视觉
【OpenCV】- 分水岭算法
【OpenCV】- 分水岭算法