损坏二维码重建
Damaged QrCode Reconstructing
编辑
下图是原始图像的预处理序列。
1. 原始图像 -> 2. 模糊 x n 次以使二维码位置有意义 -> 3. 裁剪原始图像,使用 blob 从第二步提取的位置 -> 4. 锐化和阈值 -> 5. 检查二维码的三个正方形 -> 6 . 进行额外的转换,如旋转 -> (最终图像)(具有调整大小分辨率的裁剪图像。)
老问题
我正在尝试从原始图像重建二维码。如您所见,照片的二维码已损坏,因此我使用 Aforge 库使用 blob 从图像中检测 3 个正方形。现在我不明白的是从这些信息生成二维码的逻辑。用给定的信息重构二维码在技术上是否可行?
这会很困难。
如果您可以使用 reader 解码此二维码(我试过但失败了),则可以使用写入器对其重新编码。但不能保证作者会重新创建相同的内容,因为可能有不同的编码选项。
如果你的目标实际上是能够解码,那你就卡住了。解码 "by hand" 可能是可能的,但冗长而复杂。您也可以考虑在完美的网格上手动重绘代码,并将其传递给 reader.
这是一个有趣的问题。要回答您的问题,这在技术上是否可行。是的,这当然是可能的。您问题中的二维码编码为“5176941.12”。
这里是预置图片,方便手动设置像素。
这一步之后,我用excel对每个像素点一一设置。之后只需将 phone 指向计算机屏幕即可。这就是它的样子。如果你想要 excel sheet,你可以 here.
既然可能性的问题已经解决了,如何使其自动化?在不知道更多额外样本的情况下,很难确定。但是,仅基于此示例,最简单的方法就是在裁剪后的 QR 图像上对齐 21x21 网格并使用阈值填充值。然后将此图像传递给您的 QR 解码器。 QR码有一定程度的冗余,所以即使部分像素丢失,你也很可能能够恢复原始数据。
编辑
下面是 python 中的一些代码,可以作为您如何自动执行此操作的指南。需要注意的几点:
- 我绕过了检测3个盒子的步骤,手动裁剪得很紧。如果抓图过程中出现旋转,需要修复。
- 阈值0.6需要针对不同的图像进行调整。现在,即使有多个错误,它 'luckily' 也能正常工作。如果错误太多,您可能永远无法获得有效的二维码。
代码:
import cv2
import numpy as np
def fill3box(qr):
qr[0:7,0:7] = 1
qr[14:21,14:21] = 1
qr[14:21,0:7] = 1
qr[0,0:6]=0
qr[0:6,0]=0
qr[0:6,6]=0
qr[6,0:7]=0
qr[2:5,2:5]=0
qr[14:21,14:21] = qr[0:7,0:7]
qr[14:21,0:7] = qr[0:7,0:7]
return qr
im = cv2.imread('to_process.png')
im = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
im = cv2.resize(im,(210,210))
im = 1-((im - im.min())/(im.max()-im.min())) #normalize and adjust contrast
avg=np.average(im)
qr = np.ones((21,21))
w,h = im.shape[:2]
im_orig = im.copy()
im[im<avg]=0#binarize
im[im>avg]=1
for y in range(21):
for x in range(21):
x1,y1 = (round(x*w/21),round(y*h/21))
x2,y2 = (round(x1+10),round(y1+10))
im_box = im[y1:y2,x1:x2]
if np.average(im_box)<0.6 and qr[y,x]!=0:#0.6 need tweaking
qr[y,x]=0
qr = fill3box(qr) #clean up 3 box areas as they need to be fixed
# debug visualization
for x in range(21):
p1 = (round(x*w/21),0)
p2 = (round(x*w/21),h)
cv2.line(im_orig,p1,p2,(255),1)
for y in range(21):
p1 = (0,round(y*h/21))
p2 = (w,round(y*h/21))
cv2.line(im_orig,p1,p2,(255),1)
qr = cv2.resize(qr,(210,210),interpolation=cv2.INTER_NEAREST)
im = (im*255).astype(np.uint8)
qr= (qr*255).astype(np.uint8)
im_orig= (im_orig*255).astype(np.uint8)
cv2.imwrite('im.png',im)
cv2.imwrite('qr.png',qr)
cv2.imwrite('im_orig.png',im_orig)
在代码中裁剪图像 to_process.png
。
叠加网格以显示此方法的工作原理
阈值图像。
已重新生成二维码,请注意,即使有多个错误,它仍然有效。
编辑 下图是原始图像的预处理序列。 1. 原始图像 -> 2. 模糊 x n 次以使二维码位置有意义 -> 3. 裁剪原始图像,使用 blob 从第二步提取的位置 -> 4. 锐化和阈值 -> 5. 检查二维码的三个正方形 -> 6 . 进行额外的转换,如旋转 -> (最终图像)(具有调整大小分辨率的裁剪图像。)
老问题 我正在尝试从原始图像重建二维码。如您所见,照片的二维码已损坏,因此我使用 Aforge 库使用 blob 从图像中检测 3 个正方形。现在我不明白的是从这些信息生成二维码的逻辑。用给定的信息重构二维码在技术上是否可行?
这会很困难。
如果您可以使用 reader 解码此二维码(我试过但失败了),则可以使用写入器对其重新编码。但不能保证作者会重新创建相同的内容,因为可能有不同的编码选项。
如果你的目标实际上是能够解码,那你就卡住了。解码 "by hand" 可能是可能的,但冗长而复杂。您也可以考虑在完美的网格上手动重绘代码,并将其传递给 reader.
这是一个有趣的问题。要回答您的问题,这在技术上是否可行。是的,这当然是可能的。您问题中的二维码编码为“5176941.12”。
这里是预置图片,方便手动设置像素。
这一步之后,我用excel对每个像素点一一设置。之后只需将 phone 指向计算机屏幕即可。这就是它的样子。如果你想要 excel sheet,你可以 here.
既然可能性的问题已经解决了,如何使其自动化?在不知道更多额外样本的情况下,很难确定。但是,仅基于此示例,最简单的方法就是在裁剪后的 QR 图像上对齐 21x21 网格并使用阈值填充值。然后将此图像传递给您的 QR 解码器。 QR码有一定程度的冗余,所以即使部分像素丢失,你也很可能能够恢复原始数据。
编辑
下面是 python 中的一些代码,可以作为您如何自动执行此操作的指南。需要注意的几点:
- 我绕过了检测3个盒子的步骤,手动裁剪得很紧。如果抓图过程中出现旋转,需要修复。
- 阈值0.6需要针对不同的图像进行调整。现在,即使有多个错误,它 'luckily' 也能正常工作。如果错误太多,您可能永远无法获得有效的二维码。
代码:
import cv2
import numpy as np
def fill3box(qr):
qr[0:7,0:7] = 1
qr[14:21,14:21] = 1
qr[14:21,0:7] = 1
qr[0,0:6]=0
qr[0:6,0]=0
qr[0:6,6]=0
qr[6,0:7]=0
qr[2:5,2:5]=0
qr[14:21,14:21] = qr[0:7,0:7]
qr[14:21,0:7] = qr[0:7,0:7]
return qr
im = cv2.imread('to_process.png')
im = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
im = cv2.resize(im,(210,210))
im = 1-((im - im.min())/(im.max()-im.min())) #normalize and adjust contrast
avg=np.average(im)
qr = np.ones((21,21))
w,h = im.shape[:2]
im_orig = im.copy()
im[im<avg]=0#binarize
im[im>avg]=1
for y in range(21):
for x in range(21):
x1,y1 = (round(x*w/21),round(y*h/21))
x2,y2 = (round(x1+10),round(y1+10))
im_box = im[y1:y2,x1:x2]
if np.average(im_box)<0.6 and qr[y,x]!=0:#0.6 need tweaking
qr[y,x]=0
qr = fill3box(qr) #clean up 3 box areas as they need to be fixed
# debug visualization
for x in range(21):
p1 = (round(x*w/21),0)
p2 = (round(x*w/21),h)
cv2.line(im_orig,p1,p2,(255),1)
for y in range(21):
p1 = (0,round(y*h/21))
p2 = (w,round(y*h/21))
cv2.line(im_orig,p1,p2,(255),1)
qr = cv2.resize(qr,(210,210),interpolation=cv2.INTER_NEAREST)
im = (im*255).astype(np.uint8)
qr= (qr*255).astype(np.uint8)
im_orig= (im_orig*255).astype(np.uint8)
cv2.imwrite('im.png',im)
cv2.imwrite('qr.png',qr)
cv2.imwrite('im_orig.png',im_orig)
在代码中裁剪图像 to_process.png
。
叠加网格以显示此方法的工作原理
阈值图像。
已重新生成二维码,请注意,即使有多个错误,它仍然有效。