From rubini@gnu.org Fri Oct 19 19:35:44 2001
Date: Mon, 15 Oct 2001 14:13:42 +0200
From: Alessandro Rubini <rubini@gnu.org>
To: tuukkat@ee.oulu.fi, barcode@lists.linux.it
Subject: Re: [barcode] recognizing barcodes


Hello.

> My objective is to recognize a barcode, not print it.

Actually, I am interested in following this path. My main problem is
finding the time, as usual.

With Dani Pardo, from Spain, we even tried to lay out the papers to
make that project and EU project, but the bureaucratic load is too high
for us to really submit the project for approval.

I hope to find some time for that task anyways, but I can't devote
the resources that are needed to make it an EU project.

FYI: this is what I have in mind, from the description I wrote when we
were trying to make the EU project.

----------------------------------------------------

"crab" (Computer-aided Reverse Analysis of Barcodes) is designed as a
software liberary included in GNU barcode. It can be used to implement
a hardware "edocrab" (Electronic Device for Optical C-a R A of B).

One problem that will be non-trivial is dealing with curved symbols
(i.e., not exactly flat ones, where the orientation of the stripes
changes along the symbol).  A "cut" step will work nonetheless, but
all the machinery for rotation, squashing etc is expected to fail (so
a noisy image with non-parallel lines will not be detected unless I
find something really smart :). Sometimes the camera returns distorted
images (mostly happens for large-angle cameras like one I have here);
mapping this image to an undistorted one is left to the application,
as no general rule or mapping exists.


The problem being addressed can be split into several steps in order
to better fit different operating environments and constraints. Most
of those steps are implemented using image-processing techniques,
aimed at cleaning the image and getting the bes information out of the
digital image. The final step, identifying the encoding used in the
relevant symbol and the meaning of the symbol itself, is of minor
importance and relatively easy to implement.

The caller application must specify a "program" to follow in the
decoding process. The program outlines which image-processing steps
are to be performed on the image in order to get a clean cut of white
and black stripes to be used in the final step. The program is
described by an array of data structure, each of them selecting an
elaboration step together with zero or more arguments whose meaning
depends on the step being invoked. Each step returns a success or
failure indication, in case of failure no further step is performed.
The calling application can thus choose to try several programs in a
selected order to maximize performance for good input images and still
be able to decode bad input images using a more refined, and slower,
program. Applications that need to continuously monitor a camera and
only react to good input images can use a program that rejects bad
images early to reduce the load on the system by avoiding excessive
computation on false positives.

Some of the steps work on 2-D images and create a new 2-D image, some
of the steps turn 2-D data into 1-D data, and some act on 1-D data
alone. The final (implied) step gets 1-D data as input and turns it
into a string (similar to the intermediate format used by GNU barcode
in printing bar codes) that is then used to decode the symbol.

* 2-D to 2-D steps

"localize" finds a barcode pattern. It's two optional arguments the
starting point for localization (for example, if you know or require
that the barcode symbol must pass for the selected pixel. Localization
with a starting point is much faster than localization of a symbol in
the whole image. The step adds hints to the target image; those hints
represent the corners of the symbol and its rotation angle.

"smooth" smooths the image by applying a low-pass filter. The
compusory argument specifies the width of the mask used in low-pass.
The step is useful if the input image is noisy.

"sharpen" enhances edges in the image. It's useful if the image is
blurred but already at high resolution. The use of sharpening can help
in making detection faster, as often a "sharpen, cut" program is as
effective as "expand, rotate, squash", while being faster (see below
fora description of other steps).

"expand" expands the image to a bigger image. This step is needed if
the symbol is small and the granularity introduced by digital imaging
can adversely affect identification of the bars. Pixels in the target
image are set according to bilinear interpolation of the input image.

"rotate" rotates the symbol to be exactly horizontal. The step can use
the hints created by "localize" but can also work without them (if no
localize step has been performed). The step requires that the center
of the image falls within the barcode symbol. Optional arguments
specify the maximum rotation angle; thus, if you know that the symbol
is already more-or-less horizontal this step works much faster and
must only refine orientation.

"threshold2" turns the image into a black-and-white image. The
optional argument is the threshold value; if no argument is passed the
threshold is elected to be the average between white and black pixels
in the image.  The step is useful if the input image is very good, as
a "cut" operation is much faster on a thresholded input.

* 2-D to 1-D steps

"squash" is used to turn the input image into an array of pixel values
by averaging each column of the input image. It obviously requires
that the input image is exactly horizontal. Use of image expansion,
rotation and squashing is most effective with bad input images.

"cut" tries to find a barcode symbol inthe input image by cutting it
in several directions through the center of the image. This is how a
laser scanner works and is the fastest recognition technique, but it
needs the input image to be of good quality. Optional arguments
specify the starting point for cutting and the number of directions to
try (three by default). The step selects which of the several cuts is
most likely to intersect a complete barcode symbol, it's thus much
fater if the input image is already thresholded. If the input image
has been processed by "localize", the position/rotation hints are used
and a single cut is made and arguments are ignored. If no hints are
there and the number of cuts is set to one, the barcode symbol is
assumed to be horizontal; the set of cuts always includes a horizontal
cut (if the symbol is known to have a specific orientation, either use
"rotate" with the known angle or select a number of cuts that is known
to detect the symbol; computational overhead in using several cuts is
low if one of the cuts is clearly a good barcode).

* 1-D to 1-D steps

"threshold1" like threshold2, it turns the input array into a
black-and-white one. It's obviously not needed if the input image has
been thresholded and cut. The optional argument specifies the expected
encoding of the symbol; encoding-specific program code, if available,
will choose the threshold value to ease the recognition step.

"decode" This step turns the input array into a string representing
the width of the individual bars and spaces, the first and last width
representing bards. The output string is similar to the intermediate
representation of barcodes used by GNU barcode in creating barcode
symbols as output. The string is then fed to encoding-specific
recognition code that returns the text encoded in the barcode symbol.
Optional arguments specify the set of encodings to be used in
recognition.


