2016-01-28 49 views
1

我想實現多級大津的閾值,更具體地說,我需要3個閾值/ 4類。多級(4)Otsu閾值

我知道關於它的2個similair問題:#34856019和#22706742。 問題是我沒有得到好的結果:我閱讀了幾篇文章,其中的代碼圖片和代碼發現的閾值與這些論文中的不同。

比方說,我有一個黑色背景上的3個圈圖片,圓圈的亮度從非常明亮的不同而不同暗:

Sample Image

我說得對的假設得到的結果是4班級:黑色背景和3個班級的強度?

我的節目給了我這些閾值:226,178,68

其結果是,第三圈是完全看不見的 - 這是在同一個班作爲背景。

有人可以檢查這些值和/或源代碼嗎?也許有可能使用Matlab或其他方式檢查此圖像... 順便說一句,通過零處理分割的最佳方法是什麼?這種方法通常在直方圖中出現零值? 源代碼:

void MultilevelThresholding(cv::Mat& src) 
{ 
    int histogram[256] = { 0 }; 
    int pixelsCount = src.cols * src.rows; 

    for (int y = 0; y < src.rows; y++) 
    { 
     for (int x = 0; x < src.cols; x++) 
     { 
      uchar value = src.at<uchar>(y, x); 
      histogram[value]++; 
     } 
    } 

    double c = 0; 
    double Mt = 0; 

    double p[256] = { 0 }; 
    for (int i = 0; i < 256; i++) 
    { 
     p[i] = (double) histogram[i]/(double) pixelsCount; 
     Mt += i * p[i]; 
    } 

    int optimalTreshold1 = 0; 
    int optimalTreshold2 = 0; 
    int optimalTreshold3 = 0; 

    double maxBetweenVar = 0; 

    double w0 = 0; 
    double m0 = 0; 
    double c0 = 0; 
    double p0 = 0; 

    double w1 = 0; 
    double m1 = 0; 
    double c1 = 0; 
    double p1 = 0; 

    double w2 = 0; 
    double m2 = 0; 
    double c2 = 0; 
    double p2 = 0; 
    for (int tr1 = 0; tr1 < 256; tr1++) 
    { 
     p0 += p[tr1]; 
     w0 += (tr1 * p[tr1]); 
     if (p0 != 0) 
     { 
      m0 = w0/p0; 
     } 

     c0 = p0 * (m0 - Mt) * (m0 - Mt); 

     c1 = 0; 
     w1 = 0; 
     m1 = 0; 
     p1 = 0; 
     for (int tr2 = tr1 + 1; tr2 < 256; tr2++) 
     { 

      p1 += p[tr2]; 
      w1 += (tr2 * p[tr2]); 
      if (p1 != 0) 
      { 
       m1 = w1/p1; 
      } 

      c1 = p1 * (m1 - Mt) * (m1 - Mt); 


      c2 = 0; 
      w2 = 0; 
      m2 = 0; 
      p2 = 0; 
      for (int tr3 = tr2 + 1; tr3 < 256; tr3++) 
      { 

       p2 += p[tr3]; 
       w2 += (tr3 * p[tr3]); 
       if (p2 != 0) 
       { 
        m2 = w2/p2; 
       } 

       c2 = p2 * (m2 - Mt) * (m2 - Mt); 

       c = c0 + c1 + c2; 

       if (maxBetweenVar < c) 
       { 
        maxBetweenVar = c; 
        optimalTreshold1 = tr1; 
        optimalTreshold2 = tr2; 
        optimalTreshold3 = tr3; 
       } 
      } 
     } 
    } 
+0

添加一個大的中值濾波器來消除邊緣處的衰落效應?你是否嘗試k-means聚類(4簇)而不是otsu? – Micka

+0

是的,我可以添加任何我想要的過濾器,但這只是一個例子 - 問題是關於Otsu及其閾值。你認爲這樣做對嗎? – natan337

+0

我不知道,但它看起來像你的代碼只承擔3閾值(optimalThreshold1-3)而不是4? – Micka

回答

2

所以,我已經想通了。

// cv::Mat& src - source image's matrix 
    int histogram[256] = { 0 }; 
    int pixelsCount = src.cols * src.rows; 

    for (int y = 0; y < src.rows; y++) 
    { 
     for (int x = 0; x < src.cols; x++) 
     { 
      uchar value = src.at<uchar>(y, x); 
      histogram[value]++; 
     } 
    } 

    double c = 0; 
    double Mt = 0; 

    double p[256] = { 0 }; 
    for (int i = 0; i < 256; i++) 
    { 
     p[i] = (double) histogram[i]/(double) pixelsCount; 
     Mt += i * p[i]; 
    } 

    int optimalTreshold1 = 0; 
    int optimalTreshold2 = 0; 
    int optimalTreshold3 = 0; 

    double maxBetweenVar = 0; 

    double w0 = 0; 
    double m0 = 0; 
    double c0 = 0; 
    double p0 = 0; 

    double w1 = 0; 
    double m1 = 0; 
    double c1 = 0; 
    double p1 = 0; 

    double w2 = 0; 
    double m2 = 0; 
    double c2 = 0; 
    double p2 = 0; 
    for (int tr1 = 0; tr1 < 256; tr1++) 
    { 
     p0 += p[tr1]; 
     w0 += (tr1 * p[tr1]); 
     if (p0 != 0) 
     { 
      m0 = w0/p0; 
     } 

     c0 = p0 * (m0 - Mt) * (m0 - Mt); 

     c1 = 0; 
     w1 = 0; 
     m1 = 0; 
     p1 = 0; 
     for (int tr2 = tr1 + 1; tr2 < 256; tr2++) 
     { 

      p1 += p[tr2]; 
      w1 += (tr2 * p[tr2]); 
      if (p1 != 0) 
      { 
       m1 = w1/p1; 
      } 

      c1 = p1 * (m1 - Mt) * (m1 - Mt); 


      c2 = 0; 
      w2 = 0; 
      m2 = 0; 
      p2 = 0; 
      for (int tr3 = tr2 + 1; tr3 < 256; tr3++) 
      { 

       p2 += p[tr3]; 
       w2 += (tr3 * p[tr3]); 
       if (p2 != 0) 
       { 
        m2 = w2/p2; 
       } 

       c2 = p2 * (m2 - Mt) * (m2 - Mt); 

       double p3 = 1 - (p0 + p1 + p2); 
       double w3 = Mt - (w0 + w1 + w2); 
       double m3 = w3/p3; 
       double c3 = p3 * (m3 - Mt) * (m3 - Mt); 

       double c = c0 + c1 + c2 + c3; 

       if (maxBetweenVar < c) 
       { 
        maxBetweenVar = c; 
        optimalTreshold1 = tr1; 
        optimalTreshold2 = tr2; 
        optimalTreshold3 = tr3; 
       } 
      } 
     } 
    } 

Source image

enter image description here

Result: 3 thresholds/4 classes

enter image description here 閾值::4類(3個閾值)大津的閾值的最終源代碼179,92,25

你可以試試
+1

什麼是worng?你能詳細說明嗎? –