# Detecting which digital number an image represents

I photograph the dashboard of my car every day to register the mileage for work. I use OpenCv to detect the region of the digital displayed mileage, crop to the numbers and match them. The method I use now to determine what numbers are displayed is working for (lets say) 95% of the cases. Finding the numbers is working fine (resize, rotate, correct perspective). Matching the numbers I find still a bit tricky.

The method I use now is determining the center location of each part/stripe that makes up the digit and match the difference of the center to predefined values. To find the center I use blob detection of open cv.

is then converted to a binary image

and blob detection is used to find the center of each blob (marked with red)

The center location of each blob is compared (squared distance) to the center location of a predefined set of locations. And the least square distance is related to what stripe of the digit it is. Then the combination of the stripes found is compared to a dictionary containing the stripe locations for each digit.

The problem I have now is that, although the images are normalized, sometimes more blobs are detected because the the threshold for making the binary image leave out pixels unexpectedly in the center of a blob. And blob detection sees that are separate blobs.

Is there a better approach to determine what digit it is using the particular display of the digits shown above? 'Better' would be: more robust, simpelere, less logic/code required, more universal applicable. I don't want to pull in a whole OCR library for this, if possible.

• Since the font is known and to an extent you are in full control of image acquisition (i.e. scale and orientation will remain within controllable limits), why don't you try simple cross-correlation? (For an example, please see this link)
– A_A
Commented Jul 24, 2016 at 21:18
• @A_A Thank you for your comment. I will definitely look into it! I am glad I asked this question as it has provide great input so far! Commented Jul 26, 2016 at 12:49

A simple count of the pixels where the binary color is matching between the image to be recognized and the images of the ten reference digits might be good enough.

For best results, it is advisable to create the reference images using exactly the same method as that for the target image.

If it turns out that binarization doesn't work repeatably enough, you can switch to finer comparison metrics such as Sum of Absolute Differences, Sum of Squared Differences or Normalized Grayscale Correlation.

You already converted to binary - if that proves to work well, then you can do a shrinkage operation (I'm quite sure there should be such in OpenCV but not completely) until you get one point per segment. Measure coordinates of these points and do pairwise comparison to array of coordinates from a set of models of the digits of a 7 segment display. ( first some suitable normalization of the coordinates may be needed ).

Assuming you have measured column vector x_measured and y_measured of coordinates and x_model and y_model of a stored model of a 7 segment number in Octave then you could do:

sum(min(abs(x_measured - x_model') + abs(y_measured - y_model')))


In a c-like language just a double loop storing minimum values of sums of absolute differences and then summing them.

Then you pick the digit that matches with least error.

You may want to read more on mathematical morphology if you are interested. If you see the shape of the dancing couple note that for advanced shapes you may be getting several pixels from one connected shape. But I think the digit blobs should be "nice" enough for that not to happen.

• That shrinkage approach didn't cross my mind. I will look into it. One point per segment means 1 pixel per segment? What do you think would become the minimum dimensions of the shrinked image, looking at the form of the digit? Commented Jul 26, 2016 at 5:54
• Yes after shrinking each area of white pixels one ends up with one white pixel for each of those areas. Then we can stuff the coordinates of each such pixel into a list or array and compare to template lists or arrays for previously measured digits. Then we have reduced the information from all the pixels in the image down to a couple of lists. Since it is 7 segment display there should be a maximum of 7 pixels to store coordinates for. Commented Jul 26, 2016 at 9:22
• Do I understand correctly that by shrinking you mean that the blobs are eroded? docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/… Commented Jul 26, 2016 at 9:39
• Yep you can start with erosion. An operation in the same sense as those which give one point if you start with anything simply connected. There are some different ones, I don't remember the names of them all just the ideas and how they work and some don't shrink down end-points but instead give like a "skeleton". But you are on the right track there. Lots of useful tools with those operations. Commented Jul 26, 2016 at 9:50