二维码(QRCODE)纠错容错位读取修复操作

一次CTF比赛的杂项解题遇到了一道和二维码相关的题目,但是利用扫描工具扫描不出来结果,随后查阅了二维码的相关资料,定位到了问题出在二维码的校验码上。需要读取二维码的纠错容错位,然后比对两个纠错容错码,最后修复二维码纠错位扫码找到结果。

二维码是一个仅支持校验和纠错的编码,对于纠错功能比较直观的感受就是遮挡了一部分非关键区块之后二维码还可以扫出结果。在计算机网络课程里面多多少少都会提到校验码、纠错码的概念,简单啰嗦一下。校验码是能发现信息代码中存在错误的编码算法,最常见的是CRC算法,在文件校验、网络校验中都有应用。纠错码除了能检查到错误还可以一定程度纠正错误情况保证不出意外的编码,海明码(Hamming Code)是常见的纠错码。

二维码纠错信息存储的位置

二维码纠错信息所在的位置(以25*25大小的二维码为例,不同版本有差异),第一个纠错串信息在左上角定位符附近:

(8, 0),(8, 1),(8, 2),(8, 3),(8, 4),(8, 5),(8, 7),(8, 8),(7, 8),(5, 8),(4, 8),(3, 8),(2, 8),(1, 8),(0, 8)

第二个纠错串信息在右下角定位符附近:

(24, 8),(23, 8),(22, 8),(21, 8),(20, 8),(19, 8),(18, 8),(8, 17),(8, 18),(8, 19),(8, 20),(8, 21),(8, 22),(8, 23),(8, 24)

注意,这里两个纠错字符串的信息必须一致才能进行纠错操作。测试很多工具扫码遇到两个纠错字符串不一致时会忽略,从而识别不出二维码内容。

二维码纠错容错等级

二维码的纠错等级,容错等级。纠错等级是指容错率的大小,按照容错率从小到大可分L(<7%),M(<15%),Q(<25%),H(<30%)。容错率也叫纠错率。纠错率指的就是二维码能被正常扫描时允许被遮挡的最大面积占总面积的比率,确保二维码在被遮挡部分面积后仍能被正常扫描。

纠容错等级纠错串
L0111011111000100
L1111001011110011
L2111110110101010
L3111100010011101
L4110011000101111
L5110001100011000
L6110110001000001
L7110100101110110
M0101010000010010
M1101000100100101
M2101111001111100
M3101101101001011
M4100010111111001
M5100000011001110
M6100111110010111
M7100101010100000
Q0011010101011111
Q1011000001101000
Q2011111100110001
Q3011101000000110
Q4010010010110100
Q5010000110000011
Q6010111011011010
Q7010101111101101
H0001011010001001
H1001001110111110
H2001110011100111
H3001100111010000
H4000011101100010
H5000001001010101
H6000110100001100
H7000100000111011

解题代码

图片本身有白色外边,先进行裁边,返回图片实际像素数量和一个信息编码位的比例。

def position(stdsize=25):
    from PIL import Image
    
    qr = Image.open('key.png')
    x, y = qr.size
    start = x
    end = 0
    for i in range(x):
        for j in range(y):
            if qr.getpixel((i, j)) != 1:
                start = min(i, j, start)
                end = max(i, j, end)
    img2 = qr.crop((start + 1, start + 1, end + 1, end + 1))
    proportion = (end - start) // stdsize
    return img2, proportion

还原信息到当前二维码25*25大小的数组上,并输出当前二维码的两个纠错容错等级。

dic = {
        "L0": "111011111000100",
        "L1": "111001011110011",
        "L2": "111110110101010",
        "L3": "111100010011101",
        "L4": "110011000101111",
        "L5": "110001100011000",
        "L6": "110110001000001",
        "L7": "110100101110110",
        "M0": "101010000010010",
        "M1": "101000100100101",
        "M2": "101111001111100",
        "M3": "101101101001011",
        "M4": "100010111111001",
        "M5": "100000011001110",
        "M6": "100111110010111",
        "M7": "100101010100000",
        "Q0": "011010101011111",
        "Q1": "011000001101000",
        "Q2": "011111100110001",
        "Q3": "011101000000110",
        "Q4": "010010010110100",
        "Q5": "010000110000011",
        "Q6": "010111011011010",
        "Q7": "010101111101101",
        "H0": "001011010001001",
        "H1": "001001110111110",
        "H2": "001110011100111",
        "H3": "001100111010000",
        "H4": "000011101100010",
        "H5": "000001001010101",
        "H6": "000110100001100",
        "H7": "000100000111011"}
l1 = [
    (8, 0),
    (8, 1),
    (8, 2),
    (8, 3),
    (8, 4),
    (8, 5),
    (8, 7),
    (8, 8),
    (7, 8),
    (5, 8),
    (4, 8),
    (3, 8),
    (2, 8),
    (1, 8),
    (0, 8)]
l2 = [
    (-1, 8),
    (-2, 8),
    (-3, 8),
    (-4, 8),
    (-5, 8),
    (-6, 8),
    (-7, 8),
    (8, -8),
    (8, -7),
    (8, -6),
    (8, -5),
    (8, -4),
    (8, -3),
    (8, -2),
    (8, -1)]


def reshape(img2, sub_step):
    sub_step = step
    result = []
    result2 = []
    x, y = img2.size
    for i in range(0, x, sub_step):
        tmpl = []
        tmpl2 = []
        for j in range(0, y, sub_step):
            tmpl.append(1 - img2.getpixel((j, i)))
            tmpl2.append(img2.getpixel((j, i)))
        result.append(tmpl)
        result2.append(tmpl2)
    f1 = ''.join([str(result[i[0]][i[1]]) for i in l1])
    f2 = ''.join([str(result[i[0]][i[1]]) for i in l2])
    for k, v in dic.items():
        if v == f1:
            print(f1, k)
        if v == f2:
            print(f2, k)
    return result2

最后有两种办法,可以暴力枚举纠错容错等级或者用较大的纠错容错等级替换纠错容错位修复图片(测试用L4可以扫出来),最后调用zxing扫描输出结果。

def fix(result2):
    import numpy as np
    import matplotlib.pyplot as plt
    import zxing

    for a, b in enumerate(dic['L4']):
        result2[l1[a][0]][l1[a][1]] = 1 - int(b)
        result2[l2[a][0]][l2[a][1]] = 1 - int(b)
    gray_array = np.array(result2)
    plt.imshow(gray_array, cmap='Greys_r')  # 转灰度图
    plt.axis('off')  # 不显示坐标轴
    plt.imsave('final.png', gray_array, cmap='Greys_r')
    
    new_qr = zxing.BarCodeReader()
    pw = new_qr.decode('final.png')
    pw = pw.parsed
    print(pw)


a1, a2 = position()
a3 = liupi(a1, a2)
fix(a3)
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: C 嵌入式识别二维码 Qrcode 是一种在嵌入式系统中使用 C 语言识别二维码的技术。二维码是一种流行的图像模式,可用于在不同的应用程序和场景中传递信息。嵌入式系统通常被用于对图像的处理和分析,因此嵌入式系统中实现 Qrcode 识别对于许多应用程序至关重要。 实现 Qrcode 识别,需要使用一些开源库和工具,如 OpenCV 和 ZBar 等。 OpenCV 是一种流行的计算机视觉库,它为嵌入式系统提供丰富的图像处理和分析功能;而 ZBar 是一种针对二维码和条形码的跨平台库,可用于识别各种类型的二维码。 在使用 C 嵌入式识别二维码 Qrcode 的过程中,需要进行一些必要的基本设置,例如摄像头设置、采样率设置、图像处理和输出设置等。在处理二维码时,图像需要进行预处理,包括图像分割、增强、二值化和去噪等。此外,还需要进行二维码检测和解码,以获取二维码中包含的信息。 总的来说,C 嵌入式识别二维码 Qrcode 是一种十分重要的技术,它可以用于许多领域,例如智能物流、智能家居、智能交通和医疗等领域,能够提高系统的智能化程度,为用户带来更多的便利。 ### 回答2: 二维码是一种广泛应用于商业和生活中的图形编码技术。当我们需要获取其中的信息时,我们通常需要使用一些设备来读取其中的信息。嵌入式系统可以很好地实现二维码的识别功能。 嵌入式系统一般采用图像识别技术来实现对二维码的扫描和解析。应用程序可以通过图像采集模块来获取相机所捕捉到的图像,并进行预处理和分析,从而确定图像中是否存在二维码。如果存在二维码,系统将会进一步对图像进行解析,提取出其中的信息。最后将解析出的信息传输至外部系统。 由于二维码的图形信息较为简单,因此可以通过基于面积的方法来识别二维码。在读取二维码时,我们可以通过计算二维码内的黑色像素点占据的面积与整个二维码的面积的比例来确定是否正确读取二维码。除此之外,我们还可以采用二值化、灰度化等方法对图像进行预处理,提高识别的稳定性和准确性。 总之,嵌入式系统的二维码识别技术有着较高的实用价值,可以在自动售货机、智能门禁系统、自助购物系统等场景中广泛应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值