精华内容
下载资源
问答
  • 前言 在使用canvas绘制海报的...配置很简单,也容易上手,无论是矩形,还是将图片合成canvas;还是自己定义文字;都是很方便的。 附上一个简单的例子吧 // const _this=this; wx.getSystemInfo({ success (r
  • [273]python生成个性二维码

    千次阅读 多人点赞 2018-07-08 14:07:52
    现在,我们生活中到处可以看到二维码。它有啥好处呢?它具有信息容量大、可靠性高、可表示汉字及图象多种文字...python 有qrcode库,很容易就生成二维码。现在在需要使用Python图像库的时候一般是用 Pillow 模块代替...

    更多精选文章,请关注公众号:python前行者
    python前行者

    现在,我们生活中到处可以看到二维码。它有啥好处呢?它具有信息容量大、可靠性高、可表示汉字及图象多种文字信息、保密防伪性强等优点。

    我们生成的东西一般都在电脑上。如果弄到移动设备上,用到最多的是扫码。在移动设备浏览器中输入URL明显没有扫描二维码方便。

    就是这个:

    image.png

    python 有qrcode库,很容易就生成二维码。现在在需要使用Python图像库的时候一般是用 Pillow 模块代替PIL。安装非常简单:

    pip install pillow
    

    安装 qrcode 也是类似:

    pip install qrcode
    

    在Python中也可以用如下的方式快速生成:

    import qrcode
    
    # 方法1
    def qr_code_1():
        #调用qrcode的make()方法传入url或者想要展示的内容
        img = qrcode.make('https://blog.csdn.net/xc_zhou')
        #保存
        img.save("./img/text1.png")
        # 或者
        with open('./img/test2.png', 'wb') as f:
            img.save(f)
            
    qr_code_1()
    

    更高级一些的设置需要在Python中引入QRCode类:

    • 示例代码1:
    import qrcode
    
    # 方法2
    def qr_code_2():
        '''
        参数 version 表示生成二维码的尺寸大小,取值范围是 1 至 40,最小尺寸 1 会生成 21 * 21 的二维码矩阵,
        version 每增加 1,生成的二维码就会添加 4 个单位大小,例如 version 是 2,则生成 25 * 25 尺寸大小的二维码。
    
        参数 error_correction 指定二维码的容错系数,分别有以下4个系数:
        ERROR_CORRECT_L: 7%的字码可被容错
        ERROR_CORRECT_M: 15%的字码可被容错
        ERROR_CORRECT_Q: 25%的字码可被容错
        ERROR_CORRECT_H: 30%的字码可被容错
    
        参数 box_size 表示二维码里每个格子的像素大小。
        参数 border 表示边框的格子宽度是多少(默认是4)
        '''
        # 实例化QRCode生成qr对象
        qr = qrcode.QRCode(
            version=2,
            error_correction=qrcode.constants.ERROR_CORRECT_H,
            box_size=10,
            border=1
        )
        # 调用qrcode的make()方法传入url或者想要展示的内容
        qr.add_data("python前行者公众号")
        qr.make(fit=True)# 填充数据
        img = qr.make_image() # 生成图片
        img.save("./img/test3.png")
    
    qr_code_2()
    

    生成的结果为:


    微信扫描的结果是:

    参数 version 表示生成二维码的尺寸大小,取值范围是 1 至 40,最小尺寸 1 会生成 21 * 21 的二维码矩阵,version 每增加 1,生成的二维码就会添加 4 个单位大小,例如 version 是 2,则生成 25 * 25 尺寸大小的二维码。

    参数 error_correction 指定二维码的容错系数,分别有以下4个系数:
    ERROR_CORRECT_L: 7%的字码可被容错
    ERROR_CORRECT_M: 15%的字码可被容错
    ERROR_CORRECT_Q: 25%的字码可被容错
    ERROR_CORRECT_H: 30%的字码可被容错

    参数 box_size 表示二维码里每个格子的像素大小。
    参数 border 表示边框的格子宽度是多少(默认是4)。

    示例代码2(生成带有图标的二维码):

    # -*- coding:utf-8 -*-
    import qrcode,time
    from PIL import Image
    import matplotlib.pyplot as plt
    
    
    # 方法3  生成带有图标的二维码
    def qr_code_3():
        # 实例化QRCode生成qr对象
        qr = qrcode.QRCode(
            version=2,
            error_correction=qrcode.constants.ERROR_CORRECT_H,
            box_size=10,
            border=1
        )
        qr.add_data("https://blog.csdn.net/xc_zhou")# 添加数据
        qr.make(fit=True)# 填充数据
        # 生成图片
        # img = qr.make_image()
        img = qr.make_image(fill_color="green", back_color="white")
        img = img.convert("RGBA")
        # 添加logo,打开logo照片
        icon = Image.open("我的头像.jpg").convert("RGBA")
        # 获取图片的宽和搞
        img_w, img_h = img.size
        # 参数设置logo的大小
        factor = 3
        size_w = int(img_w / factor)
        size_h = int(img_h / factor)
        icon_w, icon_h = icon.size
        if icon_w > size_w:
            icon_w = size_w
        if icon_h > size_h:
            icon_h = size_h
        # 重新设置logo的尺寸
        icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS)
        # 得到画图的x,y坐标,居中显示
        w = int((img_w - icon_w) / 2)
        h = int((img_h - icon_h) / 2)
        '''
        img.paste(path,where,mask=None)
        其中,img为image对象;path为所添加图片;where为tuple,如:(x,y),表示图片所在二维码的横纵坐标
        '''
        # 黏贴logo照
        img.paste(icon, (w, h), icon)
        img.save("我的CSDN二维码.png")
        # img.show()# 自动打开图片
        # 终端显示图片
        plt.imshow(img)
        plt.show()
    
    if __name__=='__main__':
        qr_code_3()
    

    如此,就将以下图片
    在这里插入图片描述

    生成二维码:

    在这里插入图片描述
    如果是下载URL,扫描后就可以直接下载了。
    放到jenkins上,每次生成的build,直接扫码就可以下载到手机上了。

    code

    # -*- coding:utf-8 -*-
    import qrcode,time
    from PIL import Image
    import matplotlib.pyplot as plt
    
    
    # 方法1
    def qr_code_1():
        #调用qrcode的make()方法传入url或者想要展示的内容
        img = qrcode.make('https://blog.csdn.net/xc_zhou')
        #保存
        img.save("./img/text1.png")
        # 或者
        with open('./img/test2.png', 'wb') as f:
            img.save(f)
    
    # 方法2
    def qr_code_2():
        '''
        参数 version 表示生成二维码的尺寸大小,取值范围是 1 至 40,最小尺寸 1 会生成 21 * 21 的二维码矩阵,
        version 每增加 1,生成的二维码就会添加 4 个单位大小,例如 version 是 2,则生成 25 * 25 尺寸大小的二维码。
    
        参数 error_correction 指定二维码的容错系数,分别有以下4个系数:
        ERROR_CORRECT_L: 7%的字码可被容错
        ERROR_CORRECT_M: 15%的字码可被容错
        ERROR_CORRECT_Q: 25%的字码可被容错
        ERROR_CORRECT_H: 30%的字码可被容错
    
        参数 box_size 表示二维码里每个格子的像素大小。
        参数 border 表示边框的格子宽度是多少(默认是4)
        '''
        # 实例化QRCode生成qr对象
        qr = qrcode.QRCode(
            version=2,
            error_correction=qrcode.constants.ERROR_CORRECT_H,
            box_size=10,
            border=1
        )
        # 调用qrcode的make()方法传入url或者想要展示的内容
        qr.add_data("python前行者公众号")
        qr.make(fit=True)# 填充数据
        img = qr.make_image() # 生成图片
        img.save("./img/test3.png")
    
    # 方法3  生成带有图标的二维码
    def qr_code_3():
        # 实例化QRCode生成qr对象
        qr = qrcode.QRCode(
            version=2,
            error_correction=qrcode.constants.ERROR_CORRECT_H,
            box_size=10,
            border=1
        )
        qr.add_data("https://blog.csdn.net/xc_zhou")# 添加数据
        qr.make(fit=True)# 填充数据
        # 生成图片
        # img = qr.make_image()
        img = qr.make_image(fill_color="green", back_color="white")
        img = img.convert("RGBA")
        # 添加logo,打开logo照片
        icon = Image.open("我的头像.jpg").convert("RGBA")
        # 获取图片的宽和搞
        img_w, img_h = img.size
        # 参数设置logo的大小
        factor = 3
        size_w = int(img_w / factor)
        size_h = int(img_h / factor)
        icon_w, icon_h = icon.size
        if icon_w > size_w:
            icon_w = size_w
        if icon_h > size_h:
            icon_h = size_h
        # 重新设置logo的尺寸
        icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS)
        # 得到画图的x,y坐标,居中显示
        w = int((img_w - icon_w) / 2)
        h = int((img_h - icon_h) / 2)
        '''
        img.paste(path,where,mask=None)
        其中,img为image对象;path为所添加图片;where为tuple,如:(x,y),表示图片所在二维码的横纵坐标
        '''
        # 黏贴logo照
        img.paste(icon, (w, h), icon)
        img.save("我的CSDN二维码.png")
        # img.show()# 自动打开图片
        # 终端显示图片
        plt.imshow(img)
        plt.show()
    
    
    if __name__=='__main__':
        qr_code_2()
    

    python生成动态个性二维码

    pip install myqr
    

    1、生成普通二维码

    安装了 myqr 之后,就可以在命令行中使用它了。假如我想要将 http://www.rablive.cn 字符串生成一个二维码,则只需要将在命令行中输入以下命令即可:

    myqr http://www.rablive.cn
    

    运行后,myqr 会将生成的二维码保存在当前路径下,名称为 qrcode.png

    2、带图片的二维码

    如果想要生成艺术二维码,则可以使用 -p 参数指定图片,将二维码与该图片结合在一起

    myqr http://www.rablive.cn -p rablive.png
    

    默认生成的结果是黑白的,如果想要生成彩色的,可以加上参数 -c。

    myqr http://www.rablive.cn -p rablive.png -c -n rablive_qrcode_c.png
    

    3、动态GIF二维码

    如果想要生成动态GIF二维码,方式与上面的带图片的二维码的生成方式没有区别,只是将原始的 png/.jpg 图片换成 gif 即可。

    参考:https://www.jianshu.com/p/30b6ec813b4f
    https://www.jianshu.com/p/c0073c6aa544

    展开全文
  • 原文:关于二维码分块上色(彩色二维码)的算法研究 众所周知,二维码通常是黑白的,而且是由若干个长方形或正方形小块平铺而成。但从人们的审美角度来看,常见的黑白二维码不免让人审美疲劳。本文试着...
    原文: 关于二维码分块上色(彩色二维码)的算法研究

    众所周知,二维码通常是黑白的,而且是由若干个长方形或正方形小块平铺而成。但从人们的审美角度来看,常见的黑白二维码不免让人审美疲劳。本文试着从分块上色的角度对二维码进行美化,并尝试讲一下“美化”的编程思路。

    一、缘由及目的:

    首先,我们来看看正常情况下的黑白二维码,如图1:

    图1  普通二维码(黑白条块)

    上色的难点在于如何上色,上什么色,也就是哪些块“着”什么颜色。(关于彩色二维码的效果,请参考我的另一篇文章:《C#彩色艺术化二维码样式设计(仅说思路)http://blog.csdn.net/johnsuna/article/details/7933619

    如果上错了色,也会成为“大花脸”,变得并不艺术。就好像漂亮的农村姑娘,如果穿上大花衣裳,看上去鲜艳,但仍然显示不出其天生的丽质,反而显得“很土”。如下图2及图3:

     

    图2   大花脸式的彩色二维码

    图3  单块随机色(彩色)二维码

    而上色的难点在于分块,也就是将二维码分成多少块、如何分块,相关色块上什么颜色,后一个问题是美术工程师考虑的,不在本文讨论范围之内。从图1,图2来看,分块的归类并不容易或者说我们从外观上还不好判断哪些块分在一起成为一个大色块。

    经过上面图3、下面图4的圆角化处理后,色块的划分是显而易见的。具体如何圆角化处理,请见我的另一篇文章《C#彩色艺术化二维码样式设计(仅说思路)》http://blog.csdn.net/johnsuna/article/details/7933619 及http://blog.csdn.net/johnsuna/article/details/7948907

    图4  圆角化艺术二维码(黑白色)

    为了阐述方便,我将图1的关键块进行了编号,如下图5所示:

    图5   对图1黑白二维码相关关键色块进行编号

    与图5相对应,图6为圆角化分块后的带编号的图片:

    图6   对图2的关键块进行编号

    下图7为们我要的最终效果:

    图7  最终需要的效果示意

    尽管我的上色功夫(美感)不怎么样,但总体效果比图1-图4的效果确实好多了。

    二、算法研究:

    如下图8所示,为了方便讲述,我将图7中色块7、8、9、10、11中的每个单元格又按a,b,c……进行了编号并给每个单元格加了一个黑边框。

    图8  单元格

    图8中,单元格7a和7b最终组成一个竖条色块,单元格8为一个独立的色块,9a与9b组成一个横条色块,而10a,10b...f 又组成一个L形的色块。如图7所示,12-18等由多个单元格彼此相连而组成一个大的色块,其中,编号为16的色块面积最大。

    接下来,重点研究算法。

    首先必须找到分块的“点”,观察图7和图8,我们经过对比可以发现,分隔各块之间的交接点有一个共同的规律:交接点外围相邻对角均为空

    具体地说,就是:以“交接点”为中心的3*3个单元格区域(含交接点本身)内,如果该交接点的外围8个点中,有两个斜角(不管是呈现“/”或“\”,也不管是哪一个角位,如左上或右下,或左下或右上)的点均为空白,那么,此点必为分块关键点,也就是“交接点”。

    经过观察和研究,还有一种办法,那就是“广度优先遍历”。如下图:

    图9  单点水平/垂直延伸法示意

    此算法也是棋牌或连连看等游戏常用的算法了。网上有很多类似的例子,就不再详解。另外,此算法可以与分形递归算法相结合,实现快速有效地对整个图像的分块上色。

    展开全文
  • 美化二维码

    千次阅读 2020-05-02 16:50:50
    二维码内容长度不作控制 大多数互联网技术使用到二维码生成,都是使用开源的包生成,输入字符信息,即可生成一张包含此字符信息的黑白二维码图片: 上面有两个二维码图片,扫码结果都是访问到同个页面,...
    • 二维码内容长度不作控制

          大多数互联网技术使用到二维码生成,都是使用开源的包生成,输入字符信息,即可生成一张包含此字符信息的黑白二维码图片:

     

          上面有两个二维码图片,扫码结果都是访问到同个页面,但是大多数使用二维码的地方,都是生成第一种样式,WC里的广告就是直接的例子:

     

          很明显,第一种二维码点阵非常复杂,在某种复杂的环境下,如扫码角度大、屏幕光线反光、光线明暗对比变化大、打印粘贴出去后污点影响,这时候扫码的图像识别会变得很困难,甚至根本扫不出来,直接原因是点阵太密,摄像头对点阵的误判超过码本身的容错率。

     

          第二种二维码点阵则相对简单很多,在同样环境复杂条件下,扫码几乎都没有难度,同样优等环境下,扫码读取的速度也会 快很多。

     

           这两种码本质上有什么区别呢?如果使用扫码解析出内容,你会发现内容不一样,扫出来结果分别是:

    https://work.alibaba-inc.com/work/search?type=person&tabIndex=1&offset=0&isSingleTabSearch=1&filterParameters=%7B%22fieldindexes%22%3A%7B%22province%22%3A%22%E6%B5%99%E6%B1%9F%E7%9C%81%22%2C%22city%22%3A%22%E8%A1%A2%E5%B7%9E%E5%B8%82%22%7D%7D

     

    http://ma.taobao.com/ZSk4YV

     

     

     

           现在可以很清楚看到,第二个码是使用了短地址跳转,短地址的URL字符长度特别短,使得码的占阵变得很简单,究其原因,要了解下二维码的版本,最早的版本1只有17x17的黑白点阵,到现在最大的版本40有177x177点阵,每种版本的信息容量有限,版本越高容量越大。二维码编码过程中先是对数据进行编码,然后对照数据需要的容量来选择版本,字符长度越短,当然需要版本就越低。

     

          另外,参照《QR Code Specification》里数据编码章节,你会发现数字编码(Numeric mode )和大写字母编码(Alphanumeric mode)所占的比特位特别少,在某些条件允许的情况下,可以尽量使用数字或大写字母来作来码信息内容载体,这样的二维码生成会更加简单一些。

     

     

    • 二维码大小随意设置

          由于交互设计师的需要,经常听到运营、交互设计同学让开发在产品中生成的二维码尺寸固定为多少长宽,比如171x171相素(不带边框)的二维码,这个需求是否能实现呢?事实上,如果按照标准二维码规范,这样大小的二维码无法生成,即使不按标准尺寸生产出来码能被扫码识别,也是不推荐的(只是利用了扫码的一些容错能力达到扫码结果,但是会影响扫码响应、容错等,我们希望是越优越好),具体原因如下:

           二维码最早版本是17x17大小点阵,后面每增加一版本,点阵都是以4点阵增加,某一版本的点阵计算公式是:(V-1)*4 + 21(V是版本号),按照上面170x170大小计算:

    版本3 29点阵x5放大= 145相素

    版本3 29点阵x6放大= 174相素

    版本4 33点阵x5放大= 165相素

    版本4 33点阵x6放大= 198相素

    ...

     

           你会发现,怎么也算不出有171相素大小的二维码,除非你加上边框拼凑。

    • 二维码logo随添加

          你会很多品牌、产品为了推广自己,往往会在二维码中间或边角加上logo:

     

     

          当然,为了突出logo,你可能会这样加:

     

          这时你会发现,二维码扫不出来了。二维码规范里根本没有logo这个概念,加logo是利用二维码容错率这个功能,生成二维码时,可以设置二维码的容错率(某些地方也叫容错级别),即对二维码点阵破坏纠错能力,分为:L、M、Q、H级别,级别越高,容错能力越大,当然点阵也会更加复杂,而加logo,对二维码来说,其实是对数据的一种污染,当染污破坏数据数超过当前设置的容错级别时,数据就不能再被纠错读取出来了。

     

          在设计视觉效果前提下,建议logo越小越好,这样对点阵数据破坏小,能更好的被读取。如果对二维码解码了解的话,你可以兼顾效果和纠错,设计出如下的二维码视觉(图像和点阵复用):

     

    • 二维码不设置边框

    二维码扫码器读取二维码有一步是读取定位符(即三个角上的矩形),定位符的识别,是按照黑白点阵比例(1:1:3:1:1)来确定定位符:

          要确定此比例,得先找到比例起止点(即上图中的A和B),标准黑白二维码就是二维码最边上的黑白交界处,实际二维码可能不是纯黑白,但是灰阶处理后还是按黑白来判断,假如你生成的二维码没有边框,贴在浅色背景上,扫码没问题,背景本身是浅色,灰阶等处理后,还是一样找到边界,假如背景是深色的,扫码识别就很难定位到边界了:

     

     

    对扫码器来说,图像处理二值化后,背景颜色会被认为黑色,二维码定位符起点也是黑色,没有边界了,就无支法确定定位符位置。

    目前主流的一些APP扫码器,如手淘、微信,都修复增加了这种情况的容错能力,能够用其他图像定位算法识别二维码,虽然速度可能会有影响(影响下一般感觉不出来),但是不排除有些旧的扫码SDK无法读取,或读取速度影响很大。

           建议如果把二维码加入到深色背景上时,请加上浅色的边框,边框大小大于等于单位点阵大小为佳。

     

     

    样式改进

    • 尺寸更改

          按照二维码规范,最小版本是17x17的点阵,最大是177x177点阵,常用的版本3和版本4大小也就分别是29和33个单位点阵,如果直接转成位图相素点的话,这么小是很难用扫码器扫出来的,存储或网络传输时可以考虑直接点阵存储,显示或打印出来,一般要按照固定比例放大,单个点单位长宽高等比放大即可。

    • 矢量图

         一般图形设计时会会用到矢量图,如果是正方形的单位点,一般来说位图直接放大图像也不会有什么失真,因为单位点都是黑白点,很多处理软件放大时进行插值算法(插入位图相素点),这种矩形失真很少。

         规范图形处理还是要使用到矢量图,一般黑白二维码矢量生成都采用直接EPS文件结构生成代码:

        /**
         * Constructs an empty EpsDevice that writes directly to a file. Bounds must
         * be set before use.
         */

        EpsDocument(String title, OutputStream outputStream, int minX, int minY, int maxX, int maxY) throws IOException {
           
    this.title = title;
           
    this.minX = minX;
           
    this.minY = minY;
           
    this.maxX = maxX;
           
    this.maxY = maxY;
            bufferedWriter =
    new BufferedWriter(new OutputStreamWriter(outputStream));
           
    this.stream = outputStream;
           
    write(bufferedWriter);
        }
       
    /**
         * Outputs the contents of the EPS document to the specified Writer,
         * complete with headers and bounding box.
         */

        public synchronized void write(Writer writer) throws IOException {
           
    float offsetX = -minX;
           
    float offsetY = -minY;
            writer.
    write("%!PS-Adobe-3.0 EPSF-3.0\n");
            writer.
    write("%%Creator: EpsGraphics " + EpsGraphics.VERSION
                    +
    " by M.Taobao.Com, http://www.taobao.com/\n");
            writer.
    write("%%Title: " + title + "\n");
            writer.
    write("%%CreationDate: " + new Date() + "\n");
            writer.
    write("%%BoundingBox: 0 0 " + ((int) Math.ceil(maxX + offsetX)) + " "
                    + ((int) Math.ceil(maxY + offsetY)) + "\n");
            writer.
    write("%%DocumentData: Clean7Bit\n");
            writer.
    write("%%LanguageLevel: 2\n");
            writer.
    write("%%DocumentProcessColors: Black\n");
            writer.
    write("%%ColorUsage: Color\n");
            writer.
    write("%%Origin: 0 0\n");
            writer.
    write("%%Pages: 1\n");
            writer.
    write("%%Page: 1 1\n");
            writer.
    write("%%EndComments\n\n");
            writer.
    write("gsave\n");
            writer.
    write(offsetX + " " + (maxY + offsetY) + " translate\n");
            writer.flush();

    writer.write("grestore\n");
           
    if (isClipSet()) {
                writer.
    write("grestore\n");
            }
            writer.
    write("showpage\n");
            writer.
    write("\n");
            writer.
    write("%%EOF");
            writer.flush();
        }

           这个生成的二维码矢量是黑白的,在某些设计上需要其他色彩的二维码,就不能用这个生成了,可以先找到点阵的向量信息,再用画矢量的一些工具(如EpsGraphics)进行绘制,绘制时可以填充需要的颜色,这里提供一种简易找到点阵矩形向量信息的算法:

           1、把二维码点阵循环进行逐行处理,找到黑块的起止点,以线条为单位保存起来(保存起点坐标信息和终点坐标信息),直至最后一行结束;

           2、把相同横坐标的起点和终点且纵坐标相同的线条合到一起,即找到黑块的矩形坐标向量集合。

           以上绘制二维码只适合简单矩形或圆形的单位点阵二维码,如果涉及复杂的背景图,目前没有很好的矢量化方法,一般只能使用图形设计软件来人工制作了,如果您有把复杂图形矢量化的程序实现方法,欢迎提供。

    • 点阵样式美化

                点阵美化是常见的二维码美化手段,下面可以例举一些例子:

     

     

     

          此类样式的处理方法也不复杂, 主要是看画图的算法实现,一般是先使用开源软件得到二维码原始二维占阵数据BitMatrix[][],然后通过特定的算法,逐个绘制定位符或者把黑点转成彩色圆点。

          这里提供一个绘制定位符和黑点算法例子的部分java代码,国外网站上有些其他语言实现的算法,有兴趣的可以研究下。

            /**
             * 在指定位置绘制定位符
             *
             * @param startX 起点坐标X
             * @param startY 起点坐标Y
             * @param joinType 绘制类型 方角,圆角,斜角,
             * @param argb 绘制颜色
             * @param pointSize
             * @return 绘制是否成功
             */

            private boolean drawPartern(int startX, int startY, int joinType,int[] rgba, int pointSize, int makeMore) {
                    
    if (rgba == null || rgba.length != 4) {
                            
    log.error("绘制颜色不对,必须为RGBA数组");
                            
    return false;
                    }
                    
    this.smooth();
                    
    this.strokeWeight(pointSize);
                    
    this.strokeJoin(joinType);
                    
    // this.noFill();
                    this.fill(rgba[0], rgba[1], rgba[2], rgba[3]);
                    
    this.stroke(rgba[0], rgba[1], rgba[2], rgba[3]);
                    
    int xx = startX;
                    
    int yy = startY;
                    
    this.rect(xx + makeMore * pointSize + pointSize / 2, yy + makeMore
                                    * pointSize + pointSize /
    2, pointSize * 6, pointSize * 6);
                    
    this.stroke(255f);
                    
    this.strokeJoin(joinType);
                    
    this.fill(255f);
                    
    this.rect(xx + (makeMore + 1) * pointSize + pointSize / 2, yy
                                    + (makeMore +
    1) * pointSize + pointSize / 2, pointSize * 4,
                                    pointSize *
    4);
                    
    this.fill(rgba[0], rgba[1], rgba[2], rgba[3]);
                    
    this.stroke(rgba[0], rgba[1], rgba[2], rgba[3]);
                    
    this.strokeJoin(joinType);
                    
    this.rect(xx + (makeMore + 2) * pointSize + pointSize / 2, yy
                                    + (makeMore +
    2) * pointSize + pointSize / 2, pointSize * 2,
                                    pointSize *
    2);
                    
    // drawPartenInner(startX, startY, joinType, rgba, pointSize, makeMore);

    return true;
            }

     

            /**
             * 绘制自定义圆角填充方形
             * @param xx 中心点X
             * @param yy 中心点y
             * @param asize 总大小
             * @param rsize 圆角半径
             * @param r 颜色R
             * @param g 颜色G
             * @param b 颜色B
             * @param arf 颜色透明度
             */

            private void drawRoundRect(float xx, float yy, float asize, float rsize,float r, float g, float b, float alpha) {
                    
    this.noStroke();
                    
    this.smooth();
                    
    float ax;
                    
    float ay;
                    
    // 四个90度扇形
                    ax = xx - asize / 2 + rsize;
                    ay = yy - asize /
    2 + rsize;
                    
    this.arc(ax, ay, 2 * rsize, 2 * rsize, PI, PI + PI / 2);
                    ax = xx + asize /
    2 - rsize;
                    ay = yy - asize /
    2 + rsize;
                    
    this.arc(ax, ay, 2 * rsize, 2 * rsize, PI + PI / 2, 2 * PI);
                    ax = xx - asize /
    2 + rsize;
                    ay = yy + asize /
    2 - rsize;
                    
    this.arc(ax, ay, 2 * rsize, 2 * rsize, PI / 2, PI);
                    ax = xx + asize /
    2 - rsize;
                    ay = yy + asize /
    2 - rsize;
                    
    this.arc(ax, ay, 2 * rsize, 2 * rsize, 0, PI / 2);

    ax = xx - asize / 2 + rsize;
                    ay = yy - asize /
    2;
                    
    this.rect(ax - 1, ay, asize - 2 * rsize + 2, rsize + 1);// 上沿
                    ay = yy + asize / 2 - +rsize;
                    
    this.rect(ax - 1, ay - 1, asize - 2 * rsize + 2, rsize + 1);// 下沿
                    ax = xx - asize / 2;
                    ay = yy - asize /
    2 + rsize;
                    
    this.rect(ax, ay - 1, asize, asize - 2 * rsize + 2);// 中间区块
            }

    public void drawContent() {
                    
    boolean[][] nMatrix = getBitMatrix();
                    
    boolean[][] cMatrix = nMatrix;
                    
    if (getBitMatrix() == null) {
                            
    // 矩阵没有生成
                            log.error("生成错误");
                            
    return;
                    }
                    
    int 拓展 = super.getDilatation();
                    
    int 码宽 = this.getBitMatrix().length;
                    
    float 雕刻宽度 = super.getUnitSize();

    CImage img = this.loadImageJarIO(this.getBackGroundImage());
                    
    this.size(img.width, img.height);
                    
    this.image(img, 0, 0, img.width, img.height);

    int xx = (img.width - this.getArctualSize()) / 2;
                    
    int yy = xx;
                    
    // 定位框
                    float[] rgba = { 151, 56, 124, 255 };
                    
    // 151, 56, 124
                    float[] rgbb = { 255, 126, 141, 255 };
                    
    float[] rgbc = getAvP(rgba, rgbb, 6f / (码宽 - 2 * this.getDilatation()));

    this.noStroke();
                    drawParternRound(xx, yy,
    this.ROUND, rgbc, 雕刻宽度, 拓展);
                    drawParternRound(xx + 雕刻宽度 * (码宽 -
    7 - 2 * 拓展), yy, this.ROUND, rgbc,雕刻宽度, 拓展);
                    rgbc = getAvP(rgba, rgbb,
    0.9f);
                    drawParternRound(xx, yy + 雕刻宽度 * (码宽 -
    7 - 2 * 拓展), this.ROUND, rgbc,雕刻宽度, 拓展);

    // 去掉定位符涂黑
                    for (int i = 0; i < 7; i++) {
                            
    for (int j = 0; j < 7; j++) {
                                    nMatrix[i + 拓展][j + 拓展] =
    false;
                                    nMatrix[码宽 -
    7 - 拓展 + i][j + 拓展] = false;
                                    nMatrix[i + 拓展][码宽 -
    7 - 拓展 + j] = false;
                            }
                    }
                    
    this.noStroke();
                    
    float 半径 = 雕刻宽度 / 2;
                    
    for (int i = 0; i < 码宽; i++) {

    for (int j = 0; j < 码宽; j++) {
                                    
    if (nMatrix[i][j]) {
                                            rgbc = getAvP(rgba,rgbb,(
    float) (j - this.getDilatation())/ (码宽 - 2 * this.getDilatation()));
                                            
    this.fill(rgbc[0], rgbc[1], rgbc[2], rgbc[3]);
                                            
    this.ellipse(xx + i * 雕刻宽度 + 半径, yy + j * 雕刻宽度 + 半径, 雕刻宽度,雕刻宽度);
                                    }
                            }
                    }
            }
     

    • 背景图

          二维码加背景也是常见的样式改进,和二维码增加logo大同小异,说白了,就是二维码图片和背景图片合成,关键是设计背景图的色彩和二维码色彩配当,二维码生成注意前面提到的内容增加版本增加时边框会有变化,需要保证有深色背景时的边框大小,常见的洋葱头二维码就是一个简单的例子:

    使用突破

    • 视觉效果

          黑白二维码到处可见,彩色二维码你一定也见过,但是下面这样的二维码,你不一定见过下面这样的二维码:

     

           这样的二维码是不是看起来美观多了?除了点阵外,还可以通过图片信息来给看到二维码的人传递更多的信息,

          上面这种二维码是在二维码规范基础上作了一定的改进,因为没有违反二维码规范,所以通用的二维码扫码器都能扫码识别出来。这两种图片其实处理的关键技部分都一样的,第二个会动的GIF图,只是多了GIF图拆帧、单帧图片处理、再合成,GIF拆帧都是有现成成熟的处理方法的。所以关键还是单帧处理,业界上有类似的处理方法,但是效果不是特别好:

     

     

          以上处理合成,不是整个图一次处理的,还是按照单位点来进行处理,因为要保证单位点处理完后的图片,在扫码器二值化后,识别出来和原始的二维码黑白点对应,这里二值化时,涉及到一个黑/白点阀值,所以得保证二维码和图像合成后的单位点处在阀值的左边还是右边。

          淘宝最新的处理技术和业务有点不同,采用视觉码最新技术:

    处理的过程大致如下:

        1.背景图片与二维码重合部分处理成简单的bit流V0;

        2. V0 Xor Qrcode bit流(V1),异或得到中间变量V2;

        3. V1进行里德所罗门算法循环变换某些参数,得到变量结果V2’, V2’’, V2’’’…;

        4. 中间变量V2再和V2’, V2’’, V2’’’…一系列值参考,得到最优化的mask图像;

        5. mask图像和二维码bit流V1合并,得到视觉效果优化后的图像。

    上面主要是使用到了德所罗门算法对数据的编码特性,二维码标准文档里生成纠错码写也是这样处理的,只是一般生成码实现,只是实现了一种纠结码生成方式,如zxing里的数据编码,这里处理要生成很多参选的V2’, V2’’, V2’’’…,所以效率上会有点影响。关于德所罗门算法有兴趣的同学可以深入了解下,这个技术使用还是很广泛的,比如碟片数据读取。

    • 动态视频

          和GIF一样,只是多了些视频处理技术,对视频单帧处理,增加二维码,然后再压制成视频,看起来就是一个视频了,由于压制视频比较耗资源,一般都是离线处理。

    • 隐藏信息

          

          以上两个二维码,用通码的扫码器或二维码解析出来的内容都是:http://s.tb.cn/3/H8R8Q/ZhpkPe ,但是第一个是正版商品二维码,第二个是盗版商从第一个解析出来内容,自己再生成赝品二维码,用手淘扫码,可以识别出是否是正品,原理是什么呢?

          二信码除了正常的信息编码到点阵外,还可以把一些隐藏信息加入到二维码上面。前面提到过,不同版本的二维码信息容量不同,如果指定使用某个版本的二维码时,需要编码的信息不需要此版本的容量这么大,这时候多余的信息容量可以存放特殊的一些信息--即隐藏信息。当然这个不是二维码的标准规范,生成的二维码标准信息部分可以被通用的扫码器识别,你加上去的隐藏信息,就得你自己来解码了。

          关于隐藏信息存放位置,想了解的同学,可以参考下《QR Code Specification》里面8.4.8章节和8.4.9章节关于数据编码的补齐码和终结符。

          隐藏信息可以使用到很多地方,因为信息编码是你生成的,所以别处无法得知和防造,可以保证二维码生成的唯一性:

          

         

          扫码得到商品信息判断真假就是一个典型的使用。

          如果盗版者用拍照或扫描原始二维码图,进行拷贝,也可以利用二维码的扫码次数进行次要验证,同一商品码是否被大量扫码,验证是否正品,一般正品卖出来后,扫码次数都是只有买家扫的少数几次。

          当然这种隐藏信息使用也有缺点,就是扫码需要你的专用SDK,不然无法读取,对于手淘扫码用户量这么大情况下,可以很好的利用起来。

    其他二维码

           除了Qrcode之外,还有不少其他类型的二维码,如PDF417、QRCCode、Data Matrix、Maxi Code、Code 49、Code 16K、Code One等二维码,这些互联网上都有不少介绍,这里不再赘述。这里举几个比较形象的例子:

    • 彩链码

          彩链码是一种利用二维点阵再加上其中基本色彩(Blue、Red、Green、Black)作为信息载体,所以包含的信息长度有限,但是排列组合可以很多:

          上面的第一张图是最简单的彩链码,只有方块和颜色,再加上边框。第二三张是在第一张基础上的变形美化,扫码识别过程和第一种也是一样的,按照码的版本,对点阵图进行切割固定的块,然后对块主要色彩识别,这时块不是简单的0或1两进制了,而是4进制数据。

         这种二维码可以在符合点阵规律的基础上,适当发挥把各种图形融合进来,以达到码信息传递和视觉效果的并存。

         由于点阵不能太复杂,包含信息不多,所以不能直接表达复杂的信息,一般扫码后,需要通过这个特定排列的组合去服务端拿到真正的复杂数据信息。

          除了需在服务端访问外,还有的缺点是新型的码很难被用户认知和使用起来,一来图形和码融合太紧密,需要让用户知道可以当作码扫,另外这个需要专用的SDK才能扫,如果拥有海量用户的APP可以很好推广起来,如手淘、微信。

    • 4G

         4G码严格来说,不属于二维码范畴,属于图像特征信息扫描,不过利用了二维码定位符,扫码时将定位符内的图像裁剪然后进行图像特征处理,相对于整个图像处理地,这种方法提取的图像的特征会比较稳定,各种方式扫码得到的特征值都比较容易确定为某一值,容错能力比较强,生成码时,训练下扫码图像特征值,确定后与确定目标信息绑定,如商品连接,目前手淘扫码很快就支持4G码扫码:

     

           这种码对图像的破坏很小,生成的码非常美观,不过用户的认知性会比较差,在引导用户扫码上需要成本。

    展开全文
  • 二维码定位

    万次阅读 2017-11-02 11:15:52
    使用opencv确定图片中二维码的位置

    使用opencv确定图片中二维码的位置

    背景

    确定二维码的位置并识别,有很多开源的例子,但是毕竟不是自己做的,还是想自己一步步学习一下,这里只做了一下工作:

    1.确定二维码在图片中的位置,输出其像素坐标。

    2.使用透视变换对识别的二维码矩形进行修正,方便之后的二维码识别(这里暂不做识别,有意的同学可以使用Zbar,zxing进行识别)。

    在opencv的学习上我还是一个小白,有些考虑不周的地方还请多多指教。

    流程图

    首先上一张二维码的示意图,这里用abcd指代小矩形,下文会用到。
    2

    下面是流程图
    img8

    实现

    对每一帧的图像的预处理详见附件,这里直接从Canny提取轮廓之后开始讲述

    1. 边缘检测–Canny
    Canny(blurImage, edgeTemp, canny_thread_min, canny_thread_max, 3);
    
    2. 提取轮廓–findContours (文末有备注)
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    //输入图像,轮廓(点向量形式),轮廓数量,轮廓检索模式,轮廓逼近 
    findContours(edgeTemp, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    
    3. 绘制嵌套层次大于5的轮廓 (详情请点击此处了解hierarchy的含义)
    vector<int> vector_contours_filter;
    for (int k, c, i = 0; i < contours.size(); i++)
    {
    	k = i;
    	c = 0;
    	while (hierarchy[k][2] != -1)//表示不是最外面的轮廓
    	{
    		k = hierarchy[k][2];
    		c = c + 1;
    	}
    	if (c >= 5)
    	{
    		vector_contours_filter.push_back(i);
    	}
    }
    
    4. 利用abc三个小矩形的12个顶点做最小包围矩形
    //这里直接使用三个小矩形的12个顶点来绘制最小包围矩形
    Point2f point_minRect12[4];
    RotatedRect rect12 = minAreaRect(vertex_minRect4);	//vertex_minRect4 -> 装有abc三个小矩形的12个顶点的容器
    rect12.points(point_minRect12);//返回矩形的四个顶点给vertex  
    for (int j = 0; j < 4; j++)
    {
    	line(src1, point_minRect12[j], point_minRect12[(j + 1) % 4], Scalar(0, 0, 255), 3, 8);//非常巧妙的表达式
    }
    
    Point2f midPoint_rect;
    for (int j = 0; j < 4; j++)
    {
    	midPoint_rect.x += (point_minRect12[j].x / 4);
    	midPoint_rect.y += (point_minRect12[j].y / 4);
    }
    circle(src1, midPoint_rect, 10, Scalar(0, 255, 0), 3, 8);	//外接矩形的的中心
    imshow("结果图", src1);
    

    经过这次处理之后,基本上就只剩下abc三个小矩形了。一般情况下,利用这三个小矩形的各个顶点,绘制包围他们的最小矩形(约定包围整个二维码的最小矩形为矩形A),然后求得矩形A的中心点O,这样就得到了像素坐标下的二维码的位置。效果如下图所示:
    img3

    但是,偶尔会有这种特殊的情况发生
    img4 img5

    ############### 这就很尴尬了。。。##################

    虽然这只是个别的情况,但也说明了只利用abc这三个小矩形来确定二维码的位置并不可靠。所以很有必要确定第四个小矩形d的位置,利用其把这个别情况下的二维码的最小包围矩形框纠正回来。

    5. 画出第四个小矩形d

    已知三个小矩形abc之后,第四个矩形d也就比较容易了。

    img6

    在第4步中的代码注释中提到vertex_minRect4是装有矩形abc总计12个顶点的容器,遍历这12个顶点,求两点之间的距离,找出距离最远的两个点,就是点a-1和c-3,然后利用求线段中点的公式,如下:

    midPoint.x = (P_1.x + P_2.x)/2;
    
    midPoint.y = (P_1.y + P_2.y)/2;
    

    来获取中点O的坐标,然后再分别求矩形b的四个点关于中点O的对称点的坐标,就是求线段中点的逆过程嘛。于是乎,矩形d的四个顶点我们就get到了。最后利用这四个矩形abcd的16个顶点,画它们的最小外接矩形,再通过矩形的四个顶点求取二维码的中点,

    到这里,二维码在图像中的位置就确定了,是像素坐标哦

    上述的那个特殊情况就不存在了Yeah!

    6. 提取二维码

    使用透视变换,将二维码投影到另一个平面,方便以后的识别

    1. 二维码的四个顶点的坐标:上一步利用abcd四个矩形的16个顶点做最小包围矩形时,可以获得矩形的四个顶点,数组vertexs_minRect_QR表示。

    2. 新的投影点的坐标:新的投影平面中,二维码的坐标可以自己定义,比如

    //lenth是二维码的变长
    Point2f vertex_warp[4];
    vertex_warp[0] = Point2f(0, float(lenth-1));
    vertex_warp[1] = Point2f(0, 0);
    vertex_warp[2] = Point2f(float(lenth-1), 0);
    vertex_warp[3] = Point2f(float(lenth-1), float(lenth));
    
    1. 求解透视变换的矩阵
      可以使用opencv库中的getPerspectiveTransform函数获得
    //! returns 3x3 perspective transformation for the corresponding 4 point pairs.
    CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] );
    

    操作代码如下,由此获得变换矩阵transform

    Mat transform = getPerspectiveTransform(vertexs_minRect_QR, vertex_warp);
    
    1. 透视变换的实现
      奉上透视变换的函数warpPerspective
    //! warps the image using perspective transformation
    CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
                                       InputArray M, Size dsize,
                                       int flags=INTER_LINEAR,
                                       int borderMode=BORDER_CONSTANT,
                                       const Scalar& borderValue=Scalar());
    

    实现

    warpPerspective(src, dst, transform, Size(lenth, lenth)); 
    

    结果图
    img7
    左是识别的效果图,右上是使用透视变换投影到另一个平面的效果,右下是二维码中心在原图中的像素坐标

    备注:关于提取轮廓findContours函数的参数说明

    函数原型如下:

    //! retrieves contours and the hierarchical information from black-n-white image.
    CV_EXPORTS_W void findContours( InputOutputArray image, OutputArrayOfArrays contours,
                                  OutputArray hierarchy, int mode,
                                  int method, Point offset=Point());
    

    其中的参数mode有以下可供选择,在识别二维码中,只能使用CV_RETR_TREE

    RETR_EXTERNAL=CV_RETR_EXTERNAL, //!< retrieve only the most external (top-level) contours
    RETR_LIST=CV_RETR_LIST, //!< retrieve all the contours without any hierarchical information
    RETR_CCOMP=CV_RETR_CCOMP, //!< retrieve the connected components (that can possibly be nested)
    RETR_TREE=CV_RETR_TREE, //!< retrieve all the contours and the whole hierarchy
    RETR_FLOODFILL=CV_RETR_FLOODFILL
    

    详情请点击此处了解
    最后附上支付宝红包二维码,欢迎客官扫一扫~
    在这里插入图片描述

    展开全文
  • 用户画像愈清晰明显,那么产品的服务对象更加聚焦,和更加专注,产品也更容易成功。 那么什么是用户画像呢? 用户画像,是品牌根据对客户的了解、网站数据的分析,所拟出的一个半虚拟的客户模型,代表品牌受众群中的...
  • 二维码发展 二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型:比如:字符,数字,日文,中文等等。这...
  • opencv 二维码定位

    千次阅读 多人点赞 2018-11-24 14:11:26
    最近师兄跟我提到我二维码定位,参考了许多大佬的程序,写了这个小程序 目的: 用opencv的库实现QRcode定位 环境: Windows 10 VS2015 opencv3.4.0 基本原理 下图为二维码的其中一个黑色正方形,二维码...
  • 线上预览地址:http://47.100.232.201/github/qrcode/examples/demo.html 我的github地址有详细使用说明:https://github.com/miracle2017/qrcode_download
  • 最近有负责微信开发,对于微信开发的项目,肯定少不了二维码啦,正好有个这样的需求,这对不同的商品生成一个二维码,扫码即刻下单。博主就弄了一个二维码生成的工具类。弄出来之后,产品经理又说了,中间放上公司的...
  • 随着互联网短视频平台竞争加剧,如何针对性的给短视频平台用户推荐合适的内容,从而增加平台对于用户的粘性,巩固和扩大用户市场,是...近日,二维彩虹与抖音就定制一次性二维码展开深度合作 。帮助抖音解决用户数据筛
  • 初探AR技术

    千次阅读 多人点赞 2019-10-06 15:36:58
    初探AR技术 AR概述 概念定义: 技术手段: 参考实例: AR解决方案 AR SDK ARKit 简介 扩展 ...  增强现实(Augmented Reality,简称AR),也...A-Frame基于HTML,容易上手。但是A-Frame不仅仅是一个3D场景渲染引擎或者一...
  • 怎么做出牛逼的二维码图片?

    万次阅读 2016-12-02 11:04:13
    怎么做出牛逼的二维码图片?当然不是黑白两色的那种二维码图片了,要牛逼,要图形化,场景化、游戏化,一起看看牛逼的二维码图片是怎么做出来的吧! 我曾经以为,二维码就是这样的 或者是这样的  ...
  • 浅析二维码基本原理

    千次阅读 2020-10-21 16:08:01
    纠错码 上面我们说到了一些纠错级别,Error Correction Code Level,二维码中有四种级别的纠错,这就是为什么二维码有残缺还能扫出来,也就是为什么有人在二维码的中心位置加入图标。 水平级别 错误修正容量 L水平 ...
  • python下二进制流文件转二维码

    千次阅读 2019-09-28 16:07:01
    python下二进制流文件转二维码 之前做过的一个ctf中的misc,经过一系列操作得到一个flag.txt 里面是一串二进制流 突然束手无策 经简单计算 260^2=67600 所以尝试能否转化为一个二维码 网上找了好久,没找到好用的...
  • 或许给网站添加二维码,对网站有一定的宣传推广作用,用户可以通过手机扫描网站二维码就可以直接浏览网站,且关注网站。 通过扫描二维码可以随时看到网站推送的视频、音频广告、新鲜事宜等等,总之只要通过扫描...
  • 1、启动条码打印软件,二维码工具,在页面中一下会出来一个QRcode二维码。点击该二维码,在右侧属性栏条码属性里,输入二维码数据,生成二维码。这里做出三个二维码。 2、将黑白二维码变成彩色二维码。单击选择一...
  • Opencv的使用小教程3——利用轮廓检测实现二维码定位二维码具有什么特征识别二维码的流程1、预处理图像2、寻找轮廓 好好学习噢! 二维码具有什么特征 二维码就是两个维度的条形码,平常我们在生活中随处可见,“QR...
  • 关键点在于如何从图像中快速而准确的找到二维码区域,寻找到二维码三个匹配模式点(定位块)。 一:二维码的组成 要关注的是图中三个黑色正方形区域,它们就是用来定位一个二维码的最重要的三个区域,首先要做的...
  • 二维码,如何设计创意二维码

    千次阅读 2016-10-29 00:56:16
    我曾经以为,二维码就是这样的 或者是这样的 好看一点的也不过是这样的…… 直到有一天,boss说: 于是LZ便去问度娘:啥是“流弊”的二维码? 接着LZ的世界观被凶残的刷新了…… ...
  • 本文原文地址:【Java,二维码】Java 使用 swetake 生成二维码图片,本文更新不及时,建议到原文地址浏览。 二维码又称二维条码,是1994年由日本DW公司发明。常见的二维码为QR Code,QR全称Quick Response,是一个近...
  • 一篇文章让你知道ZXing是怎么知道图片中是否有二维码的。
  • 目录 1 引入 2 历史 2.1 一维码 2.2 二维码 3 分类 3.1 线性堆叠式二维码 3.2 矩阵式二维码 ...5.4 画二维码 5.5 二维码优势 6 个性二维码 7 总结 1 引入 近年来,随着移动互联网的发展,二维...
  • 二维码的特征定位和信息识别

    万次阅读 多人点赞 2018-01-20 21:53:44
    二维码的特征定位和信息识别 背景介绍 视觉的方法可以用来估计位置和姿态。最容易想到的是在目标上布置多个容易识别的特征,这样使用opencv相机标定和、相机畸变矫正、轮廓提取、solvepnp来获取目标相对于相机的...
  • 手绘二维码

    2019-03-22 13:37:12
    看到二维码,很容易猜到黑白相间的小方格就是二进制比特。那么这些比特是怎么得到的?小方格又是按照什么规则排布的?今天咱们就从零开始将一个 url 二维码。 考虑到大多数人可能不太了解二维码,所以先讲下基础...
  • 二维码(带Logo)加密解密-QRCode方式

    千次阅读 2020-08-25 16:33:14
    二维码加密解密-QRCode 加密工具类 /** * Copyright © 2020wangylCompany. All rights reserved. * * @Title: QRCodeUtil.java * @Prject: MyTestDemo * @Package: qrcode * @Description: TODO * @version...
  • 二维码介绍 Android中用于二维码相关的库比较少,并且大多数已经不再维护(具体可见https://android-arsenal.com/tag/81)。其中最常用的是zxing和zbar。 zxing项目是谷歌推出的用来识别多种格式条形码的开源项目...
  • 众所周知,我是一个不务正业的六年级可怜UP主,二维码在我们的生活中无处不在,比如我们老师发作业,就是发一个二维码,扫码后自动跳转到那个交作业的页面,而我一直就很好奇,这个东东是怎么做出来的呢?...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,895
精华内容 3,558
关键字:

容易画的二维码