The purpose of this blog is the application of computer vision and image processing techniques to show the basic realization of a bar code detection. I realized the nature of the algorithm based on this question on StackOverflow, browse the code, I provide some updates and improvements to the original algorithm.
First need to note is that this algorithm is not effective for all bar codes, but will give you a basic application of intuition about what type of technology.
Now let's start to write code, create a file named detect_barcode.py, open and Code:
1 # import the necessary packages
2 import numpy as np
3 import argparse
4 import cv2
6 # construct the argument parse and parse the arguments
7 ap = argparse.ArgumentParser ()
8 ap.add_argument ( "- i", "--image", required = True, help = "path to the image file")
9 args = vars (ap.parse_args ())
We first do is to import the package, we will use NumPy to do numerical calculations, argparse for parsing command-line arguments, cv2 is OpenCV bindings.
Then we set the command-line arguments, here we need a simple choice, -image refers to a path that contains a bar code image file to be detected.
Now start the real image processing:
11 # load the image and convert it to grayscale
12 image = cv2.imread (args [ "image"])
13 gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY)
15 # compute the Scharr gradient magnitude representation of the images
16 # in both the x and y direction
17 gradX = cv2.Sobel (gray, ddepth = cv2.cv.CV_32F, dx = 1, dy = 0, ksize = -1)
18 gradY = cv2.Sobel (gray, ddepth = cv2.cv.CV_32F, dx = 0, dy = 1, ksize = -1)
20 # subtract the y-gradient from the x-gradient
21 gradient = cv2.subtract (gradX, gradY)
22 gradient = cv2.convertScaleAbs (gradient)
12 to 13 lines: load images from disk and converted to grayscale.
17 to 18 rows: Use Scharr operations (specify ksize = -1) configured grayscale gradient magnitude in the horizontal and vertical directions. Fig.
21 to 22 lines: Scharr after the operation, we subtract y-gradient from the x-gradient, and this step by subtraction, to give the final image area contains high levels of low gradient and vertical gradient.
Note how the barcode area detected by the gradient operation. The next step will focus on only barcode area by de-noising.
24 # blur and threshold the image
25 blurred = cv2.blur (gradient, (9, 9))
26 (_, thresh) = cv2.threshold (blurred, 225, 255, cv2.THRESH_BINARY)
Line 25: The first thing we need to do is to use the kernel 9 * 9 of FIG gradient averaging blur, which will help smooth gradient graphic representation of high frequency noise.
Line 26: Then we'll graphical blur after binarized gradient figure anything less than equal to 255 pixels to 0 (black), and the rest is set to 255 (white).
Fuzzy and output binarized looks like this
However, as you can see, in the binary image above, there is a gap between the vertical bars of the bar code, in order to eliminate these gaps, and make our algorithm easier to detect barcodes "spot" shaped area, we need to some fundamental morphological operations:
28 # construct a closing kernel and apply it to the thresholded image
29 kernel = cv2.getStructuringElement (cv2.MORPH_RECT, (21, 7))
30 closed = cv2.morphologyEx (thresh, cv2.MORPH_CLOSE, kernel)
Line 29: We first use cv2.getStructuringElement construct a rectangular core. The core width greater than the length, so we can eliminate the gap between the vertical bars in the barcode.
Line 30: here morphological operations, the previous step was applied to our core binary image in order to eliminate the gap between the vertical bars.
Now, you can see the gap compared to the binary image above basic has been eliminated:
Of course, there are some small spots in the image, it is not part of the real barcode, but may affect our contour detection.
Let's eliminate these small spots:
32 # perform a series of erosions and dilations
33 closed = cv2.erode (closed, None, iterations = 4)
34 closed = cv2.dilate (closed, None, iterations = 4)
First of all we're doing here is four times the corrosion (erosion), and four times the expansion (dilation). Etching operation will corrode the white pixels in the image, in order to eliminate small spots, but the expansion will operate the remaining white pixels to expand and re-grow back.
If small spots of corrosion are removed in the operation, then the expansion of the operation will not occur again.
After our series of erosion and dilation operations, we can see that we have successfully removed a small spot and get the barcode area.
Finally, let us find the barcode image outline:
36 # find the contours in the thresholded image, then sort the contours
37 # by their area, keeping only the largest one
38 (cnts, _) = cv2.findContours (closed.copy (), cv2.RETR_EXTERNAL,
40 c = sorted (cnts, key = cv2.contourArea, reverse = True) 
42 # compute the rotated bounding box of the largest contour
43 rect = cv2.minAreaRect (c)
44 box = np.int0 (cv2.cv.BoxPoints (rect))
46 # draw a bounding box arounded the detected barcode and display the
47 # image
48 cv2.drawContours (image, [box], -1, (0, 255, 0), 3)
49 cv2.imshow ( "Image", image)
50 cv2.waitKey (0)
38 to 40 lines: Fortunately, this part is relatively easy, we simply find the image in the maximum outline, if we correct the image processing step is completed, there should be corresponding to the barcode area.
43 to 44 lines: Then we determine the minimum to the maximum outline border
48 to 50 rows: last display detected barcode
The next section, we will try more images.
Successful barcode detection
To follow these results, please use the form below the article to download the source code of this article and comes with pictures.
Once you have the code and the image, open a terminal to execute the following command:
$ Python detect_barcode.py --image images / barcode_02.jpg
Barcode detection coconut on the bottle is no problem.
Let's try another one image:
$ Python detect_barcode.py --image images / barcode_03.jpg
We can also find the bar code in the image above.
Barcode detection on food enough, the bar code on how to do the books:
$ Python detect_barcode.py --image images / barcode_04.jpg
No problem, by again.
That parcel tracking code on it?
$ Python detect_barcode.py --image images / barcode_05.jpg
Our algorithm successfully detected a bar code again.
Finally, we'll try a picture, this is my favorite pasta sauce - Rao's homemade vodka sauce (Rao's Homemade Vodka Sauce):
$ Python detect_barcode.py --image images / barcode_06.jpg
Our algorithm detected bar code again!
to sum up
This blog, we review the steps necessary to use computer vision technology to detect an image of a bar code, using the Python programming language and OpenCV library implements our algorithm.
Algorithm are summarized as follows:
Scharr gradient magnitude calculated x and y directions indicates
The x-gradient minus y-gradient to display the barcode area
Fuzzy and binary image
Application of binary image kernel closing operation
Serially corrosion, swelling
Find the maximum outline image, it is probably the barcode
It should be noted that this method made assumptions about image gradient representation is therefore only valid for horizontal barcode.
If you want to implement a more robust barcode detection algorithm, you need to consider the direction of the image, or better, applying machine learning techniques such as Haar cascade or HOG + Linear SVM to scan the bar code image area.