Python基于二维码实现的在线编解码系统

目 录

摘 要 I
Abstract II
第一章 绪论 1
1.1 课题背景 1
1.2 研究现状 1
1.3 工作环境和背景 2
1.3.1 操作系统 3
1.3.2 编程语言 3
1.3.3编码库和解码库 3
1.3.4 网页web框架 4
1.4 主要工作和内容安排 4
第二章 QR二维码概述 6
2.1 QR二维码的结构 6
2.1.1 相关名词概念 6
2.1.2 图像结构 6
2.1.3 特点 9
2.2 QR二维码的编解码过程简介 9
2.2.1 编码过程 9
2.2.2 解码过程 10
第三章 程序设计 12
3.1 前端程序 12
3.2 后端程序 16
3.3 程序运行流程 21
3.3.1 单次录入 21
3.3.2 批量生成 22
3.3.3 解码 23
第四章 结果与分析 25
4.1 可用性验证 25
4.2 测试过程与结果 25
4.3 分析 26
第五章 总结与展望 27
5.1 总结 27
5.2 展望 27
参考文献 28
致谢 30
1.3.2 编程语言
网页采用Html(HyperText Markup Language)语言编写,版本Html 5。
由于整个运维部门的运维脚本正在准备使用Python语言进行改写,以后的主用脚本也将是Python。Python是一种面向对象的脚本语言,1991年由荷兰人Guido van Rossum首次公开发行。Python具有简洁的语法规则,易读易改,扩展性很好。并且我之前也学习过一些Python语言,对Python有一些基础,因此,综合考虑,决定选用Python语言来编写程序。在本课题中,使用的Python版本为2.7.6,Ubuntu Kylin14.04 64位操作系统自带,无需额外安装。

1.3.3编码库和解码库
本课题由于侧重于应用层次,因此决定选择已有的QR二维码的编码库和解码库。Python语言具有非常良好的扩展性,有非常丰富的库可以利用。在Python的官方包管理网站,https://pypi.python.org/pypi上可以找到各种各样的库。经过查找和了解,确定使用qrcode和zbar两个Python库完成QR二维码的编码和解码工作。课题中使用到的Qrcode版本为4.0.4,zbar版本为0.10 。由于系统默认不带有这两个库,因此需要自行安装。
库模块的安装步骤为:
1.先安装Python的包管理程序pip。在终端命令行下键入命令进行安装:
$ sudo apt-get install python-pip
2.通过pip安装qrcode和zbar:
$ sudo pip install qrcode zbar
安装好包之后,在python程序中使用时只需import qrcode zbar即可。

1.3.4 网页web框架
课题使用网页形式来表现程序的功能,那么HTTP服务器是不可少的。由于本课题规模较小,处于开发阶段,离真正放到服务器上运行还有一段距离,因此决定选用Web框架自带的开发服务器运行和调试,就不再安装Apache、Nginx等专业的HTTP服务器了。
在Web框架的选择上,我选用了web.py框架。Web.py是一个基于Python语言的轻量级框架,相比于其他框架具有简单易用,扩展简单的优点。课题中使用的web.py版本为0.37。由于该框架系统默认不安装,本文转载自http://www.biyezuopin.vip/onews.asp?id=14562因此需要另外安装。安装过程类似于qrcode和zbar,在命令行键入命令:
$ sudo pip install web.py
即可成功安装web.py模块,当需要在程序中使用时,只需import web即可使用web.py模块的相关功能。
1.4 主要工作和内容安排
本文的主要内容包括:

  1. QR二维码的由来和优点
    介绍QR二维码的由来,发展过程以及相比于其他二维码的优点等。
  2. QR二维码的结构
    介绍QR二维码的图形构成,包含的内容,特性和规范标准。
  3. 建立网页
    以网页的形式提供将资产信息生成QR二维码的功能,用户在网页上提交资产信息并提交,网页将信息交给后台程序处理并返回结果。
  4. Python后台程序
    用户通过网页提交的信息从前端传递给后台处理程序,后台程序根据资产信息生成对应的二维码并保存到指定位置。
    本文的内容安排:
    第二章主要简介QR二维码的特点和格式规范等内容。
    第三章主要进程程序设计,包括前端网页和后台程序的功能,以及整个程序的运行流程。
    第四章主要是对整个程序的分析,展示程序的运行结果,对过程中出现的错误进行分析和总结。
    第五章是总结与展望,主要对全文所做的工作进行了总结。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cStringIO
import urllib
import web
import qrcode
import zbar
try:
    from PIL import Image
except ImportError:
    import Image
from lib.mime import ImageMIME
from lib import charset


class Index(object):
    """首页
    """
    def GET(self):
        msg = "解码后的信息将显示在这里。"
        return render.index(msg)

class QR(object):
    """处理传来的数据并显示 QR Code 二维码图片
    """
    def handle_parameter(self, chl, chld, chs):
        """处理表单提交的变量
            chl=编码内容
            chs=图片尺寸
            chld=纠错级别
        """
        if len(chl) > 2953:  # V40-L最大容量
            raise web.badrequest()
        chld = chld.upper()
        # chld 是非必需参数,有默认值
        if not chld:
            chld = 'M|1'
        # 处理 chld 参数值
        chld = chld.split('|')
        if len(chld) == 2:  # e.g. 'M|2'
            try:
                border = int(chld[1])  # 二维码与图片的边距
            except:
                border = 1
        elif len(chld) == 1:  # e.g. 'M'
            border = 1
        level = chld[0]  # 纠错级别
        if level not in ['L', 'M', 'Q', 'H']:
            level = 'M'  # 默认纠错级别
        if border < 0:
            border = 1
        try:
            chs = chs.lower()
            size = tuple([int(i) for i in chs.split('x')])
        except:
            raise web.badrequest()
        else:
            # 处理负数及零的情况,
            # 同时限制图片大小,防止图片太大导致系统死机
            if (size[0] * size[1] == 0 or size[0] < 0 or size[1] < 0 or (
                    size[0] > 600) or size[1] > 600):
                raise web.badrequest()
        # 由于生成的二维码图片是个正方形,所以由 size 的最小值组成的正方形
        # 来限制二维码图片大小
        square_size = size[0] if size[0] <= size[1] else size[1]
        # L,M,Q,H 纠错级别下 1~40 版本的最大容量(Binary)
        l_max = [17, 32, 53, 78, 106, 134, 154, 192, 230, 271, 321,
                 367, 425, 458, 520, 586, 644, 718, 792, 858, 929,
                 1003, 1091, 1171, 1273, 1367, 1465, 1528, 1628,
                 1732, 1840, 1952, 2068, 2188, 2303, 2431, 2563,
                 2699, 2809, 2953]
        m_max = [14, 26, 42, 62, 84, 106, 122, 152, 180, 213, 251,
                 287, 331, 362, 412, 450, 504, 560, 624, 666, 711,
                 779, 857, 911, 997, 1059, 1125, 1190, 1264, 1370,
                 1452, 1538, 1628, 1722, 1809, 1911, 1989, 2099,
                 2213, 2331]
        q_max = [11, 20, 32, 46, 60, 74, 86, 108, 130, 151, 177,
                 203, 241, 258, 292, 322, 364, 394, 442, 482, 509,
                 565, 611, 661, 715, 751, 805, 868, 908, 982, 1030,
                 1112, 1168, 1228, 1283, 1351, 1423, 1499, 1579, 1663]
        h_max = [7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137, 155,
                 177, 194, 220, 250, 280, 310, 338, 382, 403, 439,
                 461, 511, 535, 593, 625, 658, 698, 742, 790, 842,
                 898, 958, 983, 1051, 1093, 1139, 1219, 1273]

        # 根据纠错级别及字符数选定版本。
        if level == 'L':
            for i in l_max:
                if len(chl) < i:
                    version = l_max.index(i) + 1
                    break
            else:  # 如果超出了该纠错级别所能处理的最大字符数,抛出错误异常
                raise web.badrequest()
            error_correction = qrcode.constants.ERROR_CORRECT_L
        elif level == 'M':
            for i in m_max:
                if len(chl) < i:
                    version = m_max.index(i) + 1
                    break
            else:
                raise web.badrequest()
            error_correction = qrcode.constants.ERROR_CORRECT_M
        elif level == 'Q':
            for i in q_max:
                if len(chl) < i:
                    version = q_max.index(i) + 1
                    break
            else:
                raise web.badrequest()
            error_correction = qrcode.constants.ERROR_CORRECT_Q
        elif level == 'H':
            for i in h_max:
                if len(chl) < i:
                    version = h_max.index(i) + 1
                    break
            else:
                raise web.badrequest()
            error_correction = qrcode.constants.ERROR_CORRECT_H

        box_size = square_size / ((version * 4 + 17) + border * 2)
        # print box_size
        args = {'version': version,
                'error_correction': error_correction,
                'box_size': box_size,
                'border': border,
                'content': chl,
                'size': size
                }
        return args

    def show_image(self, **args):
        """返回图片 MIME 及 内容,用于显示图片
        """
        version = args['version']
        error_correction = args['error_correction']
        box_size = args['box_size']
        border = args['border']
        content = args['content']
        size = args['size']

        if box_size == 0:
            im = Image.new("1", (1, 1), "white")  # 空白图片
        else:
            # 生成二维码
            qr = qrcode.QRCode(
                version=version,
                error_correction=error_correction,
                box_size=box_size,
                border=border,
            )
            print "qr.add_data(content) ,content is :"
            print content
            qr.add_data(content)
            qr.make(fit=True)
            im = qr.make_image()

        # 将生成的二维码图片保存到内存中,用于下面的缩放处理
        temp_img = cStringIO.StringIO()
        im.save(temp_img, 'png')
        img_data = temp_img.getvalue()  # 获取图片内容
        im = Image.open(cStringIO.StringIO(img_data))
        x, y = im.size  # 生成的二维码图片大小
        rx, ry = size  # 用户请求的图片大小

        new_im = Image.new("1", (rx, ry), "white")
        # 将二维码图片粘贴到空白图片中并保持二维码图片居中
        paste_size = ((rx - x) / 2, (ry - y) / 2, (rx - x) / 2 + x,
                      (ry - y) / 2 + y)  # 粘贴位置
        new_im.paste(im, paste_size)  # 若位置全为负值则缩放并填充整个目标图片

        temp_img.write('')
        new_im.save(temp_img, 'png')  # 保存粘贴好的图片
        new_im_data = temp_img.getvalue()
        # 图片 MIME 类型
        MIME = ImageMIME().get_image_type(new_im_data)
        temp_img.close()  # 释放内存
        return (MIME, new_im_data)

    def GET(self):
        querys = web.ctx.env['QUERY_STRING']
        if querys == '':
            ''' querys like this : chl=aaa&chs=350x350&chld=M 
                type is str
            '''
            return web.badrequest()
        querys = querys.split('&')
        ''' querys turn to : ['chl=aaa','chs=350x350','chld=M'] 
            type is list
        '''
        print "querys is:"
        print querys
        try:
            # 分割参数,能处理类似 'chl===hello&chls=200x200&chld=M|3'
            values = [x.split('=', 1) for x in querys]
            '''values like this : [['chl', 'aaa'], ['chs', '350x350'], ['chld', 'M']] 
                可以处理由于多个=号引起的解析错误,如: chl===wo
            '''
            print "values is:"
            print values
            querys = {}
            chl = ''
            temp_list = []
            for n in range(len(values)):
                temp_list.append(values[n][1])
            chl = ':'.join(temp_list)
            print "chl is :"
            print chl
        except:
            return web.badrequest()

        #chl = querys.get('chl')
        chl = chl.replace('+', '%20') # 解决空格变加号,替换空格为 '%20'
        chs = '350x350'
        chld = 'M|1'
        print "chl type is :"
        print type(chl)
        chl = urllib.unquote(chl)
        print "urllib.unquote(chl) is:"
        print chl
        chl = charset.encode(chl)  # 将字符串解码然后按 utf8 编码
        print "charset.encode(chl)"
        print chl
        if chl is None:
            return web.badrequest()
        args = self.handle_parameter(chl, chld, chs)
        print "args is :"
        print args
        MIME, data = self.show_image(**args)
        web.header('Content-Type', MIME)
        # save img file {
        tagfile = open('tags/' + chl.split(':')[0] + '.png', 'wb')
        tagfile.write(data)
        tagfile.close
        print "save data success!"
        print "data type is:" ,
        print type(data)
        # }
        return data

    def POST(self):
        """处理 POST 数据
        """
        querys = web.input()
        print "querys.chl="
        print querys.chl
        print "querys.chl type is :"
        print type(querys.chl)
        print "querys.chs ="
        print querys.chs
        chl = querys.chl
        chl_list = chl.split('\n')
        print "chl_list is :"
        print chl_list
        chs = querys.chs
        for chl in chl_list:
            if not chl:
                pass
            else:
                if chl is None or chs is None:
                    return web.badrequest()
                chld = querys.chld
                chl = chl.replace('\t',':')
                print "chl = chl.replace('\t',':')"
                print chl
                args = self.handle_parameter(chl, chld, chs)
                MIME, data = self.show_image(**args)
                web.header('Content-Type', MIME)
                # save img file {
                tagfile = open('tags/' + chl.split(':')[0] + '.png', 'wb')
                tagfile.write(data)
                tagfile.close
                print "save data success!"
                print "data type is:" ,
                print type(data)
                # }
        return data

class Decode(object):
    """解码
    """
    def decodeQR(self, fileName):
        '''解析QR码'''
        scanner = zbar.ImageScanner()
        scanner.parse_config("enable")
        pil = Image.open(fileName).convert('L')
        width, height = pil.size
        raw = pil.tostring()
        image = zbar.Image(width, height, 'Y800', raw)
        scanner.scan(image)
        data = ''
        for symbol in image:
            data+=symbol.data
        del(image)
        print "decodeQR data is:"
        print data
        return data

    def POST(self):
        img = web.input(qrimg={})
        print type(img)
        # save img file {
        save_path = './uploads'
        fname=img['qrimg'].filename
        img_save = open(save_path + '/' + fname, 'wb')
        img_save.write(img.qrimg.file.read())
        img_save.close()
        # }
        img_read = save_path + '/' + fname
        msg = self.decodeQR(img_read)
        try:   
            msg = msg.decode('utf-8').encode('sjis').decode('utf-8')
        except UnicodeEncodeError:   
            pass

        print "The info in QR is :"
        print msg
        return render.index(msg)

if __name__ == '__main__':
    web.config.debug = True
    urls = (
        '/', 'Index', 
        '/qr', 'QR',  
        '/decode', 'Decode', 
        '/.*', 'Index'
    )
    # 应用模板
    render = web.template.render('templates')
    app = web.application(urls, globals())
    app.run()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基于Python二维码识别系统是一种使用Python编程语言开发的应用程序,用于识别和解码二维码图像。这个系统结合了图像处理和计算机视觉技术,能够在图片中快速准确地识别并解码二维码。 这个系统的主要流程如下:首先,使用Python的图像处理库,如OpenCV或PIL,对输入的图片进行预处理。预处理的目的是增强二维码图像的对比度、降噪、去除背景等,以提高二维码的识别率。接下来,使用Python的图像识别技术,如特征提取和模式匹配,对预处理后的图像进行分析和处理,以提取二维码的特征信息。然后,使用Python二维码解码库,如ZBar或PyQRCode,对提取到的特征信息进行解码,得到二维码的内容。最后,将解码结果返回给用户或进一步处理。 基于Python二维码识别系统具有以下优点:首先,Python是一种简单易学的编程语言,具有丰富的图像处理和计算机视觉库,使得开发二维码识别系统变得简单快捷。其次,Python具有良好的可移植性和跨平台性,可以在多种操作系统上运行,如Windows、Linux和Mac OS。此外,Python还具有强大的社区支持,有许多开源的二维码识别库可供选择,开发人员可以根据需要灵活使用。 总之,基于Python二维码识别系统是一种便捷、高效的应用程序,可以广泛应用于二维码相关领域,如商品追溯、支付扫码、活动签到等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shejizuopin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值