Example image:
Code:
#get height and width of image
height, width = possible_barcode_img.shape[:2]
#prepare list for rows
barcode_rows = []
for i in range(height):
# set variables and list for beginning of row
white_bar_width = 0
black_bar_width = 0
barcode_row = []
for j in range(width):
if possible_barcode_img[i,j] == 0:
#add to count
black_bar_width = black_bar_width +1
#ensure last bar is gotten if there was one
if white_bar_width > 0:
#add bar to row
barcode_row.append(["white", white_bar_width])
white_bar_width = 0
elif possible_barcode_img[i,j] > 0:
#add to width
white_bar_width = white_bar_width +1
#ensure last bar is gotten if there was one
if black_bar_width > 0:
#add bar to row
barcode_row.append(["black", black_bar_width])
black_bar_width = 0
#ensure last bar is gotten since a row just finished
if white_bar_width > 0:
#add bar to row
barcode_row.append(["white", white_bar_width])
elif black_bar_width > 0:
#add bar to row
barcode_row.append(["black", black_bar_width])
#add entire row to rows
barcode_rows.append(barcode_row)
Print row 50 of the picture in the question print(barcode_rows[50])
:
[['black', 3], ['white', 7], ['black', 4], ['white', 6], ['black', 4], ['white', 6], ['black', 13], ['white', 5], ['black', 4], ['white', 15], ['black', 4], ['white', 5], ['black', 5], ['white', 5], ['black', 13], ['white', 15], ['black', 13], ['white', 5], ['black', 13], ['white', 6], ['black', 3], ['white', 15], ['black', 5], ['white', 4], ['black', 4], ['white', 14], ['black', 13], ['white', 6], ['black', 4], ['white', 14], ['black', 13], ['white', 14], ['black', 5], ['white', 5], ['black', 4], ['white', 5], ['black', 4], ['white', 14], ['black', 4], ['white', 5], ['black', 4], ['white', 5], ['black', 13], ['white', 14], ['black', 13], ['white', 5], ['black', 14], ['white', 4], ['black', 5], ['white', 4]]
50 bars found as in the picture, ready for decoding.
This has quite an effect on fps when doing it with video. I know that I don't have to loop through the entire image, I will have it send to a decoder after each row of pixels and end the loop if successful.
However I'm hoping there's a more optimized way to do this than using the Python loops on each individual pixel because I don't think the above will be fast enough for my needs.
1 Answer 1
You don't need a number of pixels, you need to detect narrow bars and wide bars. Use first black and white bar width as a pattern with 15% margin for next bars. The wide bar has 2.0 to 3.0 times the width of a narrow bar. Try to detect start or stop code at the begin of selected line, if it is correct, then read the rest of the line... After every 5 black+white bars (in the right direction) you can decode two digits, black bars define 1st and white 2nd ... Bars have weights: 1st: 1, 2nd: 2, 3th: 4, 4th: 7: 5th 0. Add weights of every wide bars, and you get the digit (11 = 0). If 3 lines give you the same result, this is probably your code...
EDIT:
You can see the algorithm on your code: enter image description here
-
\$\begingroup\$ Yeah I was going to figure the wide or narrow width after I got the numbers. My concern was that the existing code was slow. I realized I don't have to reinvent the wheel and decided to try using a decode library.
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
decode(possible_barcode_img, symbols=[ZBarSymbol.I25])
It seems to work well for what I need. \$\endgroup\$Trevor– Trevor2018年10月21日 21:10:07 +00:00Commented Oct 21, 2018 at 21:10 -
\$\begingroup\$ You got it. The "?" is the edge of a cyan marker I used to help locate the barcode and unintentionally got in there. also typo, 1+7 is actually 8. The barcode reads "12345678". \$\endgroup\$Trevor– Trevor2018年10月21日 22:27:56 +00:00Commented Oct 21, 2018 at 22:27
-
\$\begingroup\$ Image corrected... \$\endgroup\$Adam Silenko– Adam Silenko2018年10月21日 23:10:16 +00:00Commented Oct 21, 2018 at 23:10
Interleaved 2 of 5
... \$\endgroup\$