Петър Улев
Петър Улев

Reputation: 1

Python how to detect QR code in image reliably

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) ?

Upvotes: 0

Views: 2407

Answers (2)

Haru Kaeru
Haru Kaeru

Reputation: 146

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")

Upvotes: 0

farhan jatt
farhan jatt

Reputation: 1056

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

Upvotes: 1

Related Questions