代码之家  ›  专栏  ›  技术社区  ›  denis631 Oleg

如何识别模拟计数器中的数字?

  •  4
  • denis631 Oleg  · 技术社区  · 11 年前

    我试图从计数器中读取以下kWh数。问题是 细分OCR 无法识别模拟数字。

    counter

    问题是:将所有数字(从0到9)的照片放在不同的位置(我的意思是当数字在中间时,当数字稍微在顶部时,数字2出现时,等等),并尝试图像识别而不是文本识别,这会更好吗?

    据我所知,区别在于,图像识别比较照片,而文本识别……嗯,我不知道。。。

    有什么建议吗?

    2 回复  |  直到 6 年前
        1
  •  3
  •   denis631 Oleg    10 年前

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

    首先,我让用户制作图片,其中数字占图像的70-80%(为了去除不必要的细节)。

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

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

    然后我用 Canny 算法并通过删除不需要的细节来过滤它们。

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

    但在我能识别任何东西之前,我需要教算法,数字看起来像什么,它们是什么。

    我希望它有用!

        2
  •  2
  •   Jäger    11 年前

    也许您没有正确配置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;
    }