Reputation: 1
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
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
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