简体   繁体   English

Pyzbar 无法解码二维码

[英]Pyzbar Can't Decode QRCode

Have a bunch of QR Code labels printed from the same label printer, all can be read except for this one.同一台label打印机打印了一堆QR Code标签,除了这个都可以读取。

Have tried all solutions from Preprocessing images for QR detection in python已尝试python 中用于 QR 检测的预处理图像的所有解决方案

二维码

Losing my mind... any help appreciated!失去理智......任何帮助表示赞赏!

Code is here:代码在这里:

import cv2
import numpy as np
from pyzbar.pyzbar import decode
from pyzbar.pyzbar import ZBarSymbol
from kraken import binarization
from PIL import Image
from qreader import QReader

image_path = r"C:\Users\ASinger\Pictures\hdi_pdfs\page1.png"

# Method 1
im = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
ret, bw_im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
barcodes = decode(bw_im, symbols=[ZBarSymbol.QRCODE])
print(f'barcodes: {barcodes}')

# Method 2
im = Image.open(image_path)
bw_im = binarization.nlbin(im)
decoded = decode(bw_im, symbols=[ZBarSymbol.QRCODE])
print(f'decoded: {decoded}')

# Method 3
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)
decoded = decode(bw_im, symbols=[ZBarSymbol.QRCODE])
print(f'decoded: {decoded}')

# Method 4
qreader = QReader()
image = cv2.imread(image_path)
decoded_text = qreader.detect_and_decode(image=image)
print(f'decoded_text: {decoded_text}')

# Method 5
cropped_image = image_path
im2 = Image.open(cropped_image)
im2 = im2.resize((2800, 2800))
im2.save(cropped_image, quality=500)
im2.show()
im3 = cv2.imread(cropped_image, cv2.IMREAD_GRAYSCALE)
ret, bw_im = cv2.threshold(im3, 127, 255, cv2.THRESH_BINARY)
decoded = decode(bw_im, symbols=[ZBarSymbol.QRCODE])
print(f'decoded: {decoded}')

It's difficult to tell why Pyzbar fails, but we may guess that the issue is related to low quality scanning artifacts, and maybe compression artifacts.很难说出 Pyzbar 失败的原因,但我们可能会猜测该问题与低质量扫描伪影有关,也可能与压缩伪影有关。

Here is a small ROI in native resolution:这是原始分辨率下的小投资回报率:
在此处输入图像描述

As you can see there is a lot of noise and artifacts.如您所见,有很多噪音和伪像。

For improving the quality I recommend using cv2.medianBlur filter:为了提高质量,我建议使用cv2.medianBlur过滤器:

clean_im = cv2.medianBlur(im, 25)
  • Median filter was selected because it applies fine threshold between black and white.选择中值滤波器是因为它在黑色和白色之间应用了精细的阈值。
  • The size of the filter was selected to be 25 (relatively large) because the resolution of the image is relatively high compared to the details of the QR Code.过滤器的大小选择为25(比较大),因为图像的分辨率相对于QR Code的细节来说是比较高的。

Same ROI after filtering:过滤后相同的投资回报率:
在此处输入图像描述

As you can see the noise is much lower, but the details are blurred.正如您所看到的,噪音要低得多,但细节却很模糊。


For improving the issue, we may downscale the image using cv2.resize :为了改善这个问题,我们可以使用cv2.resize缩小图像:

small_clean_im = cv2.resize(clean_im, (512, 512), interpolation=cv2.INTER_AREA)

Downscaling the image with cv2.INTER_AREA interpolation is merging multiple pixels into one pixel (kind of concentrating the data), and also remove noise.使用cv2.INTER_AREA插值缩小图像是将多个像素合并为一个像素(一种集中数据),并去除噪声。
The size 512x512 seems like a good tradeoff between keeping details and removing noise. 512x512 的大小似乎是保留细节和消除噪音之间的一个很好的折衷。

Image after medianBlur and resize : medianBlurresize后的图像:

在此处输入图像描述

Same image with resize only (without medianBlur ) for comparison:resize (没有medianBlur )的相同图像用于比较:
在此处输入图像描述


I suppose it's better not to apply a threshold before using Pyzbar decode method.我想最好不要在使用 Pyzbar decode方法之前应用阈值。
I assume the decode method uses an internal thresholding algorithm that may be better than our own thresholding.我假设解码方法使用内部阈值算法,该算法可能比我们自己的阈值算法更好。


Complete code sample:完整的代码示例:

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

im = cv2.imread('page1.png', cv2.IMREAD_GRAYSCALE)

clean_im = cv2.medianBlur(im, 25)  # Apply median blur for reducing noise
small_clean_im = cv2.resize(clean_im, (512, 512), interpolation=cv2.INTER_AREA)  # Downscale the image

barcodes = decode(small_clean_im, symbols=[ZBarSymbol.QRCODE])
print(f'barcodes: {barcodes}')

# Show image for testing
cv2.imshow('small_clean_im', small_clean_im)
cv2.waitKey()
cv2.destroyAllWindows()

Output: Output:
barcodes: [Decoded(data=b'P1693921.001', type='QRCODE', rect=Rect(left=137, top=112, width=175, height=175), polygon=[Point(x=137, y=280), Point(x=304, y=287), Point(x=312, y=119), Point(x=143, y=112)])]


Note:笔记:

  • The processing worked with the sample image, but it is not guaranteed to work with other images.该处理适用于示例图像,但不保证适用于其他图像。
    You may try different filter sizes, and different image sizes for improving the success rate.您可以尝试不同的过滤器尺寸和不同的图像尺寸以提高成功率。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM