2015-10-20 114 views
0

我想二值化低質量的圖像,發現現有的全局和局部二值化技術(如Sauvola方法,NiBlack方法等)的解決方案或程序沒有多大用處。在opencv中使用較新的算法進行圖像二值化

我沒有找到關於喜歡在報紙上給出的要好得多方法的幾篇好論文: 1)http://www.ski.org/sites/default/files/publications/wacv11-display-reader.pdf#cite.adap-binar 2)https://www.jstage.jst.go.jp/article/elex/1/16/1_16_501/_pdf

但我還沒有像之前的工作處理得多,所以我想知道我可以如何執行它,以及我需要什麼知識來實現​​這些算法

+0

您應該首先以易於編碼的方式實現它(以便與解決方案進行比較)並在稍後關注優化。從論文中您只需知道如何計算子圖像的均值和方差。 – Micka

+0

但是提到的矩陣呢?如何從源圖像構建它? –

+0

你只是對二值化(2.1)感興趣嗎? – Micka

回答

1

我在第10分鐘(比處理第二張圖像的時間少)的時間實現了第一張紙的二值化 - 不保證它是正確的,最好親自看看公式:

int main() 
{ 
    //cv::Mat input = cv::imread("../inputData/Lenna.png"); 
    cv::Mat input = cv::imread("../inputData/LongLineColor.jpg"); 

    cv::Mat gray; 
    cv::cvtColor(input,gray,CV_BGR2GRAY); 


    cv::Mat binaryImage = cv::Mat::zeros(gray.rows, gray.cols, CV_8UC1); 

    // binarization: 

    // TODO: adjust to your application: 
    int smallWindowSize = 17; // suggested by the paper 
    int bigWindowSize = 35; // suggested by the paper 

    // TODO: adjust to your application 
    double minTau = 10 ; 

    // create roi relative to (0,0) 
    cv::Rect roiTemplate1 = cv::Rect(-smallWindowSize/2,-smallWindowSize/2, smallWindowSize, smallWindowSize); 
    cv::Rect roiTemplate2 = cv::Rect(-bigWindowSize/2,-bigWindowSize/2, bigWindowSize, bigWindowSize); 

    cv::Rect imgROI = cv::Rect(0,0, gray.cols, gray.rows); 

    for(int y=0; y<gray.rows; ++y) 
    { 
     std::cout << y << std::endl; 
     for(int x=0; x<gray.cols; ++x) 
     { 
      double pixelThreshold = 255; 

      // small roi 
      cv::Rect cROIs = roiTemplate1 + cv::Point(x,y); 
      // test whether ROI is inside the image. Reduce otherwise: 
      cROIs = cROIs & imgROI; 
      if(cROIs.width == 0 || cROIs.height == 0) 
       continue; // ignore this pixel 

      // large roi 
      cv::Rect cROIl = roiTemplate2 + cv::Point(x,y); 
      cROIl = cROIl & imgROI; 
      if(cROIl.width == 0 || cROIl.height == 0) 
       continue; // ignore this pixel 

      cv::Mat subSmall = gray(cROIs); 
      cv::Mat subLarge = gray(cROIl); 

      // evaluate subimages: 
      // standard deviations 
      double stdDevS =0; 
      double stdDevL =0; 
      // mean value 
      double meanS =0; 
      double minL =DBL_MAX; 
      double meanL =0; 

      // mean of small region 
      for(int j=0; j<subSmall.rows; ++j) 
       for(int i=0; i<subSmall.cols; ++i) 
       { 
        meanS += subSmall.at<unsigned char>(j,i); 
       } 
      meanS = meanS/ (double)(subSmall.cols*subSmall.rows); 


      // stddev of small region 
      for(int j=0; j<subSmall.rows; ++j) 
       for(int i=0; i<subSmall.cols; ++i) 
       { 
        double diff = subSmall.at<unsigned char>(j,i) - meanS; 
        stdDevS += diff*diff; 
       } 
      stdDevS = sqrt(stdDevS/(double)(subSmall.cols*subSmall.rows)); 



      // mean and min of large region 
      for(int j=0; j<subLarge.rows; ++j) 
       for(int i=0; i<subLarge.cols; ++i) 
       { 
        if(subLarge.at<unsigned char>(j,i) < minL) 
        { 
         minL = subLarge.at<unsigned char>(j,i); 
         meanL += subLarge.at<unsigned char>(j,i); 
        } 
       } 
      meanL = meanL/ (double)(subLarge.cols*subLarge.rows); 

      // stddef of large region 
      for(int j=0; j<subLarge.rows; ++j) 
       for(int i=0; i<subLarge.cols; ++i) 
       { 
        double diff = subLarge.at<unsigned char>(j,i) - meanL; 
        stdDevL += diff*diff; 
       } 
      stdDevL = sqrt(stdDevL/(double)(subLarge.cols*subLarge.rows)); 

      // formula (2) 
      double tau = ((meanS - minL) * (1-stdDevS/stdDevL))/2.0; 
      // minimum 
      if(tau < minTau) tau = minTau; 

      // formula (1) 
      double Threshold = meanS - tau; 


      // for debugging: 
      /* 
      std::cout << " meanS:" << meanS << std::endl; 
      std::cout << " std S:" << stdDevS << std::endl; 
      std::cout << " min L:" << minL << std::endl; 
      std::cout << " meanL:" << meanL << std::endl; 
      std::cout << " std L:" << stdDevL << std::endl; 
      std::cout << " threshold: " << Threshold << std::endl; 
      */ 


      unsigned char pixelVal = gray.at<unsigned char>(y,x); 
      if(pixelVal >= Threshold) 
       binaryImage.at<unsigned char>(y,x) = 255; 
      else 
       binaryImage.at<unsigned char>(y,x) = 0; 
     } 
    } 



    cv::imshow("input", input); 
    cv::imshow("binary", binaryImage); 
    //cv::imwrite("../outputData/binaryCustom.png", binaryImage); 
    cv::waitKey(0); 
    return 0; 
} 

給我的結果:

enter image description hereenter image description here

enter image description hereenter image description here

這是非常緩慢的,但不是最優化或包裹在所有;) 而結果AREN我真的很好。可能您必須將windowSizes調整爲您的應用程序/任務/ objectSize

+0

我試過這個和m用例,它肯定給出了一個更好的結果,但遠離我的要求。它也需要很多優化,因爲它非常慢。 我可能必須一起尋找替代解決方案(即不遵循二進制化方法)。感謝您的幫助。 –

相關問題