Skip to content

Commit

Permalink
ImageFile: Detect barcodes using zxing
Browse files Browse the repository at this point in the history
Use zxing to detect ultiple different types of barcodes including
1D and 2D. CODABAR, Code 128, DataMatrices, QR Codes, etc.
can be detected with a high degree of accuracy.
  • Loading branch information
AbdealiLoKo committed May 30, 2016
1 parent fa3c5f0 commit 465ea44
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
53 changes: 53 additions & 0 deletions file_metadata/image/image_file.py
Expand Up @@ -4,9 +4,11 @@
print_function)

import os
import re

import cv2

from file_metadata._compat import check_output, makedirs
from file_metadata.generic_file import GenericFile
from file_metadata.utilities import (app_dir, bz2_decompress, download,
to_cstr, PropertyCached)
Expand Down Expand Up @@ -105,3 +107,54 @@ def tup2(pt1, pt2):
data.append(fdata)

return {'dlib:Faces': data}

def analyze_barcode(self):
"""
Use ``zxing`` tot find barcodes, qr codes, data matrices, etc.
from the image.
"""
# Make directory for data
path_data = app_dir('user_data_dir', 'zxing')
makedirs(path_data, exist_ok=True)

def download_jar(path, name, ver):
data = {'name': name, 'ver': ver, 'path': path}
fname = os.path.join(path_data, '{name}-{ver}.jar'.format(**data))
download('http://central.maven.org/maven2/{path}/{name}/{ver}/'
'{name}-{ver}.jar'.format(**data),
fname)
return fname

# Download all important jar files
path_core = download_jar('com/google/zxing', 'core', '3.2.1')
path_javase = download_jar('com/google/zxing', 'javase', '3.2.1')
path_jcomm = download_jar('com/beust', 'jcommander', '1.48')

output = check_output([
'java', '-cp', ':'.join([path_core, path_javase, path_jcomm]),
'com.google.zxing.client.j2se.CommandLineRunner', '--multi',
'file://{0}'.format(self.filename)])

if 'No barcode found' in output:
return {}

barcodes = []
for section in output.split("\nfile:"):
lines = section.strip().splitlines()

_format = re.search(r'format:\s([^,]+)', lines[0]).group(1)
raw_result = lines[2]
parsed_result = lines[4]
num_pts = int(re.search(r'Found (\d+) result points.', lines[5])
.group(1))
points = []
float_re = r'(\d*[.])?\d+'
for i in range(num_pts):
pt = re.search(r'\(\s*{0}\s*,\s*{0}\s*\)'.format(float_re),
lines[6 + i])
point = float(pt.group(1)), float(pt.group(2))
points.append(point)
barcodes.append({'format': _format, 'points': points,
'raw_data': raw_result, 'data': parsed_result})

return {'zxing:Barcodes': barcodes}
47 changes: 47 additions & 0 deletions tests/image/image_file_test.py
Expand Up @@ -86,3 +86,50 @@ def test_facial_landmarks_baby_face(self):
data = self.baby_face.analyze_facial_landmarks()
self.assertIn('dlib:Faces', data)
self.assertEqual(len(data['dlib:Faces']), 1)


class ImageFileBarcodesTest(unittest.TestCase):

def setUp(self):
self.mona_lisa = ImageFile(fetch_file('mona_lisa.jpg'))
self.multibarcodes = ImageFile(fetch_file('multibarcodes.png'))
self.barcode = ImageFile(fetch_file('barcode.png'))
self.qrcode = ImageFile(fetch_file('qrcode.jpg'))
self.dmtx = ImageFile(fetch_file('datamatrix.png'))

def test_mona_lisa(self):
data = self.mona_lisa.analyze_barcode()
self.assertEqual(data, {})

def test_barcode(self):
data = self.barcode.analyze_barcode()
self.assertIn('zxing:Barcodes', data)
self.assertEqual(len(data['zxing:Barcodes']), 1)
self.assertEqual(data['zxing:Barcodes'][0]['format'], 'CODABAR')
self.assertEqual(data['zxing:Barcodes'][0]['data'], '137255')

def test_qrcode(self):
data = self.qrcode.analyze_barcode()
self.assertIn('zxing:Barcodes', data)
self.assertEqual(len(data['zxing:Barcodes']), 1)
self.assertEqual(data['zxing:Barcodes'][0]['format'], 'QR_CODE')
self.assertEqual(data['zxing:Barcodes'][0]['data'],
'http://www.wikipedia.com')

def test_dmtx(self):
data = self.dmtx.analyze_barcode()
self.assertIn('zxing:Barcodes', data)
self.assertEqual(len(data['zxing:Barcodes']), 1)
self.assertEqual(data['zxing:Barcodes'][0]['format'], 'DATA_MATRIX')
self.assertEqual(data['zxing:Barcodes'][0]['data'],
'Wikipedia, the free encyclopedia')

def test_multiple_barcodes(self):
data = self.multibarcodes.analyze_barcode()
self.assertIn('zxing:Barcodes', data)
self.assertEqual(len(data['zxing:Barcodes']), 2)
self.assertEqual(data['zxing:Barcodes'][0]['format'], 'CODE_128')
self.assertEqual(data['zxing:Barcodes'][0]['data'],
'2LUS94941+67000000')
self.assertEqual(data['zxing:Barcodes'][1]['format'], 'ITF')
self.assertEqual(data['zxing:Barcodes'][1]['data'], '054804124097')

0 comments on commit 465ea44

Please sign in to comment.