Reading barcodes

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

i did a test, i can’t explain how zxing work but i can tell you how i came to a working testcode (may be not the best):
i googled zxing read bar code and i found this code :

void readBar(BufferedImage barCodeBufferedImage){
try{
    LuminanceSource source = new BufferedImageLuminanceSource(barCodeBufferedImage);
    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
    Reader reader = new MultiFormatReader();
    Result result = reader.decode(bitmap);
    
    System.out.println("Barcode text is " + result.getText());
   }catch(Exception e){println(e);}
}

it looks doing what we want , taking an image and print barcode
in processing you get few errors like “The class “BufferedImage” does not exist”

google BufferedImage and i see it need :
import java.awt.image.BufferedImage;

to avoid all errors you need:

import com.google.zxing.*;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;

awt is already installed with java, but you need to add zxing, googled zxing.jar and i found it here
added this jar in a directory named “code” inside my sketch directory
no import error anymore, but readBar need a BufferedImage (not processing PImage)
in processing’s forum i searched pimage to BufferedImage and found:

BufferedImage getNative(PImage img) {  // ignore
    loadPixels();
    int type = 1;//(format == RGB) ?
      //BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
    BufferedImage image = new BufferedImage(img.width, img.height, type);
    WritableRaster wr = image.getRaster();
    wr.setDataElements(0, 0, img.width, img.height, img.pixels);
    return image;
  }

so we have everything needed
i changed :

void readBar(BufferedImage barCodeBufferedImage){
try{
    LuminanceSource source = new BufferedImageLuminanceSource(barCodeBufferedImage);

in

void readBar(PImage video){
try{BufferedImage barCodeBufferedImage = getNative(video);
    LuminanceSource source = new BufferedImageLuminanceSource(barCodeBufferedImage);

and it works
(well… my webcam is so bad, image is too blur for a real bar code, but showing a big one , it read it well)

Hello @th75,
after some workaround I wrote the following code - starting from your:

import com.google.zxing.*;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import processing.video.*;

Capture img;

void setup() {
  size(640, 360);
  img = new Capture(this, 320,240);
  img.start();
}

void captureEvent(Capture img) {
 readBar(img); 
}

void draw() {
  if (img.available()) {
    img.read();
  }
  
  image(img, 0, 0);
}

void readBar(PImage video) {
  try {
    BufferedImage barCodeBufferedImage = getNative(video);
    LuminanceSource source = new BufferedImageLuminanceSource(barCodeBufferedImage);
    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
    Reader reader = new MultiFormatReader();
    Result result = reader.decode(bitmap);

    System.out.println("Barcode text is " + result.getText());
    exit();
  }
  catch(Exception e) {
    println("");
  }
}

BufferedImage getNative(PImage img) {  // ignore
  loadPixels();
  int type = 1;//(format == RGB) ?
  //BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
  BufferedImage image = new BufferedImage(img.width, img.height, type);
  WritableRaster wr = image.getRaster();
  wr.setDataElements(0, 0, img.width, img.height, img.pixels);
  return image;
}

Unfortunately, it doesn’t read correctly the codes - I printed the code I posted earlier and it works, but other “real” codes are not correctly read

There are probably different types/ kinds of definitions for the codes. Did you check the specifications?

hi

could this run on android ?

well done,
as Chrisir said, i will suspect something about encoding…

by “are not correctly read”, do you mean it print wrong data or is not able to read them at all?

looking the image , do you think , image is more difficult than printed one?
for my fast try, i had a too bad camera for small real ones, so, to test, i searched barcode with google image and, filming the screen, all was read correctly…

in doc for MultiFormatReader , there is a “hint” option, where you can help by settings some normalised encoding,
list of hints here
(there is even a hint “try_harder” :face_with_monocle: )
may be set a key in your sketch to save img, to show us or to try it there: https://online-barcode-reader.inliteresearch.com/ and see what encoding is that
otherwise there is preprocessing before decode(bitmap), i will try to show bitmap on screen or save it, may be this preprocessing too have options (auto white balance, autocontrast…i don’t really know this library)
and last, if output is different than what is written,i will check if read is consistent in time?
:thinking:

something else in you code, i m not sure but i thing there is a timing problem:

capture Event reference
img is updated on img.read(); you update it in draw but you read bar code in capture event
i thing you need to do img.read(); first then readBar(img); and to do that sequence in capture event

(i think) capture event is an interruption triggered by the camera saying “hey i ve a new picture for you”
and draw is triggered by processing event “i need to draw something new to achieve expected framerate”, so those timing can be different

I didn’t; please consider that I’m a freshman coder and all seems so humongous that I can hardly imagine what you mean by “specifications” :slightly_smiling_face: