EDIT below image is the pre-processed sequence on original image. 1. Original Image -> 2. Blur x n times to make qrcode position significant -> 3. crop original image, position extracted from second step using blob -> 4. sharpen and threshold -> 5. check three square for qrcode -> 6. to do additional transformation like rotation -> (final image) (cropped image with resize resolution.)
Old Question I am trying to reconstruct qrcode from original image. As you can see the photo has damaged qrcode, so I use Aforge library to detect 3 square from image using blob. Now what I don't understand is the logic to generate qrcode from this information. Is it technically possible to reconstruct qrcode with given information?
This is an interesting problem. To answer your question, is this technically possible. Yes it is certainly possible. The QR code in your question encode "5176941.12".
Here's the prepossessed image so that it's easier to manually set the pixels.
After this step, I use excel to set each pixel one by one. After that simply point your phone towards the computer screen. This is what it looks like. If you want the excel sheet, you can get it here.
Now that the question of possibility is out of the way, how to automate it? Without knowing further additional samples, it is difficult to say for sure. However, just based on this sample alone, the simplest approach is simply align a 21x21 grid over your cropped QR image and fill in the values by using a threshold. And then pass this image to your QR decoder. QR code has certain level of redundancy so even if some of the pixels are missing, you will most likely be able to recover the original data.
Here's some code in python which may serve as a guide to how you might automate this. A few things to note:
Code:
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)
Cropped image to_process.png
in code.
Grid overlayed to show how this method works
Thresholded image.
Regenerated QR, note that it still works even though there are multiple errors.