1

I have an image from lottery tickets that I'd like to split into chunks. Basically the image can be described as a a group of "lanes" having on header lane, several number lanes and one footer lane. Each lane separated from the other by a line like this:

lotto logo
some info
----------------
01 02 03 04 05
----------------
01 02 03 04 05
06 07 08
----------------
footer message

A sample image can be found here. Would it be possible to use opencv to detect those lines and save each lane into a separate image?

Thanks in advance.

karlphillip
  • 92,053
  • 36
  • 243
  • 426
epc
  • 194
  • 4
  • 12

2 Answers2

2

Since you know that you are looking for repeating long horizontalish lines, you could use some kind of texture analysis such as a Gabor Filter to isolate those lines, and then use a line detection algorithm such as the Hough Transform. OpenCV has functions to do all of that.

Given the boring nature of my evening I decided to test those ideas a little bit. After tweaking some of the gabor filter parameters I was able to isolate horizontal-ish lines in the image as such:

IsolatedLines

Code:

    //Tweaked parameters
 cv::Size ks(101,101);
 int sig = 20;
     int lm = 50;
     int th = 0;

    cv::Mat kernel = cv::getGaborKernel(ks,sig,th,lm,0,0,CV_32F);

    //using kernel transpose because theta = 90 (or pi/2) 
    //did not give horizontal lines.
    cv::filter2D(im, im, CV_32F, kernel.t());
    //Threshold to get binary image for Hough
    cv::threshold( im, im, 254, 255, cv::THRESH_BINARY_INV); 

From there I just ran the usual HoughLinesP algorithm (filtering for very long lines) to get this:

Detected Lines

Code:

im.convertTo(im,CV_8U);
std::vector<cv::Vec4i> lines;
cv::HoughLinesP(im,lines,1,CV_PI/180, 200, 800, 0);

From there all you would have to do is identify each line and crop out the correct image areas.

If all of your images look pretty much identical to your sample, this approach might work for you. It also might not be robust enough. Hopefully it gives you something more to think about.

David Nilosek
  • 1,422
  • 9
  • 13
  • +1 Nice. I've done something similar and will share it later. – karlphillip Nov 17 '13 at 04:34
  • Indeed very impressive. Thanks for the help! – epc Nov 21 '13 at 18:23
  • @david-nilosek, did you pass the image output from cv::threshold directly to cv::HoughLinesP? I'm trying this out but I'm getting the errro (-5) The source image must be 8-bit, single-channel... – epc Nov 23 '13 at 13:54
  • 1
    Ah no, sorry. I did a conversion to 8-bit right before that. Updated code. – David Nilosek Nov 24 '13 at 02:45
  • Thanks for the update! Based on your help, after reading a bit about the techniques applied, I managed to get a working code going on. I'd like to tune the parameters to images for 300 dpi or lower, but I'm lost. When you pick your starting values (to tune) you do it "at random" or do you base it on something else? – epc Nov 24 '13 at 21:07
  • Ks is the size of the kernel, theta is the orientation of the filter, sigma is the width of the Gaussian which modulates the sinusoidal function, and LM is the wavelength of the sinusoidal. Based on the size of the image I picked a larger kernel size, a longer wavelength because the desired feature is rather low frequency, and set the orientation to 0 (note that I tried setting it to 90 but I was unable to get the kernel to orient itself along the x-axis, unsure why, so I used the transpose instead). From there I just changed them slightly until I got a good isolation of those lines. – David Nilosek Nov 24 '13 at 22:57
1

Sure, it's possible.

The first step requires you to detect the lines of dots, and for that you can use algorithms like:

This post provides a brief description on these methods, and you can find several examples around the web on how to use them.

Once you found the location of the lines of dots, you can perform 3 crop operations to extract the 3 Regions Of Interest (ROI) into new images.

Good luck.

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426