How to recognize numbers from an analog counter?

I am trying to read the following kWh digits from a meter. The problem is that the optical tesseract recognizer does not recognize analog numbers.

counter

The question is whether it would be better to take photos of all the numbers (from 0 to 9) in different positions (I mean when the figure is in the center, when it is slightly above and the number 2). etc.) and try image recognition instead of text recognition?

As I understand it, the difference is that image recognition compares photos and text recognition ... well, I donโ€™t know ...

Any advice?

+4
source share
2 answers

Since the counter is not digital, but analog, there are problems in the transition. Text recognition libraries and numbers cannot recognize smth. The solution I found is: Machine Learning .

First, I made the user take a picture where the numbers occupy 70-80% of the image (to remove unnecessary details).

Then I look for parallel lines (if any) and cut out the image, i.e. between them (if the distance is big enough).

After that, I filter the image (playing with contrast, brightness, set it in shades of gray), and then use a filter that forces the image to contain only two colors ( #000000 (black) and #ffffff (white)). To find outlines easier.

Then I find the outlines using the Canny algorithm and filtering them, removing unnecessary details.

After that, I use the K-Nearest-Neighbour algorithm to recognize numbers.

But before I learn anything, I need to teach the algorithm how the numbers look and what they are.

Hope this was helpful!

+3
source

You may not be setting up tesseract right. I used code that solves your problem:

 #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; } 
+2
source

All Articles