【问题标题】:How to recognize digits from the analog counter?如何识别模拟计数器中的数字?
【发布时间】:2015-10-27 09:50:51
【问题描述】:

我正在尝试从柜台读取以下千瓦时数字。问题是 tesseract OCR 无法识别模拟数字。

问题是:将所有数字(从 0 到 9)的照片制作在不同位置(我的意思是当数字在中心,当它有点在顶部和数字 2 出现等)并尝试图像识别而不是文本识别?

据我了解,区别在于,图像识别是比较照片,而文字识别……嗯,我不知道……

有什么建议吗?

【问题讨论】:

    标签: opencv image-processing tesseract image-recognition text-recognition


    【解决方案1】:

    由于计数器不是数字的,而是模拟的,所以我们在转换时遇到了问题。文本/数字识别库无法识别那样的东西。我找到的解决方案是:机器学习

    首先我让用户制作图片,其中数字占图片的 70-80%(以删除不需要的细节)。

    然后我正在寻找平行线(如果有的话)并剪切图片,即它们之间的图片(如果距离足够大)。

    之后我对图片进行过滤(使用对比度、亮度,设置灰度)然后使用过滤器,使图像只包含两种颜色(#000000(黑色)和#ffffff(白色) ))。为了更容易找到轮廓。

    然后我使用Canny 算法找到轮廓,并通过删除不需要的细节来过滤它们。

    之后我使用K-Nearest-Neighbour 算法来识别数字。

    但在我识别任何东西之前,我需要教算法,数字的样子以及它们是什么。

    希望对你有用!

    【讨论】:

      【解决方案2】:

      也许您没有正确配置 tesseract。我用它编写了一个代码来解决你的问题:

      #include <opencv2/highgui/highgui.hpp>
      #include <opencv2/imgproc/imgproc.hpp>
      #include <tesseract/baseapi.h>
      #include <iostream>
      
      using namespace cv;
      
      int main(int argc, char** argv)
      {
          cv::Mat input = cv::imread("img.jpg");
      
          //rectangle containing just the kWh numbers
          Rect roi(358,327,532,89);
      
          //convert to gray scale
          Mat input_gray;
          cvtColor(input(roi),input_gray,CV_BGR2GRAY);
      
          //threshold image
          Mat binary_img = input_gray>200;
      
          //make a copy to use on findcontours
          Mat copy_binary_img = binary_img.clone();
      
          vector<vector<Point> > contours;
          vector<Vec4i> hierarchy;
      
          //identify each blob in order to eliminate the small ones 
          findContours(copy_binary_img, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));
      
          //filter blobs by their sizes
          for (vector<vector<Point> >::iterator it = contours.begin(); it!=contours.end(); )
          {
              if (it->size()>20)
                  it=contours.erase(it);
              else
                  ++it;
          }
      
          //Erase blobs which have countour size smaller than 20
          for( int i = 0; i< contours.size(); i++ )
          {
              drawContours( binary_img, contours, i, 0, -1, 8, hierarchy, 0, Point() );
          }
      
          //initialize tesseract OCR
          tesseract::TessBaseAPI tess;
          tess.Init(NULL, "eng", tesseract::OEM_DEFAULT);
      
          tess.SetVariable("tessedit_char_whitelist", "0123456789-.");
      
          tess.SetPageSegMode(tesseract::PSM_SINGLE_BLOCK);
      
          //set input 
          tess.SetImage((uchar*)binary_img.data
                  , binary_img.cols
                  , binary_img.rows
                  , 1
                  , binary_img.cols);
      
          // Get the text
          char* out = tess.GetUTF8Text();
          std::cout << out << std::endl;
          waitKey();
          return 0;
      }
      

      【讨论】:

      • @denis631 是的,那么我认为最好尝试template matching。关于应用于个位数,可以用垂直直方图拆分计数器,例如(here有一个很好的例子)。
      • 我现在正在使用模板匹配,它也不适合我。问题是:正在制作照片的人可能会远离或靠近柜台,因此模板可能太小/太大而无法进行模板匹配。是否有类似模式匹配的东西?即使模式太小/太大,它也可以在其中找到匹配项。或者我需要动态调整我的图案大小以适应柜台照片的大小?
      • 也许你可以尝试根据你已经检测到的数字来纠正透视失真,并对比例和旋转做同样的事情。我尝试了opencv中的findHomography,但是模板上缺少关键点导致结果不佳。
      • 没错!我也尝试过缩放/变换不变算法,但它没有检测到任何关键点/特征......现在我试图强迫用户制作与我的模板尺寸几乎完全相同的照片,这样我可以做简单的模板匹配...我没有其他想法
      • 我建议您将问题中的图像更改为您在 cmets 中链接的图像,所以也许其他人有更好的主意。
      猜你喜欢
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      • 2017-01-08
      • 2021-02-11
      • 2016-03-15
      • 1970-01-01
      相关资源
      最近更新 更多