numpy 无需cv2.QRCodeDetector()或pyzbar库即可检测QR码的可靠程序

pgky5nke  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(140)

我很难找到一组形态学操作,使我能够使用cv2.connectedComponentsWithStats()cv2.findContours()(但我更愿意使用cv2.connectedComponentsWithStats())检测(仅)各种图像中的QR码。
我绝对需要代码来处理的图像如下:
第一次
我一直在使用两个不同的代码,一个使用cv2.connectedComponentsWithStats(),另一个使用cv2.findContours()和一些其他方法(基于nathancy对Detect a QR code from an image and crop using OpenCV的回答)。为了测试,我一直在使用以下代码:
1.使用cv2.connectedComponentsWithStats(),这个代码的问题是,它捕捉到的比第二个QR码更多,正如你在下面看到的。在第一个中它工作得很好,在第三个中也是如此,如果缩放到0.5,否则它也会像第二个图像一样检测到比QR码更多的信息。

import cv2
import numpy as np

#img = cv2.imread('Code-1.jpg'); scale = 1;
img = cv2.imread('Code-2.jpg'); scale = 1;
#img = cv2.imread('Code-3.jpg'); scale = 0.5;
width = int(img.shape[1] * scale); height = int(img.shape[0] * scale); img = cv2.resize(img, (width, height))

og = img.copy()

gray = np.zeros((img.shape[0], img.shape[1]), dtype=np.uint8)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

gaussianblur = cv2.GaussianBlur(gray, (7,7), 0)

otsuthresh = cv2.threshold(gaussianblur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

edges = cv2.Canny(otsuthresh, threshold1=100, threshold2=200)

dilate = cv2.dilate(edges,(5,5),iterations=1)

num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(dilate, 8, cv2.CV_32S)

for i in range(1,num_labels):
    objint = (labels == i).astype(np.uint8)*255/i
    x = stats[i, cv2.CC_STAT_LEFT]
    y = stats[i, cv2.CC_STAT_TOP]
    w = stats[i, cv2.CC_STAT_WIDTH]
    h = stats[i, cv2.CC_STAT_HEIGHT]
    area = stats[i, cv2.CC_STAT_AREA]
    ratio = w / float(h)
    (cX, cY) = centroids[i]
    if area > 500 and (ratio > .95 and ratio < 1.05) and (w < 0.99*img.shape[1]):
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
        ROI = og[y:y + h, x:x + w]
        cv2.imwrite('ROI.png', ROI)

cv2.imshow('image', img)
cv2.imshow('QR code', ROI)

1.使用cv2.findContours()时,该程序无法检测到图像中的任何QR代码,但可以检测到其他一些随机图像

import cv2
import numpy as np

#img = cv2.imread('Code-1.jpg'); scale = 1;
img = cv2.imread('Code-2.jpg'); scale = 1;
#img = cv2.imread('Code-3.jpg'); scale = 0.5;
width = int(img.shape[1] * scale); height = int(img.shape[0] * scale); img = cv2.resize(img, (width, height))

og = img.copy()

gray = np.zeros((img.shape[0], img.shape[1]), dtype=np.uint8)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

gaussianblur = cv2.GaussianBlur(gray, (7,7), 0)

otsuthresh = cv2.threshold(gaussianblur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
closed = cv2.morphologyEx(otsuthresh, cv2.MORPH_CLOSE, kernel, iterations=3)

contours = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

if len(contours) == 2:
    contours = contours[0]
else:
    contours = contours[1]

for cnt in contours:
    perim = cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, 0.05 * perim, True)
    x,y,w,h = cv2.boundingRect(approx)
    area = cv2.contourArea(cnt)
    ratio = w / float(h)
    if len(approx) == 4 and area > 1000 and (ratio > .80 and ratio < 1.2):
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 4)
        ROI = og[y:y + h, x:x + w]
        cv2.imwrite('ROI.png', ROI)

cv2.imshow('image', img)
cv2.imshow('QR code', ROI)

谢谢你的阅读,如果我不清楚的东西,请让我知道。
菲利佩·阿尔梅达

i5desfxk

i5desfxk1#

也许,你可以试试QReader。它只是一个OpenCV,Pyzbar和其他QR检测和图像过滤方法的 Package 器,但它对这些情况的工作相当开箱即用。

from qreader import QReader
from matplotlib import pyplot as plt
import cv2

if __name__ == '__main__':
    # Initialize QReader
    detector = QReader()
    for img_path in ('0oOAF.jpg', 'HXlS8.jpg', '5fFTo.jpg'):
        # Read the image
        img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB)

        # Detect the QR bbox
        found, bbox = detector.detect(image=img)
        if found:
            # Draw the bbox
            x1, y1, x2, y2 = bbox
            cv2.rectangle(img=img, pt1=(x1, y1), pt2=(x2, y2), color=(0, 255, 0), thickness=2)
            # Save the image
            plt.imshow(img)
            plt.savefig(f"{img_path}-bbox.png")

这就是它给出的输出:
第一次

相关问题