多级阈值。大津的方法 [英] Multi-Level Thresholding. Otsu's Method

查看:353
本文介绍了多级阈值。大津的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题是可能的重复多otsu(多阈值)与openCV ,因为它非常相似。但是我没有足够的权限对​​此发表评论,所以我的问题被回答。



我试图使用OPENCV库使用Otsu的方法做三级电平阈值。我是按照@ Antoni4发布的指南,但它只涵盖两级阈值,我无法将其扩展到三个级别。



我知道如何原始Otsu的方法工作,最大化类方差之间,但我如何可以添加一个外部(或内部)for循环计算第三级阈值我不知道。



我使用此代码进行两级阈值处理:

  #includeShadow01-1.cuh

void multiThresh(double& optimalThresh1,double& optimalThresh2,double& optimalThresh3,cv :: Mat& imgHist,cv :: Mat& src){
double W0K,W1K,W2K ,W3K,M0,M1,M2,M3,currVarB,maxBetweenVar,M0K,M1K,M2K,M3K,

unsigned char * histogram =(unsigned char *)(imgHist.data);

int N = src.rows * src.cols;
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] // 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] / // Pi
M1K + = t2 *(直方图[t2] /(双)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 * );

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

}
}

/ p>

我实际上不是这两行:

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

如何扩展他们第三个阈值。



提前感谢。

解决方案

修改@reexre
无关紧要。



我实现了第三个内部for循环来添加另一个阈值级别,并使用以下行作为W3K和M3K,即使我还不知道为什么他们是这样的。

  W3K = 1  - (W1K + W2K); 
M3K = MT - (M1K + M2K);

它可以工作。



,然后:

  #includeShadow01-1.cuh

void multiThresh最优Thresh1,double& optimalThresh2,double& optimalThresh3,cv :: Mat& imgHist,cv :: Mat& src)
{
double W0K,W1K,W2K,W3K,M0, M2,M3,currVarB,maxBetweenVar,M0K,M1K,M2K,M3K,MT;
unsigned char * histogram =(unsigned char *)(imgHist.data);

int N = src.rows * src.cols;
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] // 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] / // Pi
M1K + = t2 *(直方图[t2] /(双)N); // i * Pi
M1 = M1K / W1K; //(i * Pi)/ Pi
W2K = 1-(W0K + W1K);
M2K = MT - (M0K + M1K);

if(W2K <= 0)break;

M2 = M2K / W2K;

W2K = 0;
M2K = 0;

for(int t3 = t2 + 1; t3 <= 255; t3 ++)
{
W2K + = histogram [t3] // Pi
M2K + = t3 *(直方图[t3] /(双)N); // i * Pi
M2 = M2K / W2K; //(i * Pi)/ Pi
W3K = 1-(W0K + W1K + W2K);
M3K = MT - (M0K + M1K + M2K);

M3 = M3K / W3K;
currVarB = W0K *(M0-MT)*(M0-MT)+ W1K *(M1-MT)*(M1-MT)+ W2K * (M3-MT)*(M3-MT);

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


I know this Question is a possible duplicate of Multi otsu(multi-thresholding) with openCV as it's very similar. But I don't have enough privileges to make a comment on that so my question is answered.

I'm trying to do THREE level threshold using Otsu's method using OPENCV library. I was following the guides posted by @Antoni4, but it only covers two-level thresholding and I wasn't able to expand it to three level.

I know how to original Otsu's method works, maximizing the between class variance, but how I could add an external (or internal) for-loop for calculating the third level threshold I did not know.

I'm using this code for the two-level thresholding:

#include "Shadow01-1.cuh"

void multiThresh(double &optimalThresh1, double &optimalThresh2,double &optimalThresh3, cv::Mat &imgHist, cv::Mat &src) {
double W0K, W1K, W2K, W3K, M0, M1, M2, M3, currVarB, maxBetweenVar, M0K, M1K, M2K, M3K, MT;

unsigned char *histogram = (unsigned char*)(imgHist.data);

int N = src.rows*src.cols;
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;
        }

    }
}

}

I actually don't what are those two lines:

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

And how I could expand them for the third threshold.

Thanks in advance.

解决方案

[Edit] Fixed a bug reported by @reexre Yeah, never mind.

I implemented a third inner for-loop to add another threshold level and used the following lines as the W3K and M3K, even though I still don't know why they are like this.

W3K = 1 - (W1K + W2K);
M3K = MT - (M1K + M2K);

It works.

Whole code is, then:

#include "Shadow01-1.cuh"

void multiThresh(double &optimalThresh1, double &optimalThresh2, double &optimalThresh3, cv::Mat &imgHist, cv::Mat &src)
{
double W0K, W1K, W2K, W3K, M0, M1, M2, M3, currVarB, maxBetweenVar, M0K, M1K, M2K, M3K, MT;
unsigned char *histogram = (unsigned char*)(imgHist.data);

int N = src.rows*src.cols;
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;

        W2K = 0;
        M2K = 0;

        for (int t3 = t2 + 1; t3 <= 255; t3++)
        {
            W2K += histogram[t3] / (double) N; //Pi
            M2K += t3 * (histogram[t3] / (double) N); // i*Pi
            M2 = M2K / W2K; //(i*Pi)/Pi
            W3K = 1 - (W0K + W1K + W2K);
            M3K = MT - (M0K + M1K + M2K);

            M3 = M3K / W3K;
            currVarB = W0K * (M0 - MT) * (M0 - MT) + W1K * (M1 - MT) * (M1 - MT) + W2K * (M2 - MT) * (M2 - MT) + W3K * (M3 - MT) * (M3 - MT);

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

这篇关于多级阈值。大津的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆