首页 文章

如何提高otsu阈值输出

提问于
浏览
2

我在图像上使用 otsu threshold .
这是输入图像:

enter image description here

这是输出:

enter image description here

这是我正在使用的代码:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <math.h>

using namespace std;
using namespace cv;

int main(int argc, char const *argv[]) {
  title("Text Extractor");
  string win_name = "textextractor";
  Mat img_a;

  img_a = imread("../input/test_c.jpg");

  Mat img_a_gray;
  cvtColor(img_a, img_a_gray, CV_BGR2GRAY);

  Mat img_a_blur;    
  GaussianBlur(img_a_gray, img_a_blur, Size(3, 3), 0, 0);

  Mat img_a_thres;
  // adaptiveThreshold(img_a_blur, img_a_thres, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 5, 4);
  threshold(img_a_blur, img_a_thres, 0, 255, THRESH_OTSU);
  namedWindow(win_name + "_a", CV_WINDOW_AUTOSIZE);
  imshow(win_name + "_a", img_a_thres);

  imwrite("../output/output_a.jpg", img_a_thres);

  waitKey(0);
  return 0;
}

问题是输出在底部和左侧有一个黑色区域 . 我该怎么做才能最小化/删除它?

编辑:

我试过 equalizeHist() ,我得到了这个:

enter image description here

将尝试将图像分解成碎片并单独处理它们 .

对不起这是我的错 . 前一个是使用自适应过滤 . 使用 Otsu 我得到这个:

enter image description here

otsu的输出没有变化:/

编辑2:完成了Feng Tan算法,它提供了更好的结果,但是文本没有清晰度 .

码:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/photo/photo.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <math.h>

using namespace std;
using namespace cv;

int main(int argc, char const *argv[]) {
  string win_name = "textextractor";

  Mat img_c;
  img_c = imread("../input/sample.jpg");

  Mat img_c_gray;
  cvtColor(img_c, img_c_gray, CV_BGR2GRAY);

  Mat img_c_bin = Mat::zeros(img_c_gray.rows, img_c_gray.cols, CV_8UC1);

  int s_win = 17;
  int l_win = 35;

  double min_tau = 10;

  Rect roi_s = Rect(-s_win/2, -s_win/2, s_win, s_win);
  Rect roi_l = Rect(-l_win/2, -l_win/2, l_win, l_win);
  Rect img_c_roi = Rect(0, 0, img_c_gray.cols, img_c_gray.rows);

  for (size_t r = 0; r < img_c_gray.rows; r++) {
    for (size_t c = 0; c < img_c_gray.cols; c++) {
      double pthres = 255;

      Rect sROI = roi_s + Point(c, r);
      sROI = sROI & img_c_roi;
      if(sROI.width == 0 || sROI.height == 0) {
        continue;
      }

      Rect lROI = roi_l + Point(c, r);
      lROI = lROI & img_c_roi;
      if(lROI.width == 0 || lROI.height == 0) {
        continue;
      }

      Mat sROI_gray = img_c_gray(sROI);
      Mat lROI_gray = img_c_gray(lROI);

      double s_stdDev = 0;
      double l_stdDev = 0;
      double s_mean = 0;
      double l_mean = 0;
      double l_min = DBL_MAX;

      for (size_t r = 0; r < sROI_gray.rows; r++) {
        for (size_t c = 0; c < sROI_gray.cols; c++) {
          s_mean += sROI_gray.at<unsigned char>(r, c);
        }
      }

      s_mean = s_mean / static_cast<double> (sROI_gray.cols * sROI_gray.rows);

      for (size_t r = 0; r < sROI_gray.rows; r++) {
        for (size_t c = 0; c < sROI_gray.cols; c++) {
          double diff = sROI_gray.at<unsigned char> (r, c) - s_mean;
          s_stdDev += diff * diff;
        }
      }

      s_stdDev = sqrt(s_stdDev / static_cast<int> (sROI_gray.cols * sROI_gray.rows));

      for (size_t r = 0; r < lROI_gray.rows; r++) {
        for (size_t c = 0; c < lROI_gray.cols; c++) {
          l_mean += lROI_gray.at<unsigned char> (c, r);

          if(lROI_gray.at<unsigned char> (r, c) < l_min) {
            l_min = lROI_gray.at<unsigned char> (r, c);
          }
        }
      }
      l_mean = l_mean / static_cast<double> (lROI_gray.cols * lROI_gray.rows);

      for (size_t r = 0; r < lROI_gray.rows; r++) {
        for (size_t c = 0; c < lROI_gray.cols; c++) {
          double diff = lROI_gray.at<unsigned char> (r, c) - l_mean;
          l_stdDev += diff * diff;
        }
      }
      l_stdDev = sqrt(l_stdDev / static_cast<double> (lROI_gray.cols * lROI_gray.rows));

      double tau = ((s_mean - l_min) * (1 - s_stdDev / l_stdDev)) / 2.0;
      if(tau < min_tau) {
        tau = min_tau;
      }

      double threshold = s_mean - tau;

      unsigned char pixel_val = img_c_gray.at<unsigned char>(r, c);
      if(pixel_val >= threshold) {
        img_c_bin.at<unsigned char> (r, c) = 255;
      } else {
        img_c_bin.at<unsigned char> (r, c) = 0;
      }
    }
  }

  namedWindow(win_name + "_c", CV_WINDOW_AUTOSIZE);
  imshow(win_name + "_c", img_c_bin);

  imwrite("../output/output_c.jpg", img_c_bin);
  waitKey(0);
  return 0;
}

输出:

enter image description here

2 回答

  • 0

    这是我在一些试验和运行后能够获得的 . 最初我 median blurred 原始图像 . 然后我将 adpative threshold 应用于模糊图像 .

    这就是我得到的:

    1. Adaptive Threshold using Gaussian filter:

    enter image description here

    2. Adaptive Threshold using Mean filter:

    enter image description here

    从这里开始,您可以执行一系列最适合您最终图像的形态学操作 . :)

  • 1

    你应该尝试使用CLAHE .

    我在MATLAB上尝试使用:

    Ia = imread('FHXTJ.jpg');
    I = rgb2gray(Ia);
    A = adapthisteq(I, 'clipLimit', 0.02, 'Distribution', 'rayleigh');
    

    结果:
    CLAHE Result

    注意:您可以对此图像应用阈值处理 . 大津现在应该工作正常 .

    Threshold 65, 152

相关问题