OTSU算法(大津法—最大类间方差法)原理及实现
初始化:统计图像中每个灰度级的像素数,计算每个灰度级的概率。 累计计算:逐步累加概率和累计均值。 类间方差计算:遍历所有灰度级,计算每个阈值对应的类间方差。 寻找最优阈值:找出使类间方差最大的灰度级作为最终阈值。
图像分辨率:702 × 648 分割质量:与OpenCV自带函数一致 分辨率对比:本文实现与OpenCV自带函数对比,分割效果一致
发布日期:2025-06-18 16:19:27
浏览次数:4
分类:精选文章
本文共 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;}
功能说明
实施效果
阈值分割效果
阈值准确性
- 计算时间:约1ms,运行效率较高
- 阈值精度:与OpenCV自带函数一致
参考资料
- OpenCV官方文档
- GitHub:欢迎Star、Fork
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2026年05月26日 20时20分13秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!