我正在尝试用otsu进行多阈值处理 . 我目前使用的方法实际上是通过最大化类间差异,我已经设法获得与OpenCV库相同的阈值 . 但是,这只是通过运行otsu方法一次 .
关于如何进行多级阈值处理或者更确切地说是递归阈值处理的文档相当有限 . 获得原始otsu的 Value 后我该怎么办?会欣赏一些提示,我一直在玩代码,添加一个外部for循环,但计算的下一个值对于任何给定的图像总是254 :(
我的代码如果需要:
//compute histogram first
cv::Mat imageh; //image edited to grayscale for histogram purpose
//imageh=image; //to delete and uncomment below;
cv::cvtColor(image, imageh, CV_BGR2GRAY);
int histSize[1] = {256}; // number of bins
float hranges[2] = {0.0, 256.0}; // min andax pixel value
const float* ranges[1] = {hranges};
int channels[1] = {0}; // only 1 channel used
cv::MatND hist;
// Compute histogram
calcHist(&imageh, 1, channels, cv::Mat(), hist, 1, histSize, ranges);
IplImage* im = new IplImage(imageh);//assign the image to an IplImage pointer
IplImage* finalIm = cvCreateImage(cvSize(im->width, im->height), IPL_DEPTH_8U, 1);
double otsuThreshold= cvThreshold(im, finalIm, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU );
cout<<"opencv otsu gives "<<otsuThreshold<<endl;
int totalNumberOfPixels= imageh.total();
cout<<"total number of Pixels is " <<totalNumberOfPixels<< endl;
float sum = 0;
for (int t=0 ; t<256 ; t++)
{
sum += t * hist.at<float>(t);
}
cout<<"sum is "<<sum<<endl;
float sumB = 0; //sum of background
int wB = 0; // weight of background
int wF = 0; //weight of foreground
float varMax = 0;
int threshold = 0;
//run an iteration to find the maximum value of the between class variance(as between class variance shld be maximise)
for (int t=0 ; t<256 ; t++)
{
wB += hist.at<float>(t); // Weight Background
if (wB == 0) continue;
wF = totalNumberOfPixels - wB; // Weight Foreground
if (wF == 0) break;
sumB += (float) (t * hist.at<float>(t));
float mB = sumB / wB; // Mean Background
float mF = (sum - sumB) / wF; // Mean Foreground
// Calculate Between Class Variance
float varBetween = (float)wB * (float)wF * (mB - mF) * (mB - mF);
// Check if new maximum found
if (varBetween > varMax) {
varMax = varBetween;
threshold = t;
}
}
cout<<"threshold value is: "<<threshold;
6 回答
为了将Otsu的阈值方法扩展到多级阈值处理,类间方差方程变为:
这是我的Otsu Multi的C#实现2阈值:
这是我用以上代码对土壤图像扫描进行阈值处理得到的结果:
(T1 = 110,T2 = 147) .
希望这可以帮助 .
我已经写过一个关于otsu阈值处理如何在python中工作的例子 . 你可以在这里看到源代码:https://github.com/subokita/Sandbox/blob/master/otsu.py
在示例中有2个变体,otsu2()是优化版本,如维基百科页面上所见,而otsu()是基于算法描述本身的更天真的实现 .
如果你可以阅读python代码(在这种情况下,它们非常简单,几乎是伪代码),你可能想看看示例中的otsu()并修改它 . 将它移植到C代码也不难 .
@ Antoni4在我看来给出了最好的答案,并且非常直接地增加了关卡数量 .
这是针对三级阈值处理:
@Guilherme Silva
你的代码有一个BUG
你必须替换:
同
和
同
;-) 问候
编辑(1):[Toby Speight]我发现这个错误是通过将效果应用于不同重塑(Sizes)的相同图片,并看到输出结果彼此差异很大(甚至更改分辨率)
W3K和M3K必须是总数减去前一个WK和MK . (我认为这与代码相似性与一个级别较少的那个)目前由于我缺乏英语我无法解释更好的方式和为什么
说实话,我仍然不能100%确定这种方式是正确的,即使从我的输出中我也可以看出它可以提供更好的结果 . (即使有1级以上(5级灰色))你可以试试自己;-)抱歉
我的输出:
3 Thresholds 4 Thresholds
我在这个帖子中找到了一段有用的代码 . 我正在寻找双层/浮点图像的多级Otsu实现 . 所以,我试图用双/浮点矩阵作为输入推广N级的例子 . 在我的下面的代码中,我使用armadillo库作为依赖 . 但是这个代码可以很容易地适应标准的C数组,只需用单维双重和整数数组替换vec,uvec对象,使用二维替换mat和umat . 这里使用的犰狳的另外两个函数是:vectorise和hist .
以下是 python (> 3.0)中'n'阈值的简单通用方法:
有关完整论文和更多信息,请访问this link .