[英]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)
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
: medianBlur
和resize
后的图像:
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:笔记:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.