The goal of this project is to allow integrated or USB-connected webcams to be accessed directly from Java. Using provided libraries users are able to read camera images and detect motion. Main project consist of several sub projects - the root one, which contains required classes, build-in webcam driver compatible with Windows, Linux and Mac OS, which can stream images as fast as your camera can serve them (up to 50 FPS). Main project can be used standalone, but user is able to replace build-in driver with different one - such as OpenIMAJ, GStreamer, V4L4j, JMF, LTI-CIVIL, FMJ, etc.
I'm currently working on a Java application that needs to scan Data Matrix QR-Codes, specifically to extract and display XML data in a text box. The QR-Codes I'm dealing with contain BMP (German medication plans). For testing purposes, I'm using examples from this document: https://download.hl7.de/ukf/Testfaelle_ukf201.pdf im running this on a microsoft surface go 4 business webcam specs are : Rear Camera:
Resolution: 8.0 megapixels Video Resolution: 1080p HD video
Logging in german btw
Here's the code I have so far:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamResolution;
import com.google.zxing.*;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import javax.swing.*;
import java.awt.*;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Logger;
public class QRCodeScanner extends JFrame implements Runnable, ThreadFactory {
private static final Logger LOGGER = Logger.getLogger(QRCodeScanner.class.getName());
private static final long serialVersionUID = 1L;
private BlockingQueue<String> decodedResultsQueue = new LinkedBlockingQueue<>();
private Executor executor = Executors.newSingleThreadExecutor(this);
private Webcam webcam = null;
private WebcamPanel panel = null;
private JTextArea textarea = null;
private JScrollPane scrollPane = null;
public QRCodeScanner() {
super();
setLayout(new BorderLayout());
setTitle("QR Code Scanner");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension size = WebcamResolution.VGA.getSize();
webcam = Webcam.getWebcams().get(1);
webcam.setViewSize(size);
panel = new WebcamPanel(webcam);
panel.setPreferredSize(size);
textarea = new JTextArea();
textarea.setEditable(false);
scrollPane = new JScrollPane(textarea);
scrollPane.setPreferredSize(size);
add(panel, BorderLayout.WEST);
add(scrollPane, BorderLayout.CENTER);
pack();
setVisible(true);
executor.execute(this);
}
@Override
public void run() {
do {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
LOGGER.severe("Thread interrupted: " + e.getMessage());
}
BufferedImage image = null;
if (webcam.isOpen()) {
LOGGER.info("Webcam is open.");
if ((image = webcam.getImage()) == null) {
LOGGER.warning("Webcam image is null.");
continue;
}
} else {
LOGGER.warning("Webcam is not open.");
}
Result result = processImageAndDecodeQRCode(image);
if (result != null) {
if (result.getBarcodeFormat() == BarcodeFormat.UPC_E) {
LOGGER.info("Detected UPC_E format, rescanning...");
continue;
}
result.getBarcodeFormat();
LOGGER.info("QR code format: " + result.getBarcodeFormat());
result.getNumBits();
LOGGER.info("QR code num bits: " + result.getNumBits());
result.getResultMetadata();
LOGGER.info("QR code result metadata: " + result.getResultMetadata());
result.getRawBytes();
LOGGER.info("QR code raw bytes: " + result.getRawBytes());
String text = result.getText();
LOGGER.info("QR code text: " + text);
decodedResultsQueue.add(text);
}
} while (true);
}
private Result processImageAndDecodeQRCode(BufferedImage image) {
// Preprocess image: convert to grayscale and apply thresholding
BufferedImage grayscaleImage = new BufferedImage(
image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics g = grayscaleImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
LuminanceSource source = new BufferedImageLuminanceSource(grayscaleImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = null;
try {
result = new MultiFormatReader().decode(bitmap);
} catch (NotFoundException e) {
LOGGER.warning("No QR code found.");
e.getCause();
}
return result;
}
public void startUIUpdateThread() {
new Thread(() -> {
while (true) {
try {
// Take the next decoded result from the queue and update the UI
String text = decodedResultsQueue.take();
textarea.append(text + "\n");
} catch (InterruptedException e) {
LOGGER.severe("UI update thread interrupted: " + e.getMessage());
}
}
}).start();
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "example-runner");
t.setDaemon(true);
return t;
}
public static void main(String[] args) {
QRCodeScanner scanner = new QRCodeScanner();
scanner.startUIUpdateThread(); // Start the UI update thread
}
}
I'm currently working on a Java application that needs to scan Data Matrix QR-Codes, specifically to extract and display XML data in a text box. The QR-Codes I'm dealing with contain BMP (German medication plans). For testing purposes, I'm using examples from this document: https://download.hl7.de/ukf/Testfaelle_ukf201.pdf im running this on a microsoft surface go 4 business webcam specs are : Rear Camera:
Resolution: 8.0 megapixels Video Resolution: 1080p HD video
Logging in german btw
Here's the code I have so far:
Tried it on online generated Data Matrix QR Codes and it works really well https://barcode.tec-it.com/en/DataMatrix?data=This%20is%20a%20Data%20Matrix%20by%20TEC-IT99999 Sometimes I'm able to scan those example codes from the PDF, but it takes too long, if it even works. I want this app to perform as well as those QR code scanners from the Play Store.
Maybe someone with more knowledge in computer vision can help me optimize the scanning process or suggest a more efficient approach?
Any assistance or pointers would be greatly appreciated. Thanks in advance!