博客
关于我
OTSU算法(大津法—最大类间方差法)原理及实现
阅读量:798 次
发布时间:2023-04-15

本文共 3122 字,大约阅读时间需要 10 分钟。

大津法(OTSU)图像阈值分割算法详解

大津法(OTSU)是一种经典的图像二值化阈值分割算法,由日本学者大津在1979年提出。其核心思想是通过最大化图像两部分之间的类间方差来确定最优的阈值。这种方法被广泛认为是图像分割中阈值选取的最佳方案,因其计算简单且不受图像亮度和对比度的影响。


算法原理

大津法的核心在于计算图像中灰度级的类间方差,并找出使类间方差最大的阈值。具体步骤如下:

  • 初始化统计数据:首先统计图像中每个灰度级的像素数量,计算每个灰度级的概率分布(概率密度函数)。

  • 计算累计概率和累计均值:遍历所有灰度级,逐步累加概率和累计均值。

  • 计算类间方差:对于每个灰度级k,计算其与全局均值的类间方差。具体公式为:[\sigma^2 = \frac{(mG \cdot p_k - m_k)^2}{p_k \cdot (1 - p_k)}]其中,(mG)为图像全局均值,(p_k)为灰度级k的概率,(m_k)为灰度级k的累计均值。

  • 寻找最大类间方差:遍历所有灰度级,找出使得类间方差最大的k值,这个k值即为OTSU算法的阈值。


  • OpenCV实现

    OpenCV提供了OTSU算法的接口,函数定义如下:

    double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)

    代码实现

    #include 
    #include
    #include
    #include
    using namespace cv;int Otsu(Mat& src, Mat& dst, int thresh) { const int Grayscale = 256; int graynum[Grayscale] = {0}; int r = src.rows; int c = src.cols; for (int i = 0; i < r; ++i) { const uchar* ptr = src.ptr(i); for (int j = 0; j < c; ++j) { graynum[ptr[j]]++; } } double P[Grayscale] = {0}; double PK[Grayscale] = {0}; double MK[Grayscale] = {0}; double sumtmpPK = 0, sumtmpMK = 0; for (int i = 0; i < Grayscale; ++i) { P[i] = graynum[i] / (r * c); PK[i] = sumtmpPK + P[i]; sumtmpPK = PK[i]; MK[i] = sumtmpMK + i * P[i]; sumtmpMK = MK[i]; } double Var = 0; int best_thresh = thresh; for (int k = 0; k < Grayscale; ++k) { double numerator = (MK[Grayscale-1] * PK[k] - MK[k]); double denominator = PK[k] * (1 - PK[k]); if (denominator == 0) continue; double current_var = numerator * numerator / denominator; if (current_var > Var) { Var = current_var; best_thresh = k; } } if (best_thresh != thresh) { src.copyTo(dst); for (int i = 0; i < r; ++i) { uchar* ptr = dst.ptr(i); for (int j = 0; j < c; ++j) { if (ptr[j] > best_thresh) ptr[j] = 255; else ptr[j] = 0; } } } return best_thresh;}int main() { Mat src = cv::imread("I:\\Learning-and-Practice\\Img\\Fig1039(a)(polymersomes).tif"); if (src.empty()) { return -1; } if (src.channels() > 1) { cvtColor(src, src, CV_RGB2GRAY); } Mat dst, dst2; int thresh = 0; // 通过OTSU算法计算阈值 thresh = Otsu(src, dst, thresh); // 使用OpenCV自带函数计算阈值 double Otsu_thresh = threshold(src, dst2, thresh, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); cout << "Mythresh=" << thresh << endl; cout << "OpenCVthresh=" << Otsu_thresh << endl; namedWindow("src", CV_WINDOW_NORMAL); imshow("src", src); namedWindow("dst", CV_WINDOW_NORMAL); imshow("dst", dst); namedWindow("dst2", CV_WINDOW_NORMAL); imshow("dst2", dst2); waitKey(0); return 0;}

    功能说明

  • 初始化:统计图像中每个灰度级的像素数,计算每个灰度级的概率。
  • 累计计算:逐步累加概率和累计均值。
  • 类间方差计算:遍历所有灰度级,计算每个阈值对应的类间方差。
  • 寻找最优阈值:找出使类间方差最大的灰度级作为最终阈值。

  • 实施效果

    阈值分割效果

  • 图像分辨率:702 × 648
  • 分割质量:与OpenCV自带函数一致
  • 分辨率对比:本文实现与OpenCV自带函数对比,分割效果一致
  • 阈值准确性

    • 计算时间:约1ms,运行效率较高
    • 阈值精度:与OpenCV自带函数一致

    参考资料

    • OpenCV官方文档
    • GitHub:欢迎Star、Fork

    转载地址:http://xrrfk.baihongyu.com/

    你可能感兴趣的文章
    MySQLSyntaxErrorException: Unknown error 1146和SQLSyntaxErrorException: Unknown error 1146
    查看>>
    Mysql_Postgresql中_geometry数据操作_st_astext_GeomFromEWKT函数_在java中转换geometry的16进制数据---PostgreSQL工作笔记007
    查看>>
    mysql_real_connect 参数注意
    查看>>
    mysql_secure_installation初始化数据库报Access denied
    查看>>
    MySQL_西安11月销售昨日未上架的产品_20161212
    查看>>
    Mysql——深入浅出InnoDB底层原理
    查看>>
    MySQL“被动”性能优化汇总
    查看>>
    MySQL、HBase 和 Elasticsearch:特点与区别详解
    查看>>
    MySQL、Redis高频面试题汇总
    查看>>
    MYSQL、SQL Server、Oracle数据库排序空值null问题及其解决办法
    查看>>
    mysql一个字段为空时使用另一个字段排序
    查看>>
    MySQL一个表A中多个字段关联了表B的ID,如何关联查询?
    查看>>
    MYSQL一直显示正在启动
    查看>>
    MySQL一站到底!华为首发MySQL进阶宝典,基础+优化+源码+架构+实战五飞
    查看>>
    MySQL万字总结!超详细!
    查看>>
    Mysql下载以及安装(新手入门,超详细)
    查看>>
    MySQL不会性能调优?看看这份清华架构师编写的MySQL性能优化手册吧
    查看>>
    MySQL不同字符集及排序规则详解:业务场景下的最佳选
    查看>>
    Mysql不同官方版本对比
    查看>>
    MySQL与Informix数据库中的同义表创建:深入解析与比较
    查看>>