Reading barcodes

Ciao!
I’d like to scan some UPC barcodes to get the product number, and after some research I unsuccessfully used the following libraries

  • Zxing for Processing (unable to load some plugins for gstreamer 1.0) and
  • QRCode (throws some errors in the console and seems dedicated to 2d barcodes)

Now I’m writing my own code starting from this image:

My approach is based on the image pixels’ brightness - if it’s greater than 200, draw a line:


PImage img;         

void setup() {
  size(1237, 1080);
  background(255);
  img = loadImage("campbell_soup_barcode.jpg");

}

void draw() {

  image(img, 0, 0);

  img.loadPixels();

  for (int x = 0; x < width; x++ ) {

    int loc = x + height/2 * img.width;
    float pixelBrightness = brightness(img.pixels[loc]);
      
    if (pixelBrightness > 200)  {
      stroke(255,0,0);
      line(x, 0, x, height);
    }

  }
  img.updatePixels();


}

This is the result, which gives me a pretty good approximation of the code that I’m reading:

Now comes the hazy part: I need to read the distance between the two outer red stripes and split it by 95 to get the unit width and then getting the binary code.
How can I do this??
As far as I know, to use dist() you have to know the point location; is there another way to get the measure?

1 Like

Woe…

You can use ANY java library with processing.

Sure, there is no library that works?

I suppose the point are not the libraries, but their usage… probably there is some piece missing and I’m not able to fix it. On Windows I’m having some troubles with gstreamer, here’s the screenshot while running Zxing for Processing, the BarcodeReaderCam example:

@Chrisir I’d appreciate a lot your suggestions on how to fix this…

When he doesn’t find the dll:

Do you have the dll?

You can (under windows) add the path to the path statement of windows iirc

Really no expert for QR… but have you installed GStream? What does the documentation tell you?

I neither have that dll nor found it reinstalling gstreamer; why does the software seek for a windows32 dll while I’m running a 64-bit OS?

Does it work even for 1D barcodes?

i have not trying it

but i found out that if any project could achieve without any kind of libraries is more flexible

And, by the way, any suggestion on how to get the distance between two parallel lines?

@jafal thank you for your support.
Before opening this topic I discarded that solution as seems to import too many libraries and it’s unclear if it’s oriented only to QR codes.

Did you see: Processing QRCode Library | Daniel Shiffman

take a look to this project

no libraries and its multi task you can modifies it as logic analyses or any other idea by replacing the ir receiver in Arduino

there is much to learn in this sketch despite its easy arrays, drawing lines in pattern, briny conversion, serial communication, spiting, timing and much more … you can play a lot with it

i am on win 7 64 bit i download the library now its working but my pc without camera

/*
QRcode reader
 Generate images from a QRcode generator such as
 http://qrcode.kaywa.com/ and put them in this sketch's
 data folder.
 Press spacebar to read from the camera, generate an image,
 and scan for barcodes.  Press f to read from a file and scan.
 Press s for camera settings.
 Created 9 June 2007
 by Tom Igoe / Daniel Shiffman
 */


import processing.video.*;
import qrcodeprocessing.*;

Capture video;                                 // instance of the video capture library
String statusMsg = "Waiting for an image";     // a string to return messages:

// Decoder object from prdecoder library
Decoder decoder;

void setup() {
  size(400, 320);
  video = new Capture(this, 320, 240);
  video.start();

  // Create a decoder object
  decoder = new Decoder(this);
}

// When the decoder object finishes
// this method will be invoked.
void decoderEvent(Decoder decoder) {
  statusMsg = decoder.getDecodedString();
}

void captureEvent(Capture video) {
  video.read();
}

void draw() {
  background(0);

  // Display video
  image(video, 0, 0);
  // Display status
  text(statusMsg, 10, height-4);

  // If we are currently decoding
  if (decoder.decoding()) {
    // Display the image being decoded
    PImage show = decoder.getImage();
    image(show, 0, 0, show.width/4, show.height/4); 
    statusMsg = "Decoding image";
    for (int i = 0; i < (frameCount/2) % 10; i++) statusMsg += ".";
  }
}

void keyReleased() {
  // Depending on which key is hit, do different things:
  switch (key) {
  case ' ':        
    // Spacebar takes a picture and tests it:
    // copy it to the PImage savedFrame:
    PImage savedFrame = createImage(video.width, video.height, RGB);
    savedFrame.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
    savedFrame.updatePixels();
    // Decode savedFrame
    decoder.decodeImage(savedFrame);
    break;
  case 'f':    // f runs a test on a file
    PImage preservedFrame = loadImage("qrcode.png");
    // Decode file
    decoder.decodeImage(preservedFrame);
    break;
  }
}

Well yes I tried to rerun the sketch QRCode example from QRCode library and by pressing spacebar or f it acquires the image to be read from the camera or from the file, despite of the error messages in the console.
However it seems to be working only with QR codes, I need 1D barcodes instead

1 Like

I can’t help you with that

As I said it should exist a java library since it is a standard problem

To analyze an image, this is hard- maybe check openCV library

See GitHub - zxing/zxing: ZXing ("Zebra Crossing") barcode scanning library for Java, Android

Or Barcodes recognition: How to create barcode scanner in Java with ABBYY Cloud OCR SDK – Help Center

if you want to process images as the sample you shown, image processing can be a fun project.

but if you want to process images from webcam, i will recommand using Zxing too. dealing with “real life” images, with poor contrast , noises, rotation artefact, color artefact and … it is really hard

and in the other hand, Zxing require only one jar:
org.apache.servicemix.bundles.zxing-3.4.1_1.jar

( no extra dll needed or install )

1 Like

I agree. As soon as it’ll be ready I’ll post my solution.

Would you be so kind to explain how to use it?
Thank you for your support!

Hello Th3cG,

You can find below my take on your problem.

This is the process I did:

  1. Extract the middle row of the image
  2. Convert the color to 0 or 1
  3. Get rid of the sides by finding the first black pixel in each direction
  4. Find the size of each band by dividing pixel total width (in pixels) by expected nb of bands
  5. sum and average pixel values of each band to determine if 0 or 1.

Of course it implies that the image is straight and the bar code centered but this can be done easily with openCV for example.

Here the code:
import java.util.Arrays;

final int bitNB = 95;
PImage barCode;
int[] singleRow;
int[] result = new int[bitNB];
int beg, end;
float stepSize;

void setup() {
  barCode = loadImage("barCode.jpeg");
  
  // Get the middle row of the picture
  int midRow = barCode.height / 2;
  
  // Extract the color value of the middle row
  barCode.loadPixels();
  beg = midRow * barCode.width;
  end = beg + barCode.width;
  singleRow = Arrays.copyOfRange(barCode.pixels, beg, end);
  
  // Convert the value to 0 or 1
  for (int i = 0; i < singleRow.length; i++) {
    singleRow[i] = (singleRow[i] & 0xFF) > 125 ? 1 : 0;
  }
  
  // Find first black pixels
  for (int i = 0; i < singleRow.length; i++) {
    if (singleRow[i] == 0) {
      beg = i;
      break;
    }
  }
  
  // Find last black pixels
  for (int i = singleRow.length - 1; i >= 0; i--) {
    if (singleRow[i] == 0) {
      end = i;
      break;
    }
  }
  
  // Find "width" of each bar
  stepSize = (float)(end - beg) / bitNB;
  float left = 0;
  float right = stepSize;
  
  // Read the bar code
  for (int n = 0; n < bitNB; n++) {
    // Set start point
    beg = floor(left);
    if (left - beg > 0.6) beg++; // the width can be a float number. Consider a pixel if at least 40% is within the range
    
    // Set end point
    end = ceil(right);
    if(end - right > 0.6) right--; // the width can be a float number. Consider a pixel if at least 40% is within the range
    
    // Sum and average the value
    float sum = 0;
    for (int i = beg; i < end + 1; i++) {
      sum += singleRow[i];
    }
    sum /= end - beg + 1;
    
    // Store value in result
    result[n] = sum > 0.5 ? 1 : 0;
    
    left = right;
    right += stepSize;
  }
  
  println(singleRow);
  println(beg, end);
  println(result);
}
2 Likes