用Python预处理图像进行QR码检测

5
我使用了Zbar和OpenCV来读取下面图片中的QR码,但是两者都无法检测到。对于ZBar,我使用pyzbar库作为Python的封装程序。有些图像可以正确地检测到QR码,也有一些与成功的图像非常相似但失败了。我的手机相机可以读取上传图片中的QR码,这意味着它是有效的。以下是代码片段:
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
import cv2

# zbar    
results = decode(cv2.imread(image_path), symbols=[ZBarSymbol.QRCODE])
print(results) 

# opencv
qr_decoder = cv2.QRCodeDetector()
data, bbox, rectified_image = qr_decoder.detectAndDecode(cv2.imread(image_path))
print(data, bbox)

什么类型的预处理有助于增加QR码检测成功率? the image attached

这在这种情况下也非常有用: https://dev59.com/OFIG5IYBdhLWcg3wtz9F - fifofonix
3个回答

6

zbar 做了一些预处理,但不会检测QR码,你可以使用 zbarimg image.jpg 进行测试。

好的 二值化 在这里是有用的。我使用 Kraken 库的 kraken.binarization.nlbin() 函数使其工作。该库是用于OCR的,但通过使用非线性处理,也非常适用于QR码。Kraken 二值化代码在这里

以下是示例代码:

from kraken import binarization
from PIL import Image
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol

image_path = "image.jpg"
# binarization using kraken
im = Image.open(image_path)
bw_im = binarization.nlbin(im)
# zbar
decode(bw_im, symbols=[ZBarSymbol.QRCODE])

[Decoded(data=b'DE-AAA002065', type='QRCODE', rect=Rect(left=1429, top=361, width=300, height=306), polygon=[Point(x=1429, y=361), Point(x=1429, y=667), Point(x=1729, y=667), Point(x=1723, y=365)])]

下面的图片展示了二值化后QR码的清晰图像:

二值化后的图片


值得注意的是,Kraken似乎在Windows系统中不可用,只能在Linux和MacOS上使用。 - undefined

5

我曾经遇到类似的问题,而 Seanpue 的回答让我对该问题有了正确的理解。由于我已经在图像处理中使用 OpenCV 库而不是 PIL,因此我按照OpenCV 图像阈值教程中的说明使用它来执行 Otsu 二值化。这是我的代码:

import cv2
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol

image_path = "qr.jpg"
# preprocessing using opencv
im = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
blur = cv2.GaussianBlur(im, (5, 5), 0)
ret, bw_im = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# zbar
decode(bw_im, symbols=[ZBarSymbol.QRCODE])

[Decoded(data=b'DE-AAA002065', type='QRCODE', rect=Rect(left=1429, top=362, width=300, height=305), polygon=[Point(x=1429, y=362), Point(x=1430, y=667), Point(x=1729, y=667), Point(x=1724, y=366)])]

应用高斯模糊旨在从图片中去除噪声,以使二值化更有效,但对于我的应用程序而言,它实际上并没有产生太大的影响。关键是将图像转换为灰度图像,以使阈值函数发挥作用(通过使用带有 cv2.IMREAD_GRAYSCALE 标志打开文件来完成)。

2
除此之外,我发现我必须缩小涉及的图像。相机拍摄的 4000x3000 照片似乎存在问题,但当缩放为 1600x1200 时,一切解决! - fifofonix

2
"

QReader 过去在这些情况下表现得相当不错。

"
from qreader import QReader
import cv2

if __name__ == '__main__':
    # Initialize QReader
    detector = QReader()
    img = cv2.cvtColor(cv2.imread('92iKG.jpg'), cv2.COLOR_BGR2RGB)
    # Detect and Decode the QR
    print(detector.detect_and_decode(image=img))

这段代码的输出结果是该二维码:
DE-AAA002065

QReader无法识别二维码版本20及以上(大型)。看起来它只能识别小型二维码。 - hldev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接