Search code examples
javaswingwebcamzxing

NotFoundException even when a barcode is in the picture


I am trying to make a simple barcode scanner project for fun. And I've run into a slight problem. I am using zXing and Webcam Capture for this.

Even if a Barcode is present in the picture, Java keeps telling me none is found through the NotFoundException. I look for a frame every time webcamImageObtained is run (which I assume is every frame?) and then I look for a barcode in the frame that I captured.

I took this picture with that webcam (Ironically using the code hah):

barcode

When I hover over this barcode it reports about 30 images per second and otherwise about 7-8 when it looks at me from my screen (if that means anything).

Whenever I find a code, I want to add it to a JList (not accounting for duplicates and the likes yet).

I call this code every time webcamImageObtained(WebcamEvent we) fires:

@Override
    public void webcamImageObtained(WebcamEvent we) {
        BufferedImage myImage;
        try {
            myImage = webcam.getImage();
            LuminanceSource source = new BufferedImageLuminanceSource(myImage);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Result result = reader.decode(bitmap);
            DefaultListModel dlm = (DefaultListModel) list.getModel();
            dlm.addElement(result.toString());
            list.setModel(dlm);
        } catch (NotFoundException ex) {
            Logger.getLogger(AdvancedWebcamPanelExample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ChecksumException ex) {
            Logger.getLogger(AdvancedWebcamPanelExample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FormatException ex) {
            Logger.getLogger(AdvancedWebcamPanelExample.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

Here is the entire class:

package sandbox_webcam;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamDiscoveryEvent;
import com.github.sarxos.webcam.WebcamDiscoveryListener;
import com.github.sarxos.webcam.WebcamEvent;
import com.github.sarxos.webcam.WebcamListener;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamPicker;
import com.github.sarxos.webcam.WebcamResolution;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;

public class AdvancedWebcamPanelExample extends JFrame implements Runnable, WebcamListener, WindowListener, UncaughtExceptionHandler, ItemListener, WebcamDiscoveryListener {

    private Webcam webcam = null;
    private WebcamPanel panel = null;
    private WebcamPicker picker = null;
    private JButton button = null;
    private JList list = null;
    private ActionListener buttonListener = null;
    private com.google.zxing.Reader reader = new com.google.zxing.MultiFormatReader();

    @Override
    public void run() {
        Webcam.addDiscoveryListener(this);

        setTitle("Java Webcam Capture POC");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        addWindowListener(this);

        picker = new WebcamPicker();
        picker.addItemListener(this);

        webcam = picker.getSelectedWebcam();

        if (webcam == null) {
            System.out.println("No webcams found...");
            System.exit(1);
        }

        webcam.setViewSize(WebcamResolution.VGA.getSize());
        webcam.addWebcamListener(AdvancedWebcamPanelExample.this);

        panel = new WebcamPanel(webcam, false);
        panel.setFPSDisplayed(true);

        buttonListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (webcam != null) {
                    BufferedImage image = webcam.getImage();
                    JFileChooser filechooser = new JFileChooser();

                    int saveValue = filechooser.showDialog(button, "Save");
                    if (saveValue == JFileChooser.APPROVE_OPTION) {
                        try {
                            File f = filechooser.getSelectedFile();
                            ImageIO.write(image, "png", new File(f.getAbsolutePath() + ".png"));
                            System.out.println("Picture saved at: " + f.getAbsolutePath());
                        } catch (IOException ex) {
                            System.err.println("Failed to save the picture!");
                            ex.printStackTrace();
                        }
                    }
                } else {
                    System.err.println("no webcam found to take a picture");
                }
            }
        };

        button = new JButton("Snap a Picture!");
        button.addActionListener(buttonListener);
        list = new JList();
        list.setMinimumSize(new Dimension(200,this.getHeight()));

        add(picker, BorderLayout.NORTH);
        add(panel, BorderLayout.CENTER);
        add(button, BorderLayout.SOUTH);
        add(list, BorderLayout.EAST);

        pack();
        setVisible(true);

        Thread t = new Thread() {
            @Override
            public void run() {
                panel.start();
            }
        };

        t.setName("example-starter");
        t.setDaemon(true);
        t.setUncaughtExceptionHandler(this);
        t.start();
    }

    @Override
    public void webcamOpen(WebcamEvent we) {
        System.out.println("webcam open");
    }

    @Override
    public void webcamClosed(WebcamEvent we) {
        System.out.println("webcam closed");
    }

    @Override
    public void webcamDisposed(WebcamEvent we) {
        System.out.println("webcam disposed");
    }

    @Override
    public void webcamImageObtained(WebcamEvent we) {
        BufferedImage myImage;
        try {
            myImage = webcam.getImage();
            LuminanceSource source = new BufferedImageLuminanceSource(myImage);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Result result = reader.decode(bitmap);
            DefaultListModel dlm = (DefaultListModel) list.getModel();
            dlm.addElement(result.toString());
            list.setModel(dlm);
        } catch (NotFoundException ex) {
            Logger.getLogger(AdvancedWebcamPanelExample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ChecksumException ex) {
            Logger.getLogger(AdvancedWebcamPanelExample.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FormatException ex) {
            Logger.getLogger(AdvancedWebcamPanelExample.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void windowOpened(WindowEvent e) {
        // do nothing
    }

    @Override
    public void windowClosing(WindowEvent e) {
        // do nothing
    }

    @Override
    public void windowClosed(WindowEvent e) {
        webcam.close();
    }

    @Override
    public void windowIconified(WindowEvent e) {
        System.out.println("webcam viewer paused");
        panel.pause();
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
        System.out.println("webcam viewer resumed");
        panel.resume();
    }

    @Override
    public void windowActivated(WindowEvent e) {
        // do nothing
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
        // do nothing
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.err.println(String.format("Exception in thread #s", t.getName()));
        e.printStackTrace();
    }

    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getItem() != webcam) {
            if (webcam != null) {
                panel.stop();

                remove(panel);
                webcam.removeWebcamListener(this);
                webcam.close();

                webcam = (Webcam) e.getItem();
                webcam.setViewSize(WebcamResolution.VGA.getSize());
                webcam.addWebcamListener(this);

                System.out.println("selected " + webcam.getName());

                panel = new WebcamPanel(webcam, false);
                panel.setFPSDisplayed(true);

                add(panel, BorderLayout.CENTER);
                pack();

                Thread t = new Thread() {
                    @Override
                    public void run() {
                        panel.start();
                    }
                };

                t.setName("example-stopper");
                t.setDaemon(true);
                t.setUncaughtExceptionHandler(this);
                t.start();
            }
        }
    }

    @Override
    public void webcamFound(WebcamDiscoveryEvent event) {
        if (picker != null) {
            picker.addItem(event.getWebcam());
        }
    }

    @Override
    public void webcamGone(WebcamDiscoveryEvent event) {
        if (picker != null) {
            picker.removeItem(event.getWebcam());
        }
    }

}

Am I missing something about how this library scans for a barcode?

EDIT

Not sure this helps much..

Mar 02, 2015 10:04:34 PM sandbox_webcam.AdvancedWebcamPanelExample webcamImageObtained
SEVERE: null
com.google.zxing.NotFoundException

Throws exception here:

Result result = reader.decode(bitmap);

Solution

  • There is a different question which has some available answers: Android zxing NotFoundException

    As James said, it is a good idea to try with bar codes on different media (paper/screen) if it is not working, and in different circumstances and lighting conditions. Particularly ensure that you have enough light, and that the FPS of the camera is high enough while it is pointed at the barcode.

    For debugging, one could also convert the BinaryImage back into a viewable format and check whether the barcode is actually visible after conversion to black-and-white.