首页 > 解决方案 > How to make a for loop from left to right, top to bottom in Python?

问题描述

I am trying to make a QR Code, and be able to read the data that is on the code itself. I am able to write the information, as well as see the bit values for the QR Code. When I read the QR Code through the code I have written, it gives me a completely different set of bits than what was written.

Code for reading the QR Code:

i,j=150,150
    step=37
    charRep=""
    for byte in range(150,450):
        color=int(img[i,j])
        # ~ print(color)
        if (color==int(255)):
            charRep+="0"
        elif (color==int(0)):
            charRep+="1"
        i+=step
        if i>=412:
            i=150
            j+=step
            if j>=412:
                break

    show(img)

The QR Code: enter image description here

This QR Code, with my code, says "Test", in binary notation, with the first character being the top row, the second the one below, so on.

The way I have my code for writing onto the QR Code template is I take the bits and write them, left to right, top to bottom. However, my code doesn't read back the data from the QR Code in the same way. I am wondering what to change with my code to make it work properly.

Minimal Reproducible Example Code:

import numpy as np
import cv2

def show(img,wait=0,destroy=True):
    img=np.uint8(img)
    cv2.imshow("image",img)
    cv2.waitKey(wait)
    if destroy:
        cv2.destroyAllWindows()

def straighten(img,data):
    color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

    contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # ~ print(len(contours))
    cv2.drawContours(color, contours, -1, (0,255,0), 3)
    # ~ show(color)

    targets=[]
    while len(contours):
        contour=contours.pop()
        _,x,y=stats(contour)
        friends=[]
        for index,c in enumerate(contours):
            _,i,j=stats(c)
            if np.hypot(x-i,y-j)<5:
                friends.append(index)
        for index in friends[::-1]:
            del contours[index]
        targets.append((len(friends)+1,x,y))
    targets.sort()
    targets=targets[-4:]

    points=np.float32([[500,500],[500,100],[100,100],[100,500]])
    source=np.float32([[x,y] for c,x,y in targets])
    M=cv2.getPerspectiveTransform(source,points)
    dst=cv2.warpPerspective(img, M, (600,600))
    _,img=cv2.threshold(dst,127,255,cv2.THRESH_BINARY)
    
    i,j=150,150
    step=37
    charRep=""
    for byte in range(150,450):
        color=int(img[i,j])
        # ~ print(color)
        if (color==int(255)):
            charRep+="0"
        elif (color==int(0)):
            charRep+="1"
        i+=step
        if i>=412:
            i=150
            j+=step
            if j>=412:
                break
    print(charRep)
    show(img)


def stats(contour):
    M = cv2.moments(contour)
    return M['m00'],(M['m10']/M['m00']),(M['m01']/M['m00'])
def data2bits(data):
    bits=""
    for i in range(len(data)):
        binary=str(bin(ord(data[i])))
        binary=binary.replace("0b","0")
        binary=binary.zfill(8)
        bits+=binary
        # ~ print(bits)

    bits=bits.ljust(64,'0')
    print("\nThese are the bits of the data you put in:\n"+str(bits)+"\n")
    return bits
    
def bits2pixels(bits,qrCode):
    i,j=150,150
    step=37
    for bit in bits:
        if (bit=="1"):
            dim = 37
            color=(0,0,0)
        elif (bit=="0"):
            i+=step
            if i>=412:
                i=150
                j+=step
                if j>=412:
                    break
            continue
        cv2.rectangle(qrCode,(i,j),(i+dim,j+dim),color,-1)
        i+=step
        if i>=412:
            i=150
            j+=step
            if j>=412:
                break
    show(qrCode)
    return(qrCode)

def bits2data(bits):
    string_blocks = (bits[i:i+8] for i in range(0, len(bits), 8))
    string = ''.join(chr(int(char, 2)) for char in string_blocks)
    print("This is the data you typed in, converted from the bits:\n"+str(string))
qrCode=cv2.imread("scan.png",0)
data=input("Put in the data you want and you will get the binary output for the first 8 characters.\nIf the data put in is less than 8 characters long, the bits will be filled up\nbut will be removed when the data is recompiled.\nType in your data: ")
data=data[:8]
bits=data2bits(data)
qrCode=bits2pixels(bits,qrCode)
bits2data(bits)

straighten(qrCode,data)

标签: pythonloops

解决方案


推荐阅读