OTSU算法 -- 三通道阈值分割
来源:互联网 发布:太平洋官方软件 编辑:程序博客网 时间:2024/06/04 08:39
otsu 应用
依据像素值的权重,分离图像前景和背景。
otsu 算法确定图像前景和背景阈值
// 关键之处是处理像素值的权重占比// Otsu algorithmint Otsu(const Mat src){ int height = src.rows; int width = src.cols; int size = height * width; unsigned char* data = src.data; // histogram long histogram[256] = { 0 }; // pixel gray value count for (int i = 0; i < height; i++) { unsigned char* p = data + i * src.step; for (int j = 0; j < width; j++) { histogram[int(*p++)]++; } } /* * sum0:前景的灰度总和 sum1:背景灰度总和 * cnt0:前景像素的总个数 cnt1:背景像素的总个数 * w0: 前景像素个数占整幅图像像素的比例 * w1: 背景像素个数占整幅图像像素的比例 * u0: 前景的平均灰度 u1: 背景的平均灰度 * variance: 类间方差 */ long sum0 = 0, sum1 = 0; long cnt0 = 0, cnt1 = 0; double w0 = 0, w1 = 0; double u0 = 0, u1 = 0; double variance = 0; /* * u: 整幅图像的总平均灰度 * maxVariance: 最大类间方差 */ int i, j; double u = 0; double maxVariance = 0; // 目标阈值 int threshold = 0; // 依次遍历每个像素 for (i = 1; i < 256; i++) { // 初始化 sum0 = 0; sum1 = 0; cnt0 = 0; cnt1 = 0; u0 = 0; u1 = 0; w0 = 0; w1 = 0; // 前景 for (j = 0; j < i; j++) { cnt0 += histogram[j]; sum0 += (long)(j * histogram[j]); } // u0:前景平均灰度 w0:前景像素点数量占全部像素点的比例 u0 = (double)(sum0 * 1.0 / cnt0); w0 = (double)(cnt0 * 1.0 / size); // 背景 for (j = i; j <= 255; j++) { cnt1 += histogram[j]; sum1 += (long)(j * histogram[j]); } // u1:背景平均灰度 w1:背景像素点数占全部像素点的比例 u1 = (double)(sum1 * 1.0 / cnt1); w1 = 1 - w0; // u:图像平均灰度 variancn:类间方差 //u = u0 * w0 + u1 * w1; variance = w0 * w1 * (u0 - u1) * (u0 - u1); if (variance > maxVariance) { maxVariance = variance; threshold = i; } } return (threshold);}
分别根据r,g,b三通道的阈值分离图像,再merge(r,g,b)
- 图像分离可采用 opencv split()函数,将Mat格式图像转换为vector格式的图像。
- 合并r, g, b则采用相反的操作,使用opencv merge()函数,将vector格式的图像合并成Mat格式的完整图像。
// splite input imagevoid ThresholdByOtsu(const Mat src, Mat & Dst){ // split Mat src to Vector src_v vector<Mat>src_v; split(src, src_v); imshow("r_src", src_v[0]); imshow("g_src", src_v[1]); imshow("b_src", src_v[2]); // save origin image r, g, b imwrite((g_kOutputPath + "r_src.tiff"), src_v[0]); imwrite((g_kOutputPath + "g_src.tiff"), src_v[1]); imwrite((g_kOutputPath + "b_src.tiff"), src_v[2]); // get threshold int threshold_r, threshold_g, threshold_b = 0; threshold_r = Otsu(src_v[0]); threshold_g = Otsu(src_v[1]); threshold_b = Otsu(src_v[2]); // output r, g, b threshold after otsu. cout << "after otsu:" << endl; cout << "------------------" << endl; cout << "threshold_r:" << threshold_r << endl; cout << "threshold_g:" << threshold_g << endl; cout << "threshold_b:" << threshold_b << endl; // 二值化 vector<Mat>out_v; threshold(src_v[0], src_v[0], threshold_r, 255, CV_THRESH_BINARY); threshold(src_v[1], src_v[1], threshold_g, 255, CV_THRESH_BINARY); threshold(src_v[2], src_v[2], threshold_b, 255, CV_THRESH_BINARY); // save r, g, b image after otsu imwrite((g_kOutputPath + "r_otsu.tiff"), src_v[0]); imwrite((g_kOutputPath + "g_otsu.tiff"), src_v[1]); imwrite((g_kOutputPath + "b_otsu.tiff.tiff"), src_v[2]); // merge three chanels image with r_otsu, g_otsu, b_otsu merge(src_v, Dst); // clear src_v.clear();}
Example
输入图像: http://sipi.usc.edu/database/download.php?vol=misc&img=4.2.04
1. 美丽的Lena女士
2. 原图像 R, G, B 三通道分离,依次输出r,g,b单通道图像如下
3. Otsu() 分别计算图像阈值得到r, g, b单通道阈值
3. 原图像R,G,B三通道,otsu阈值二值化,依次输出如下图像
4. 将二值化的R,G,B三通道进行merge操作,输出OTSU的最终结果
编译环境
More
see more https://github.com/Guguant/anypapers/tree/master/sga
阅读全文
0 0
- OTSU算法 -- 三通道阈值分割
- 自适应阈值分割之otsu算法
- 自适应阈值分割之otsu算法
- Otsu算法寻找灰度图像中最优分割阈值
- 基于Otsu算法的图像自适应阈值分割
- 自适应阈值分割—大津法(OTSU算法)C++实现
- 自适应阈值分割—大津法(OTSU算法)C++实现
- 一种otsu阈值分割方法
- Otsu自适应阈值算法
- opencv学习笔记(十九)单通道固定阈值cvThreshold()以及自适应阈值化 OTSU算法
- 大津法otsu的自动阈值分割源代码
- 大津法otsu的自动阈值分割源代码
- 基于OTSU算法和基本粒子群优化算法的双阈值图像分割
- 基于OTSU算法和基本粒子群优化算法的双阈值图像分割
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- OpenCV的otsu自适应阈值分割的算法在肤色检测中的应用
- otsu自适应阈值分割的算法描述和opencv实现,及其在肤色检测中的应用
- Linux的基础命令
- 结构体数组管理学生简单信息
- Redis 章节学习总结
- 数据压缩实验六
- 思想的变化
- OTSU算法 -- 三通道阈值分割
- Radar Installation(贪心)
- 微信公众号接收回复
- Laravel基础-Eloquent ORM 模型
- Java线程从零开始(三)——进一步认识线程之生命周期
- H.264编码实验
- httpd高并发的实现
- BZOJ 1052 覆盖问题题解
- 数据类型与变量