2

This is question is a follow-up of Prepare complex image for OCR.

I have an output of a canny edge detector of an image with digits:

Canny edge image

As you can see, I have various edges for a digit, which result from the embossment on a credit card. The goal would be to have solid digits, which are suitable for character recognition.

This is an attempt to "fill" the digits using a morphological close operation with a 5x5 structuring element in shape of a diamond:

Morphological close operation

I tried various structuring elements, but without much success. You can see how holes are being created (digit 9 and 0) and shapes are being distorted (digit 3).

Can you recommend a better approach to fill the structures, but without glueing different digits together and keeping the original shape?

However, even with the poorly looking digits and splitting the digits vertically after applying the close operation, there are already good recognition results achievable.

Thanks, Valentin

Community
  • 1
  • 1
valentin
  • 511
  • 3
  • 16
  • Valentin, I'm working on the same problem as you were (reading credit cards with OCR). I've had some success using tesseract to read images after manual pre-processing, but I'm still struggling with automating that processes. I was wondering what solution(s) you eventually settled on? Is your code available anywhere? I'd love to compare notes with you. – bjmc Nov 02 '12 at 21:13
  • You can send me a mail (www.valentin-manthei.de) if you want. I realized the OCR with an own approach using template/feature matching techniques and additional criteria to improve the results. The preprocessing is the worst part, though. A whole filter chain, which dynamically adjusts its parameters, is now eventually able to scan some credit card numbers completely, but only under good circumstances (lightning, resolution). – valentin Nov 05 '12 at 14:32

2 Answers2

2

enter image description hereI think that you can reach better results with advanced grayscale binarisation techniques, like sauvola binarisation with big kernel (I use 50x50). This threshold filter takes into account local variance of grayscale values and is not sensitive to changes in liminance. It also has some highpass/lowpass properties depending on settings. See implementation in JavaOCR Project:

http://sourceforge.net/projects/javaocr/

(PS: 50x50 kernels are not a problem - this implementation speed is kernel size independent )

Update, just tried my OCR dialer on credit card, binarisation result below:

Reflecting surfaces produce a lot of noise, but I think this could be manageable with some more preprocessing.

Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
  • Thanks a lot for your opinion. This is the result with a 40x40 kernel and the sauvola algorithm: http://i.imgur.com/QWlPc.jpg (I didn't find the sauvola source in JavaOCR, though). The result is very noisy, but that could probably be optimized with an applied Gaussian blur. However, I am not sure how this solves the problem of partial digits, which are not suitable for character recognition (I only get the outlines with all approaches), yet. – valentin Mar 21 '12 at 14:24
  • As sauvola uses Mx and variance over a widnow, it already has low-pass filter properties. But apparentlz not enough for silver reflecting plastic surfaces. In this sample my slicing code could not extract glyphs, but I daresay that probability based recognition I use in JavaOCR would work pretty well on credit card number font, even if image is distorted – Konstantin Pribluda Mar 21 '12 at 17:58
1

you haven't shown any code, so we can't help too much. Here is a snippet of how to use some morphological operations to fill in some gaps without changing the size before you try the canny operation.

// OTSU, then binary threshold
Imgproc.threshold(colorImg, grayImg, 0, 255.0, Imgproc.THRESH_OTSU | Imgproc.THRESH_BINARY);

// Morphological reduction of noise, strengthen lines
Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(7, 7));
Imgproc.dilate(grayImg, grayImg2, element);
Imgproc.erode(grayImg2, grayImg, element);

// Edge detection
Imgproc.Canny(grayImg, output, 50, 50);

However, you should look at card.io, which reads credit cards. Reading the embossed symbols is very difficult with pre image processing because the lighting varies so much. You are better off using machine learning.

Buddhisthead
  • 329
  • 2
  • 12