0

I have images of receipts and some of them have QR codes. I want to reliably detect QR codes in these images. It's not important the location of the QR code, just whether it is present in an image of a receipt or not.

My current progress:

import cv2

uri = 'dummy-uri'
qrCodeDetector = cv2.QRCodeDetector()
image = io.imread(uri)
decodedText, points, _ = self.qrCodeDetector.detectAndDecode(image)
NoneType = type(None)
if type(points) is not NoneType:
            print('There is QR code in the image')
else:
            print('There is not QR code in the image')

Basically, point is None if there is no QR code - there are no points of the edges. But the cv2 QrCodeDetector does not perform really well. I could imagine that training an object detector (Yolo, for example) would give way higher accuracy. Right now, most of the images I have of receipts are identified as ones without QR codes, although they have one. Any ideas of how to detect QR codes more reliably (with higher accuracy) ?

jpeg
  • 2,372
  • 4
  • 18
  • 31
  • convert your image to grayscale for more accuracy.Also there are modules only for qr codes – farhan jatt Aug 04 '21 at 13:54
  • Can you point me out? – Петър Улев Aug 04 '21 at 13:58
  • https://stackoverflow.com/questions/27233351/how-to-decode-a-qr-code-image-in-preferably-pure-python – farhan jatt Aug 04 '21 at 13:59
  • Unfortunately, the solution doesn't work. AttributeError: module 'qrtools' has no attribute 'QR' – Петър Улев Aug 04 '21 at 14:14
  • I tried the solutions there, but still no QR code is detected. This was the main point of my question, I know that if I have a good image there is no problem, but on the receipt, the QR code is usually smaller and the pyzbar doesn't detect it. What can I do ? – Петър Улев Aug 04 '21 at 14:16
  • use gray scale to increase accuracy of cv2 – farhan jatt Aug 04 '21 at 14:17
  • Okay! :) I will try and let you know – Петър Улев Aug 04 '21 at 14:22
  • The result is exactly the same. No improvement :( – Петър Улев Aug 04 '21 at 21:00
  • Any suggestions ? – Петър Улев Aug 04 '21 at 21:07
  • try to use corner detection of cv2 to cut image. see "https://www.youtube.com/watch?v=I7lCpTOfxF4" – farhan jatt Aug 05 '21 at 01:32
  • Tried it, but it doesn't work, since the cv2 detect all kinds of corners (of numbers, letters, and so on). It doesn't know that it should detect the corners of the QR code. It doesn't work. – Петър Улев Aug 05 '21 at 08:32
  • use them to crop part image i.e crop the area where corners have same distance it is very complicated but last option for you or you can wait to learn ML and train it to get the job done – farhan jatt Aug 05 '21 at 13:05
  • can you send me some images i will work on it.I was busy in my examinations but now i have a huge gap in next so i,ll try to solve your problem by tomorrow – farhan jatt Aug 05 '21 at 13:14
  • Yes, sure! Here are some images: 1. http://jackdaniels-uploads.s3-website-us-east-1.amazonaws.com/node_1115/1621834819702_IMG_20210524_083452.jpg 2. http://jackdaniels-uploads.s3-website-us-east-1.amazonaws.com/node_1115/1621855342309_16218553250267646166612185929662.jpg 3. http://jackdaniels-uploads.s3-website-us-east-1.amazonaws.com/node_1115/1621860888557_16218607951547146430434981146191.jpg 4. http://jackdaniels-uploads.s3-website-us-east-1.amazonaws.com/node_1115/1621866387955_image.jpg – Петър Улев Aug 05 '21 at 13:55

2 Answers2

1

I tried doing template matching.It will give quite accurate results if the template and the picture are of same size this code gives good results for 2 images but in others the template provided and qr code in image is of different size so it is not showing desired results

import numpy as np
import cv2

I resized image to decrease difference btw template and full image. qr.png is screenshot of actual image

img  = cv2.resize(cv2.imread('Download/full.jpg', 0), (0, 0), fx=0.2, fy=0.17)
template = cv2.imread('qr.png', 0)
h, w = template.shape

methods list describe different methods to find template.You can test which one is more accurate by checking one by in for loop and select it.

methods = [cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED, cv2.TM_CCORR,
            cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]

for method in methods:
    img2 = img.copy()

    result = cv2.matchTemplate(img2, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        location = min_loc
    else:
        location = max_loc
    bottom_right = (location[0] + w, location[1] + h)
    cv2.rectangle(img2, location, bottom_right, 255, 5)
    cv2.imshow('Match', img2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

More details of code can be found on this link

farhan jatt
  • 509
  • 1
  • 8
  • 31
0

You could try QRDet, that's a quite straight-forward QR Detector based on YOLOv7 and tends to work pretty well in difficult images.

from qrdet import QRDetector
import cv2

detector = QRDetector()
image = cv2.imread(filename='path/to/your/image')
detections = detector.detect(image=image, is_bgr=True)

print(f"There is {'not' if len(detections == 0 else ''} QR code in the image")
Haru Kaeru
  • 41
  • 3