本文介绍了多重otsu(多阈值)与openCV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用otsu执行多阈值。我目前使用的方法实际上是通过最大化类间方差,我已经设法获得相同的阈值给定的OpenCV库。但是,这只是通过运行otsu方法一次。



关于如何做多级阈值或相当递归阈值的文档是有限的。我在获得原始otsu的价值后,我该怎么办?感谢一些提示,我一直在玩代码,添加一个外部循环,但下一个值计算总是254任何给定的图像:(



我的代码如果需要:

  //首先计算直方图
cv :: Mat imageh; //图像编辑为灰度直方图目的
// imageh = image; //以下删除和取消注释;
cv :: cvtColor(image,imageh,CV_BGR2GRAY);

int histSize [1] {256}; // number of bins
float hranges [2] = {0.0,256.0}; // min andax像素值
const float * ranges [1] = {hranges};
int channels [1] = {0}; //只使用一个通道

cv :: MatND hist;
//计算直方图
calcHist(& imageh,1 ,channels,cv :: Mat(),hist,1,histSize,ranges);

IplImage * im = new IplImage(imageh); //将图像分配给IplImage指针
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<<总像素数为<<< totalNumberOfPixels< endl;


float sum = 0;
for(int t = 0; t {
sum + = t * hist.at< float>(t)
}
cout<<sum is<< sum<< endl;

float sumB = 0; // background of background
int wB = 0; //背景权重
int wF = 0; //前景的权重

float varMax = 0;
int threshold = 0;

//运行迭代以找到类间方差之间的最大值(类方差之间的最大化)
for(int t = 0; 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; //平均背景
float mF =(sum - sumB)/ wF; //平均前景

//计算类之间的变异
float varBetween =(float)wB *(float)wF *(mB - mF)*(mB - mF)

//检查是否找到了新的最大值
if(varBetween> varMax){
varMax = varBetween;
threshold = t;
}
}

cout<<阈值为


解决方案

要将Otsu的阈值法扩展到多级阈值类间方差方程变为:







希望这有助。


I am trying to carry out multi-thresholding with otsu. The method I am using currently is actually via maximising the between class variance, I have managed to get the same threshold value given as that by the OpenCV library. However, that is just via running otsu method once.

Documentation on how to do multi-level thresholding or rather recursive thresholding is rather limited. Where do I do after obtaining the original otsu's value? Would appreciate some hints, I been playing around with the code, adding one external for loop, but the next value calculated is always 254 for any given image:(

My code if need be:

//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;
解决方案

To extend Otsu's thresholding method to multi-level thresholding the between class variance equation becomes:

Here is my C# implementation of Otsu Multi for 2 thresholds:

/* Otsu (1979) - multi */

Tuple < int, int > otsuMulti(object sender, EventArgs e) {
    //image histogram
    int[] histogram = new int[256];

    //total number of pixels
    int N = 0;

    //accumulate image histogram and total number of pixels
    foreach(int intensity in image.Data) {
        if (intensity != 0) {
            histogram[intensity] += 1;
            N++;
        }
    }

    double W0K, W1K, W2K, M0, M1, M2, currVarB, optimalThresh1, optimalThresh2, maxBetweenVar, M0K, M1K, M2K, MT;

    optimalThresh1 = 0;
    optimalThresh2 = 0;

    W0K = 0;
    W1K = 0;

    M0K = 0;
    M1K = 0;

    MT = 0;
    maxBetweenVar = 0;
    for (int k = 0; k <= 255; k++) {
        MT += k * (histogram[k] / (double) N);
    }


    for (int t1 = 0; t1 <= 255; t1++) {
        W0K += histogram[t1] / (double) N; //Pi
        M0K += t1 * (histogram[t1] / (double) N); //i * Pi
        M0 = M0K / W0K; //(i * Pi)/Pi

        W1K = 0;
        M1K = 0;

        for (int t2 = t1 + 1; t2 <= 255; t2++) {
            W1K += histogram[t2] / (double) N; //Pi
            M1K += t2 * (histogram[t2] / (double) N); //i * Pi
            M1 = M1K / W1K; //(i * Pi)/Pi

            W2K = 1 - (W0K + W1K);
            M2K = MT - (M0K + M1K);

            if (W2K <= 0) break;

            M2 = M2K / W2K;

            currVarB = W0K * (M0 - MT) * (M0 - MT) + W1K * (M1 - MT) * (M1 - MT) + W2K * (M2 - MT) * (M2 - MT);

            if (maxBetweenVar < currVarB) {
                maxBetweenVar = currVarB;
                optimalThresh1 = t1;
                optimalThresh2 = t2;
            }
        }
    }

    return new Tuple(optimalThresh1, optimalThresh2);
}

And this is the result I got by thresholding an image scan of soil with the above code:

(T1 = 110, T2 = 147).

Hope this helps.

这篇关于多重otsu(多阈值)与openCV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-14 01:00