Leptonica  1.82.0
Image processing and image analysis suite
readbarcode.c File Reference
#include <string.h>
#include "allheaders.h"
#include "readbarcode.h"

Go to the source code of this file.

Macros

#define DEBUG_DESKEW   0
 
#define DEBUG_WIDTHS   0
 

Functions

static PIXpixGenerateBarcodeMask (PIX *pixs, l_int32 maxspace, l_int32 nwidth, l_int32 nheight)
 
static NUMApixAverageRasterScans (PIX *pixs, l_int32 nscans)
 
static l_int32 numaGetCrossingDistances (NUMA *nas, NUMA **pnaedist, NUMA **pnaodist, l_float32 *pmindist, l_float32 *pmaxdist)
 
static NUMAnumaLocatePeakRanges (NUMA *nas, l_float32 minfirst, l_float32 minsep, l_float32 maxmin)
 
static NUMAnumaGetPeakCentroids (NUMA *nahist, NUMA *narange)
 
static NUMAnumaGetPeakWidthLUT (NUMA *narange, NUMA *nacent)
 
static l_int32 numaEvalBestWidthAndShift (NUMA *nas, l_int32 nwidth, l_int32 nshift, l_float32 minwidth, l_float32 maxwidth, l_float32 *pbestwidth, l_float32 *pbestshift, l_float32 *pbestscore)
 
static l_int32 numaEvalSyncError (NUMA *nas, l_int32 ifirst, l_int32 ilast, l_float32 width, l_float32 shift, l_float32 *pscore, NUMA **pnad)
 
SARRAYpixProcessBarcodes (PIX *pixs, l_int32 format, l_int32 method, SARRAY **psaw, l_int32 debugflag)
 
PIXApixExtractBarcodes (PIX *pixs, l_int32 debugflag)
 
SARRAYpixReadBarcodes (PIXA *pixa, l_int32 format, l_int32 method, SARRAY **psaw, l_int32 debugflag)
 
NUMApixReadBarcodeWidths (PIX *pixs, l_int32 method, l_int32 debugflag)
 
BOXApixLocateBarcodes (PIX *pixs, l_int32 thresh, PIX **ppixb, PIX **ppixm)
 
PIXpixDeskewBarcode (PIX *pixs, PIX *pixb, BOX *box, l_int32 margin, l_int32 threshold, l_float32 *pangle, l_float32 *pconf)
 
NUMApixExtractBarcodeWidths1 (PIX *pixs, l_float32 thresh, l_float32 binfract, NUMA **pnaehist, NUMA **pnaohist, l_int32 debugflag)
 
NUMApixExtractBarcodeWidths2 (PIX *pixs, l_float32 thresh, l_float32 *pwidth, NUMA **pnac, l_int32 debugflag)
 
NUMApixExtractBarcodeCrossings (PIX *pixs, l_float32 thresh, l_int32 debugflag)
 
NUMAnumaQuantizeCrossingsByWidth (NUMA *nas, l_float32 binfract, NUMA **pnaehist, NUMA **pnaohist, l_int32 debugflag)
 
NUMAnumaQuantizeCrossingsByWindow (NUMA *nas, l_float32 ratio, l_float32 *pwidth, l_float32 *pfirstloc, NUMA **pnac, l_int32 debugflag)
 

Variables

static const l_int32 MAX_SPACE_WIDTH = 19
 
static const l_int32 MAX_NOISE_WIDTH = 50
 
static const l_int32 MAX_NOISE_HEIGHT = 30
 
static const l_int32 MIN_BC_WIDTH = 50
 
static const l_int32 MIN_BC_HEIGHT = 50
 

Detailed Description


     Basic operations to locate and identify the line widths
     in 1D barcodes.

     Top level
         SARRAY          *pixProcessBarcodes()

     Next levels
         PIXA            *pixExtractBarcodes()
         SARRAY          *pixReadBarcodes()
         l_int32          pixReadBarcodeWidths()

     Location
         BOXA            *pixLocateBarcodes()
         static PIX      *pixGenerateBarcodeMask()

     Extraction and deskew
         PIXA            *pixDeskewBarcodes()

     Process to get line widths
         NUMA            *pixExtractBarcodeWidths1()
         NUMA            *pixExtractBarcodeWidths2()
         NUMA            *pixExtractBarcodeCrossings()

     Average adjacent rasters
         static NUMA     *pixAverageRasterScans()

     Signal processing for barcode widths
         NUMA            *numaQuantizeCrossingsByWidth()
         static l_int32   numaGetCrossingDistances()
         static NUMA     *numaLocatePeakRanges()
         static NUMA     *numaGetPeakCentroids()
         static NUMA     *numaGetPeakWidthLUT()
         NUMA            *numaQuantizeCrossingsByWindow()
         static l_int32   numaEvalBestWidthAndShift()
         static l_int32   numaEvalSyncError()


 NOTE CAREFULLY: This is "early beta" code.  It has not been tuned
 to work robustly on a large database of barcode images.  I'm putting
 it out so that people can play with it, find out how it breaks, and
 contribute decoders for other barcode formats.  Both the functional
 interfaces and ABI will almost certainly change in the coming
 few months.  The actual decoder, in bardecode.c, at present only
 works on the following codes: Code I2of5, Code 2of5, Code 39, Code 93
 Codabar and UPCA.  To add another barcode format, it is necessary
 to make changes in readbarcode.h and bardecode.c.
 The program prog/barcodetest shows how to run from the top level
 (image --> decoded data).

Definition in file readbarcode.c.

Function Documentation

◆ numaEvalBestWidthAndShift()

static l_int32 numaEvalBestWidthAndShift ( NUMA nas,
l_int32  nwidth,
l_int32  nshift,
l_float32  minwidth,
l_float32  maxwidth,
l_float32 *  pbestwidth,
l_float32 *  pbestshift,
l_float32 *  pbestscore 
)
static

numaEvalBestWidthAndShift()

Parameters
[in]nasnuma of crossing locations
[in]nwidthnumber of widths to consider
[in]nshiftnumber of shifts to consider for each width
[in]minwidthsmallest width to consider
[in]maxwidthlargest width to consider
[out]pbestwidthbest size of window
[out]pbestshiftbest shift for the window
[out]pbestscore[optional] average squared error of dist of crossing signal from the center of the window
Returns
0 if OK, 1 on error
Notes:
     (1) This does a linear sweep of widths, evaluating at nshift
         shifts for each width, finding the (width, shift) pair that
         gives the minimum score.

Definition at line 1415 of file readbarcode.c.

References lept_stderr(), and numaEvalSyncError().

Referenced by numaQuantizeCrossingsByWindow().

◆ numaEvalSyncError()

static l_int32 numaEvalSyncError ( NUMA nas,
l_int32  ifirst,
l_int32  ilast,
l_float32  width,
l_float32  shift,
l_float32 *  pscore,
NUMA **  pnad 
)
static

numaEvalSyncError()

Parameters
[in]nasnuma of crossing locations
[in]ifirstfirst crossing to use
[in]ilastlast crossing to use; use 0 for all crossings
[in]widthsize of window
[in]shiftof center of window w/rt first crossing
[out]pscore[optional] average squared error of dist of crossing signal from the center of the window
[out]pnad[optional] numa of 1s and 0s for crossings
Returns
0 if OK, 1 on error
Notes:
     (1) The score is computed only on the part of the signal from the
         ifirst to ilast crossings.  Use 0 for both of these to
         use all the crossings.  The score is normalized for
         the number of crossings and with half-width of the window.
     (2) The optional return nad is a sequence of 0s and 1s, where a '1'
         indicates a crossing in the window.

Definition at line 1489 of file readbarcode.c.

References numaCreate(), numaDestroy(), numaGetCount(), numaGetFValue(), numaGetIValue(), numaSetCount(), and numaSetValue().

Referenced by numaEvalBestWidthAndShift(), and numaQuantizeCrossingsByWindow().

◆ numaGetCrossingDistances()

static l_int32 numaGetCrossingDistances ( NUMA nas,
NUMA **  pnaedist,
NUMA **  pnaodist,
l_float32 *  pmindist,
l_float32 *  pmaxdist 
)
static

numaGetCrossingDistances()

Parameters
[in]nasnuma of crossing locations
[out]pnaedist[optional] even distances between crossings
[out]pnaodist[optional] odd distances between crossings
[out]pmindist[optional] min distance between crossings
[out]pmaxdist[optional] max distance between crossings
Returns
0 if OK, 1 on error

Definition at line 1026 of file readbarcode.c.

References numaAddNumber(), numaCopy(), numaCreate(), numaDestroy(), numaGetCount(), numaGetFValue(), numaHistogramGetValFromRank(), numaJoin(), and numaMakeHistogram().

Referenced by numaQuantizeCrossingsByWidth(), and numaQuantizeCrossingsByWindow().

◆ numaGetPeakCentroids()

static NUMA * numaGetPeakCentroids ( NUMA nahist,
NUMA narange 
)
static

numaGetPeakCentroids()

Parameters
[in]nahistnuma of histogram of crossing widths
[in]narangenuma of ranges of x-values for the peaks in nahist
Returns
nad centroids for each peak found; max of 4, corresponding to 4 different barcode line widths, or NULL on error

Definition at line 1170 of file readbarcode.c.

References numaAddNumber(), numaCreate(), numaGetCount(), numaGetFValue(), and numaGetIValue().

◆ numaGetPeakWidthLUT()

static NUMA * numaGetPeakWidthLUT ( NUMA narange,
NUMA nacent 
)
static

numaGetPeakWidthLUT()

Parameters
[in]narangenuma of x-val ranges for the histogram width peaks
[in]nacentnuma of centroids of each peak – up to 4
Returns
nalut lookup table from the width of a bar to one of the four integerized barcode units, or NULL on error
Notes:
     (1) This generates the lookup table that maps from a sequence of widths
         (in some units) to the integerized barcode units (1, 2, 3, 4),
         which are the output integer widths between transitions.
     (2) The smallest width can be lost in float roundoff.  To avoid
         losing it, we expand the peak range of the smallest width.

Definition at line 1221 of file readbarcode.c.

References L_NOCOPY, numaCreate(), numaGetCount(), numaGetFArray(), numaGetIValue(), numaGetMax(), numaSetCount(), and numaSetValue().

◆ numaLocatePeakRanges()

static NUMA * numaLocatePeakRanges ( NUMA nas,
l_float32  minfirst,
l_float32  minsep,
l_float32  maxmin 
)
static

numaLocatePeakRanges()

Parameters
[in]nasnuma of histogram of crossing widths
[in]minfirstmin location of center of first peak
[in]minsepmin separation between peak range centers
[in]maxminmax allowed value for min histo value between peaks
Returns
nad ranges for each peak found, in pairs, or NULL on error
Notes:
     (1) Units of minsep are the index into nas.
         This puts useful constraints on peak-finding.
     (2) If maxmin == 0.0, the value of nas[i] must go to 0.0 (or less)
         between peaks.
     (3) All calculations are done in units of the index into nas.
         The resulting ranges are therefore integers.
     (4) The output nad gives pairs of range values for successive peaks.
         Any location [i] for which maxmin = nas[i] = 0.0 will NOT be
         included in a peak range.  This works fine for histograms where
         if nas[i] == 0.0, it means that there are no samples at [i].
     (5) For barcodes, when this is used on a histogram of barcode
         widths, use maxmin = 0.0.  This requires that there is at
         least one histogram bin corresponding to a width value between
         adjacent peak ranges that is unpopulated, making the separation
         of the histogram peaks unambiguous.

Definition at line 1117 of file readbarcode.c.

References numaAddNumber(), numaCreate(), numaGetCount(), numaGetFValue(), and numaSetValue().

◆ numaQuantizeCrossingsByWidth()

NUMA* numaQuantizeCrossingsByWidth ( NUMA nas,
l_float32  binfract,
NUMA **  pnaehist,
NUMA **  pnaohist,
l_int32  debugflag 
)

numaQuantizeCrossingsByWidth()

Parameters
[in]nasnuma of crossing locations, in pixel units
[in]binfracthisto binsize as a fraction of minsize; e.g., 0.25
[out]pnaehist[optional] histo of even (black) bar widths
[out]pnaohist[optional] histo of odd (white) bar widths
[in]debugflag1 to generate plots of histograms of bar widths
Returns
nad sequence of widths, in unit sizes, or NULL on error
Notes:
     (1) This first computes the histogram of black and white bar widths,
         binned in appropriate units.  There should be well-defined
         peaks, each corresponding to a specific width.  The sequence
         of barcode widths (namely, the integers from the set {1,2,3,4})
         is returned.
     (2) The optional returned histograms are binned in width units
         that are inversely proportional to binfract.  For example,
         if binfract = 0.25, there are 4.0 bins in the distance of
         the width of the narrowest bar.

Definition at line 871 of file readbarcode.c.

References gplotCreate(), lept_mkdir(), numaDestroy(), numaGetCount(), numaGetCrossingDistances(), and numaMakeHistogramClipped().

◆ numaQuantizeCrossingsByWindow()

NUMA* numaQuantizeCrossingsByWindow ( NUMA nas,
l_float32  ratio,
l_float32 *  pwidth,
l_float32 *  pfirstloc,
NUMA **  pnac,
l_int32  debugflag 
)

numaQuantizeCrossingsByWindow()

Parameters
[in]nasnuma of crossing locations
[in]ratioof max window size over min window size in search; typ. 2.0
[out]pwidth[optional] best window width
[out]pfirstloc[optional] center of window for first xing
[out]pnac[optional] array of window crossings (0, 1, 2)
[in]debugflag1 to generate various plots of intermediate results
Returns
nad sequence of widths, in unit sizes, or NULL on error
Notes:
     (1) The minimum size of the window is set by the minimum
         distance between zero crossings.
     (2) The optional return signal nac is a sequence of 0s, 1s,
         and perhaps a few 2s, giving the number of crossings in each window.
         On the occasion where there is a '2', it is interpreted as
         ending two runs: the previous one and another one that has length 1.

Definition at line 1313 of file readbarcode.c.

References numaAddNumber(), numaCreate(), numaDestroy(), numaEvalBestWidthAndShift(), numaEvalSyncError(), numaGetCount(), numaGetCrossingDistances(), numaGetFValue(), and numaGetIValue().

◆ pixAverageRasterScans()

static NUMA * pixAverageRasterScans ( PIX pixs,
l_int32  nscans 
)
static

pixAverageRasterScans()

Parameters
[in]pixsinput image; 8 bpp
[in]nscansnumber of adjacent scans, about the center vertically
Returns
numa of average pixel values across image, or NULL on error

Definition at line 803 of file readbarcode.c.

◆ pixDeskewBarcode()

PIX* pixDeskewBarcode ( PIX pixs,
PIX pixb,
BOX box,
l_int32  margin,
l_int32  threshold,
l_float32 *  pangle,
l_float32 *  pconf 
)

pixDeskewBarcode()

Parameters
[in]pixsinput image; 8 bpp
[in]pixbbinarized edge-filtered input image
[in]boxidentified region containing barcode
[in]marginof extra pixels around box to extract
[in]thresholdfor binarization; ~20
[out]pangle[optional] in degrees, clockwise is positive
[out]pconf[optional] confidence
Returns
pixd deskewed barcode, or NULL on error
Notes:
    (1) The (optional) angle returned is the angle in degrees (cw positive)
        necessary to rotate the image so that it is deskewed.

Definition at line 512 of file readbarcode.c.

◆ pixExtractBarcodeCrossings()

NUMA* pixExtractBarcodeCrossings ( PIX pixs,
l_float32  thresh,
l_int32  debugflag 
)

pixExtractBarcodeCrossings()

Parameters
[in]pixsinput image; 8 bpp
[in]threshestimated pixel threshold for crossing white <--> black; typ. ~120
[in]debugflaguse 1 to generate debug output
Returns
numa of crossings, in pixel units, or NULL on error
Notes:
     (1) Require at least 10 crossings.

Definition at line 741 of file readbarcode.c.

◆ pixExtractBarcodes()

PIXA* pixExtractBarcodes ( PIX pixs,
l_int32  debugflag 
)

pixExtractBarcodes()

Parameters
[in]pixs8 bpp, no colormap
[in]debugflaguse 1 to generate debug output
Returns
pixa deskewed and cropped barcodes, or NULL if none found or on error

Definition at line 188 of file readbarcode.c.

◆ pixExtractBarcodeWidths1()

NUMA* pixExtractBarcodeWidths1 ( PIX pixs,
l_float32  thresh,
l_float32  binfract,
NUMA **  pnaehist,
NUMA **  pnaohist,
l_int32  debugflag 
)

pixExtractBarcodeWidths1()

Parameters
[in]pixsinput image; 8 bpp
[in]threshestimated pixel threshold for crossing white <--> black; typ. ~120
[in]binfracthisto binsize as a fraction of minsize; e.g., 0.25
[out]pnaehist[optional] histogram of black widths; NULL ok
[out]pnaohist[optional] histogram of white widths; NULL ok
[in]debugflaguse 1 to generate debug output
Returns
nad numa of barcode widths in encoded integer units, or NULL on error
Notes:
    (1) The widths are alternating black/white, starting with black
        and ending with black.
    (2) This method uses the widths of the bars directly, in terms
        of the (float) number of pixels between transitions.
        The histograms of these widths for black and white bars is
        generated and interpreted.

Definition at line 642 of file readbarcode.c.

◆ pixExtractBarcodeWidths2()

NUMA* pixExtractBarcodeWidths2 ( PIX pixs,
l_float32  thresh,
l_float32 *  pwidth,
NUMA **  pnac,
l_int32  debugflag 
)

pixExtractBarcodeWidths2()

Parameters
[in]pixsinput image; 8 bpp
[in]threshestimated pixel threshold for crossing white <--> black; typ. ~120
[out]pwidth[optional] best decoding window width, in pixels
[out]pnac[optional] number of transitions in each window
[in]debugflaguse 1 to generate debug output
Returns
nad numa of barcode widths in encoded integer units, or NULL on error
Notes:
     (1) The widths are alternating black/white, starting with black
         and ending with black.
     (2) The optional best decoding window width is the width of the window
         that is used to make a decision about whether a transition occurs.
         It is approximately the average width in pixels of the narrowest
         white and black bars (i.e., those corresponding to unit width).
     (3) The optional return signal nac is a sequence of 0s, 1s,
         and perhaps a few 2s, giving the number of crossings in each window.
         On the occasion where there is a '2', it is interpreted as
         as ending two runs: the previous one and another one that has length 1.

Definition at line 698 of file readbarcode.c.

◆ pixGenerateBarcodeMask()

static PIX * pixGenerateBarcodeMask ( PIX pixs,
l_int32  maxspace,
l_int32  nwidth,
l_int32  nheight 
)
static

pixGenerateBarcodeMask()

Parameters
[in]pixs1 bpp
[in]maxspacelargest space in the barcode, in pixels
[in]nwidthopening 'width' to remove noise
[in]nheightopening 'height' to remove noise
Returns
pixm mask over barcodes, or NULL if none found or on error
Notes:
     (1) For noise removal, 'width' and 'height' are referred to the
         barcode orientation.
     (2) If there is skew, the mask will not cover the barcode corners.

Definition at line 456 of file readbarcode.c.

◆ pixLocateBarcodes()

BOXA* pixLocateBarcodes ( PIX pixs,
l_int32  thresh,
PIX **  ppixb,
PIX **  ppixm 
)

pixLocateBarcodes()

Parameters
[in]pixsany depth
[in]threshfor binarization of edge filter output; typ. 20
[out]ppixb[optional] binarized edge filtered input image
[out]ppixm[optional] mask over barcodes
Returns
boxa location of barcodes, or NULL if none found or on error

Definition at line 396 of file readbarcode.c.

◆ pixProcessBarcodes()

SARRAY* pixProcessBarcodes ( PIX pixs,
l_int32  format,
l_int32  method,
SARRAY **  psaw,
l_int32  debugflag 
)

pixProcessBarcodes()

Parameters
[in]pixsany depth
[in]formatL_BF_ANY, L_BF_CODEI2OF5, L_BF_CODE93, ...
[in]methodL_USE_WIDTHS, L_USE_WINDOWS
[out]psaw[optional] sarray of bar widths
[in]debugflaguse 1 to generate debug output
Returns
sarray text of barcodes, or NULL if none found or on error

Definition at line 142 of file readbarcode.c.

References barcodeFormatIsSupported().

◆ pixReadBarcodes()

SARRAY* pixReadBarcodes ( PIXA pixa,
l_int32  format,
l_int32  method,
SARRAY **  psaw,
l_int32  debugflag 
)

pixReadBarcodes()

Parameters
[in]pixaof 8 bpp deskewed and cropped barcodes
[in]formatL_BF_ANY, L_BF_CODEI2OF5, L_BF_CODE93, ...
[in]methodL_USE_WIDTHS, L_USE_WINDOWS;
[out]psaw[optional] sarray of bar widths
[in]debugflaguse 1 to generate debug output
Returns
sa sarray of widths, one string for each barcode found, or NULL on error

Definition at line 261 of file readbarcode.c.

References barcodeFormatIsSupported(), L_CLONE, pixaGetCount(), pixaGetPix(), pixGetDimensions(), and sarrayCreate().

◆ pixReadBarcodeWidths()

NUMA* pixReadBarcodeWidths ( PIX pixs,
l_int32  method,
l_int32  debugflag 
)

pixReadBarcodeWidths()

Parameters
[in]pixsof 8 bpp deskewed and cropped barcode
[in]methodL_USE_WIDTHS, L_USE_WINDOWS;
[in]debugflaguse 1 to generate debug output
Returns
na numa of widths (each in set {1,2,3,4}, or NULL on error

Definition at line 347 of file readbarcode.c.