5

There are images with perspectively distorted barcodes in them.

enter image description here

They are located and decoded using ZBar.

zbar barcode location

Now I do not only need the rough location, but the four real corner points of the barcode, that define the enclosing 4-point polygon.

enter image description here

I tried different approaches, but did not yet get the desired result. One of them was:

  • convert image to grayscale
  • threshold image
  • erode image
  • floodFill beginning with a pixel known to be part of barcode
  • obtain the contour around the floodFill result

But around this contour I now would need to find the minimum best fitting 4-point polygon, which seems to be not that easy.

Do you have ideas for better approaches?

Community
  • 1
  • 1
Tobias Hermann
  • 9,936
  • 6
  • 61
  • 134

2 Answers2

2

You could use the following code and try to reduce your contour to 4-point polygon via approxPoly

vector approx;

for (size_t i = 0; i < contours.size(); i++)
{
    approxPolyDP(Mat(contours[i]), approx, 
             arcLength(Mat(contours[i]), true)*0.02, true);

    if (approx.size() == 4 &&
        fabs(contourArea(Mat(approx))) > 1000 &&
        isContourConvex(Mat(approx)))
    {
        double maxCosine = 0;

        for( int j = 2; j < 5; j++ )
        {
            double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
            maxCosine = MAX(maxCosine, cosine);
        }

        if( maxCosine < 0.3 )
            squares.push_back(approx);
    }
}

http://opencv-code.com/tutorials/detecting-simple-shapes-in-an-image/

You can also try the following methods, maybe they will produce good enough results for you: http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=minarearect#minarearect

or

http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=convexhull#convexhull

  • minAreaRect is not precise enough, since the barcode is not only rotated and scaled, but also distorted perspectively. convexHull and approxPolyDP are not guaranteed to give exactly four points. I could of course try out different epsilons for approxPolyDP until I have exactly four points in the result, but this also does not guarantee that this will be the four corners I'm looking for. In the worst case there is no epsilon at all to return a four point polygon. – Tobias Hermann Jul 17 '15 at 11:24
2

OK, I found a solution that works good enough for my use case.

First a scanline is generated from the ZBar result.

scanline

Now the first and the last black pixels are found in verion of the image resulting from cv::adaptivethreshold with a large enough blockSize.

first and last black pixels

From there on the first and the last bar are segmented using cv::findContours.

first and last bar

Now for both end bars the two contour points with the most distance to each others are searched.

bar ends

They finally define the enclosing 4-point-polygon.

four point poly

Which is not exactly what I posted in my question, but the additional size due to the elongated guard patterns does not matter in my case.

Tobias Hermann
  • 9,936
  • 6
  • 61
  • 134