cozmo / jsQR

A pure javascript QR code reading library. This library takes in raw images and will locate, extract and parse any QR code found within.
https://cozmo.github.io/jsQR/
Apache License 2.0
3.69k stars 607 forks source link

Do not detect colors? #145

Open Vogod opened 4 years ago

Vogod commented 4 years ago

First of all, congratulations on the scanner and thanks for sharing.

I have created a QR code with colors and the reader does not read it. Can it be configured in any way?

If I try to read the code with the iPhone camera, it does recognize it.

I have done the test at https://www.qrcode-monkey.com. If I create a code in black on a white background, the scanner reads it. If I take, for example, yellow over red background, the scanner is not able to read it.

Thanks!

bradisbell commented 4 years ago

Technically, the QR codes need to be black and white. But, I wonder if it makes sense to pre-process the image before sending it to this library? Make it black/white, perhaps increase contrast, then run it and see what happens?

cozmo commented 4 years ago

Make it black/white, perhaps increase contrast

That's what the first step of scanning for a QR is (and coincidentally it's the most resource intensive). I'd not attempt to duplicate it pre sending it to the library unless there is some domain specific tweaks you can do that will outperform the general binarization that jsQR does.

Specifically before attempting any detection/extraction, we "binarize" the image - that is turn a full color image -> greyscale -> binarized (effectively 100% contrast). This allows the rest of the process to work on an image matrix made up fully of either white or black pixels, not having to worry about greyscale/color etc.

Binarization is a fairly well studied problem, since it's needed for many computer vision tasks. If you simply crank the contrast up across an image you'll blow out light areas/dark areas. Most binarization techniques (including jsQR) work by separating the image into smaller areas, and using a different white/black threshold for each one. Additional work can be done to suppress noisy areas (that are most costly to process later on, etc).

I'm not saying that the jsQR binarizer is perfect (far from it), there's still a lot of improvements we could make from a performance and accuracy perspective, but I am saying there's a significant amount of complexity already applied to trying to extract as much detail from images regardless of lighting/color/noise, etc, and applying a simple pre process step will almost certainly have the opposite effect than you want - it'll decrease performance (by duplicating computation) and remove information that the jsQR binarization step would preserve.

That said, if you have domain specific knowledge (for example you know the QRs you scan would be a certain color) it's possible you could write a better binarizer taking in account that information (for example simply preserve all pixels similar to the colors you expect). If you go down this road I'd be interested in incorporating it into the binarize step (aka allow users to pass in optional color hints etc), which would allow us to reduce duplicated computation and extend the library in a way that would be helpful to others.

As for the original question - @Vogod - If you have a QR that doesn't scan correctly it'd be great if you could attach it to the issue, or if you're feeling like digging in a little bit it would be interesting to see how the binarizer is binarizing it, since that's 100% where the bug/change would live.

Hope this is helpful, and happy to help debug more etc.

sep2 commented 3 years ago

I would like to know is there a way to disable the binarization step completely, as my input source will be greyscale Uint8Array already (each element is a greyscale pixel) from an ar library (which I believe the library already did the binarization because it needs to do slam/image target detect, etc.)

cozmo commented 2 years ago

Well greyscale is not binarized (greyscale is usually 256 shades of lightness, whereas binarization is 2, thus the name).

Are you saying you're passing a binarized image? Aka an array that would only have the values 0 and 255?

hawkerboy7 commented 1 year ago

@cozmo Hi!

I required what @Vogod requested as well. Having read your comment, I've made my own processing of the image with different contrasts to make a clear binarized (0 or 255) image. Seeing as you've stated that this step is the most resource intensive, is there also some sort of option like {binarized: true} which would instruct jsQR to skip its own scanning (of the already binarized image) which should make the response faster?

Thank you for this scanner =D