mebjas / html5-qrcode

A cross platform HTML5 QR code reader. See end to end implementation at: https://scanapp.org
https://qrcode.minhazav.dev
Apache License 2.0
4.9k stars 959 forks source link

Has problems reading Code 39 barcodes after a certain length #636

Open motoyugota opened 1 year ago

motoyugota commented 1 year ago

I have custom barcodes generated by using "Libre Barcode 39" on Google Fonts (https://fonts.google.com/specimen/Libre+Barcode+39). If they are at most 8 or 9 characters, it seems they work fine, but with longer barcodes, it has a success rate of about 20% (at best). Most of the time it misreads two characters next to each other, but it is the same length, but sometimes, it will do an even worse job and somehow read it as only 5 characters or so. Here are some sample barcodes:

barcodes

The shorter ones seem to work fine, but the longer ones have consistent problems.

mebjas commented 1 year ago

I am able to reproduce this.

codeconqueror commented 1 year ago

I'm having the same problem. Tried versions 2.3.4-2.3.7 all with the same result. If I upload an image, it works great, but live scanning with the camera doesn't work at all as far as I can tell using a longer code 39 value like 'US1234567890'.

Caitlin-Finn commented 1 year ago

I am having this same error for every type of 2d barcode

matschek commented 1 year ago

I see the same problem with another Barcode 39 font with codes length of 9 (7 data + stars) Scanning "1510003" for 5 times I got: 3x 1510003 2x 15100003 1x 1580000

codeconqueror commented 1 year ago

To troubleshoot this issue, I switched to QuaggaJS and had the same problem, but I was able to get it working once I set the constraints to have a higher resolution, then everything worked. I have not had time to come back to this library and try to do the same but perhaps this would help alleviate the problem?

From QuaggaJS config (see width and height), is there something similar in html5-qrcode?

           constraints: {
                facingMode: "environment",
                width: { min: 640, ideal: 1280, max: 1920 },
                height: { min: 480, ideal: 720, max: 1080 },
                aspectRatio: { min: 1, max: 2, ideal: 1 }
            }
matschek commented 1 year ago

Further testing led me to assume that the problem does not originate directly from the library, but from the BarCode detector feature. By default, useBarCodeDetectorIfSupported is set to true, which gives control of detection to the browser, if I understood correctly. With useBarCodeDetectorIfSupported set to true, I get fast scans but with errors. However, with useBarCodeDetectorIfSupported set to false, I get accurate scans but at a slower pace. You can see the engine used in the decodedResult object, which shows decoderName as BarcodeDetector or zxing-js.

My implementation now serves as a quality check. If the decoderName is BarcodeDetector, then each scan is compared to the previous one, and only if three scans in a row have the same code, my scan-handler is invoked. The BarcodeDetector is still fast enough to provide an acceptable user experience

matschek commented 1 year ago

From QuaggaJS config (see width and height), is there something similar in html5-qrcode?

There is a videoConstraints option which seems to be the same object (MediaTrackConstraints). I did not get better results using your example values.

wombatstampede commented 1 year ago

html5-qrcode does take the image/data to be decoded from the video element canvas which is displayed. If this video elements width is smaller than the stream/camera width then scaled down data is used. I.e. on a phone you might have (in portrait) an element width of 370 and the stream width ist 480 (640x480 "upright") then the data is scaled down from width 480 to width 370.

To avoid downscaling, set the width of the reader div (where the video element is added later) to exactly the video stream width. And control the actual display size with the css "scale" (or "zoom" on older browsers). It helps to set also set the css property "transform-origin: 0 0" to facilate positioning.

Example: Div/Stream width is 480px and required display width ist 240px then use "scale: 0.5".

This is less critical when (tablets/desktop) the window is wider than the video stream but you could maybe improve performance by scaling.

Please tell me if I got something wrong. ;-)

matschek commented 1 year ago

I got significant better results when I started to use the zoom factor. Depending of the codes to scan, something between 2x and 4x is good. html5QrCode.applyVideoConstraints({ advanced : [ {zoom : 2 }] })

wombatstampede commented 1 year ago

Personally, I encounter most scanning problems on iPhones. And Safari regularly tells me in the getCapabilities that there's no zoom available. So, if Safari doesn't lie (well, that IS a possibility) applying zoom on iOS wouldn't do anything.

Do you actually see a difference (zoom) in the display when applying zoom on iPhones (specifically)? Android phones use the BarcodeDetector API anyways and (for me) show no scanning problems. (Edit: OK, I see that you had problems with the BarcodeDetector)

Here's a getCapabilities (html5QrCode.getRunningTrackCapabilities()) result on an iPhone 13: {"aspectRatio":{"max":4032,"min":0.00033068783068783067},"deviceId":"870405632E6BC9F7EE22B11873270BF3ADF8E88D","facingMode":["environment"],"frameRate":{"max":60,"min":1},"height":{"max":3024,"min":1 },"width":{"max":4032,"min":1}} (no zoom listed)

And here on an Android device (Xiaomi Mi Note 10): {"aspectRatio":0.75,"colorTemperature":0,"deviceId":"d1a261234af103637b78c4e0b746694906f3d448cd9e14ef04e5d0d08d4dc929","exposureCompensation":0,"exposureMode":"continuous","exposureTime":249,"facingMode":"environment","focusDistance":0.10000000149011612,"focusMode":"continuous","frameRate":30,"groupId":"3c24ca16dbfc091c9321c75cda5051fa94d4e8e12d9f16d91e81d5940788ac55","height":640,"iso":100,"resizeMode":"none","torch":false,"whiteBalanceMode":"continuous","width":480,"zoom":1} (zoom and torch listed)