From the translator: we at Enterra are very fond of computer vision algorithms. We work most often with OpenCv. From time to time different developers write to us with the questions: “What is the best way to start working with OpenCv?” Or “What interesting task can you just solve with OpenCv?” In connection with which we decided to translate a very good article that will be useful to everyone interested in computer vision.
Black Friday is near.
')
Crowds of evil buyers. A swarm of identical middle-aged aunts who are ready to gobble up almost anything in the nearest supermarket - the main thing is that with a 75% discount. They will line up in front of the shops at midnight of Thanksgiving. They will burst inside, knock on locked doors with their fists and heads until they flatten each other and smash their hands into blood, becoming like the zombies from "28 days later." But instead of human flesh, they are eager to satisfy the buyer's instinct. Their battle cries for discounts and sales reach heaven. And their thunder can lead to an earthquake on the Great Plain.
Naturally, do not expect help from the media - they will savor every detail. From frostbitten families who spent the night in a tent in the cold, to an old lady trampled by hunters for a discount at the moment when the doors opened. Something similar happened to Gallimus in the Jurassic Park. And she just wanted to buy Halo for nine-year-old grandson Timmy, whose parents forgot to do it last year. In Wal-Mart. During Black Friday.
And I have to ask: is all this chaos and bedlam worth it?
Damn it, no!Any purchase I make on this Black Friday will be made completely safe with a laptop. But if you decide to go into the real world and start a fight with the bounty hunters,
you first need to download the code from the original post .
Just imagine how stupid you will look when standing in line waiting for a free ticket office - just to find out after scanning the last season's “Game of Thrones” barcode that you can buy it at $ 5 cheaper at Target?
Actually, then I will show how you can detect a barcode on an image using only Python and OpenCV.
We recognize streakhod on images on Pyhton and OpenCv
The goal of this post is to show a simple application of computer vision and image processing technologies for barcode recognition. My algorithm is a variation on the topic from here
with StackOverflow . I looked through the original code and added a number of updates and improvements to it. It is worth noting that this code will not work for all bar codes, but in any case, you will get an idea of ​​what methods you need to use.
It is important to note that the algorithm will not work for
all bar codes , but it will give a basic intuitive understanding of what techniques should be used for this.
For example, we will define a barcode from the following image:

Let's go to the code. Open a new file, call it
detect_barcode.py
- and go:
First of all, you need to import the necessary packages. We need NumPy for working with numbers,
agparse
for parsing command line arguments, and
cv2
for communicating with OpenCV.
Next, we process the command line arguments. We will use the single argument
--image
to specify the path to the image with a barcode.
Now let's proceed to the immediate image processing:
We load the image
image
and convert its color mode to shades of gray.
Then, we use the Sobel operator (with
ksize = -1
) to calculate the gradient value of the gray image in the vertical and horizontal directions.
After that, we subtract the y-gradient of the Sobel operator from the x-gradient. After subtraction, we get an image with a high horizontal gradient value and a low vertical value.
And now our image looks like this:
Notice that the barcode area was determined using gradient operations. The next step is to eliminate the noise in the image and focus exclusively on the area with the barcode.
And the first thing we do is use average blur with a 9x9 core. This will help smooth out the high-frequency noise in our picture with gradients.
Then we will binarize the blurred image. Each pixel of an image with a value not higher than 225 we will turn into 0 (black), and the rest - into 255 (white). As a result, we get:

However, as you can see in the original image, there is space between the vertical bars of the barcode. To close it and make it easier for our algorithm to determine the barcode area, we need to perform a series of simple morphological operations:
We start by creating a rectangle with
cv2.getStructuringElement
. The width of the core is greater than its height, which allows us to cover the space between the vertical bars of the barcode.
Next, we perform our morphological operation by applying the core to the binarized image, glossing over the space between the stripes. And you can see for yourself that the “gaps” are almost completely closed compared to the images above:

Of course, some light spots remained on the picture, which are not related to the barcode and can interfere with the exact definition of its contour.
Let's try to get rid of these stains:
Here we do four iterations of erosion, followed by four iterations of dilation. Erosion will remove white pixels from the image, removing small blobs, and dilatation will not allow large white areas to decrease. Removed during blurring small spots during stretching will not appear again.
After a series of erosions and dilations, one can see that small spots were successfully removed, only the barcode area remained:

Finally, let's find the outlines of the barcode area on the image:
Fortunately, it is quite simple. We find the largest contour in the image using
cv2.findContours
, which (if processed correctly) corresponds exactly to the barcode area.
Then we define the minimum bounding box in which we enclose this largest contour, after which we finally display the barcode found.
As you can see, we successfully found the barcode:

Trying to do this with a few more images?
Successful Barcode Detection
To get similar results, use my code (you can download it entirely on the original page) and the images shown here. Once you have the code and images, open a terminal and run the following command:
1 $ python detect_barcode.py --image images/barcode_02.jpg

No problem found barcode of coconut oil. We try again:
1 $ python detect_barcode.py --image images/barcode_03.jpg

And on this image we successfully found a barcode! But what are we all about food, let's move on to the books.
1 $ python detect_barcode.py --image images/barcode_04.jpg

And again - no problem! Can we identify the tracking number for the parcel?
1 $ python detect_barcode.py --image images/barcode_05.jpg

And again, our algorithm successfully detected a barcode.
Conclusion
In this post, we looked at the necessary steps to detect bar codes on images using computer vision technology. We applied an algorithm using the Python programming language and the OpenCV library.
Our algorithm is based on the following actions:
- Calculate the size of the gradient along the x and y axes.
- Separate the vertical gradient from the horizontal to reveal the barcode area.
- Apply blur and binarization.
- Apply the core to the binarized image to remove the “gaps” between the stripes.
- Produce a series of erosions and dilations.
- Find the largest contour in the image, which will be the barcode area.
It is worth noting that, since the method is based on the representation of an image in the form of a gradient, it will work correctly only for horizontal bar codes.
If you want to use a more reliable barcode detection algorithm, you should take into account the orientation of the image, and even better - use self-learning systems, such as the Haar or HOG + Linear SVM cascades, to “scan” the image for areas with a barcode.