精华内容
参与话题
问答
  • QRCode二维码生成与识别 IDEA2017测试通过,可以生成普通二维码以及带图片的二维码。
  • Python二维码应用(一)QRcode二维码生成&识别

    万次阅读 多人点赞 2019-01-05 20:35:39
    基于Python的二维码实验一、机器视觉之QRcode二、基于Python的QRcodetest(一)配置环境(二)生成自己的二维码(三)识别二维码三、调用opencv库摄像头识别图像 一、机器视觉之QRcode 问:什么是QRcode呢? 答...

    一、机器视觉之QRcode

    问:什么是QRcode呢?
    答:二维码(2-dimensional bar code),是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的。它能将数字、英文字母、汉字、日文字母、特殊符号(如空格,%,/ 等)、二进制等信息记录到一个正方形的图片中。
    因此,在转换的过程中,离不开编码压缩方式。在许多种类的二维条码中,常用的码制有:Data Matrix,Maxi Code,Aztec,QR Code,Vericode,PDF417,Ultracode,Code 49,Code 16K等。
    二维码在现实生活中的应用越来与普遍,归功于 QR code 码制的流行。我们常说的二维码就是它,所以,二维码又被称为 QR code。
    QR code 是一种矩阵式二维条码(又称棋盘式二维条码)。它是在一个矩形空间通过黑、白像素在矩阵中的不同分布进行编码。在矩阵相应元素位置上,用点(方点、圆点或其他形状)的出现表示二进制“1”,点的不出现表示二进制的“0”,点的排列组合确定了矩阵式二维条码所代表的意义。
    我们的目的是要使用 Python 生成 QR 码,那我们需要先了解二维码(QR 码)的结构。根据标准(ISO/IEC 18004),我们可以了解到 QR 码结构如下:
    在这里插入图片描述
    二维码的绘制大概过程如下:
    在二维码的左上角、左下角、右上角绘制位置探测图形,位置探测图形一定是一个 7x7 的矩阵;
    (1)绘制校正图形,校正图形一定是一个 5x5 的矩阵;
    (2)绘制两条连接三个位置探测图形的定位图形;
    (3)在上述图片的基础上,继续绘制格式信息;
    (4)接着绘制版本信息;
    (5)填充数据码和纠错码到二维码图中;
    (6)最后绘制蒙版图案。因为按照上述方式填充内容,可能会出现大面积空白或黑块的情况,导致扫描识别十分困难。所以需要对整个图像与蒙版进行蒙版操作(Masking),蒙版操作即为异或 XOR 操作。在这一步,我们可以将数据排列成各种图片。

    问:主要运用qrcode库文件、这是个什么东东呢?
    答: 这里给一篇博客有详细叙述:Python生成二维码

    开源库import qrcode具体使用方法:
    编码:

    #原始二维码编码
    import qrcode
    img = qrcode.make('helloworld')
    #带图片的编码方式
    qr = qrcode.QRCode(
        version=5,
        error_correction=qrcode.constants.ERROR_CORRECT_H,
        box_size=8,
        border=4)
    

    解码:

    #调用decode()的解码函数
    def decode_qr_code(code_img_path):
        if not os.path.exists(code_img_path):
            raise FileExistsError(code_img_path)
        # Here, set only recognize QR Code and ignore other type of code
        return pyzbar.decode(Image.open(code_img_path), symbols=[pyzbar.ZBarSymbol.QRCODE])
    

    二、基于Python的QRcodetest

    环境:python3.7+zbar+qrcode

    (一)配置环境

    打开cmd、pip分别安装以下库文件:(zxing也是一个强大的二维码开源库文件,建议安装)

    pip install opencv-python
    pip install numpy
    pip install pillow
    pip install myqr
    pip install qrcode
    pip install zxing
    

    tips:记得安装完成后,如果是eclipse要重新启动一次才能加载进来

    (二)生成自己的二维码

    1 MyQr制作gif二维码:

    同目录下放置一张gif格式图片
    在这里插入图片描述

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

    源码:

    #!/usr/bin/env python3
    # -*- coding:utf-8 -*-
    from MyQR import myqr
    myqr.run(
        # 在命令后输入链接或者句子作为参数,然后在程序的当前目录中产生相应的二维码图片文件,默认命名为“qrcode.png”
        words='helloworld',
        version=1,  # 设置容错率为最高默认边长是取决于你输入的信息的长度和使用的纠错等级;而默认纠错等级是最高级的H
        level='H',  # 控制纠错水平,范围是L、M、Q、H,从左到右依次升高
        picture='test.gif',  # 用来将QR码图像与一张同目录下的图片相结合,产生一张黑白图片,格式可以是.jpg, .png, .bmp, .gif
        colorized=True,  # 可以使产生的图片由黑白(False)变为彩色(True)的
        contrast=1.0,  # 用以调节图片的对比度,1.0 表示原始图片,更小的值表示更低对比度,更大反之。默认为1.0。
        brightness=1.0,  # 用来调节图片的亮度
    )
    

    2 qrcode制作带图片的二维码:
    新建工程QRcodeTest;新建PyDev包,命名为MakeMyQRcode:
    在这里插入图片描述

    因为我想做出一个漂亮简单一点的code,所以首先在目录文件下贴入一张图片,命名为QRcodeCenter,like this(左:成果图,右:准备中心图片):
    在这里插入图片描述 在这里插入图片描述

    源码:

    '''
    ==============================
    test1:生成二维码及查看
    ==============================
    '''
    from PIL import Image
    import qrcode
    
    qr = qrcode.QRCode(
        version=5, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=8, border=4)
    qr.add_data("这里是二维码信息!")
    qr.make(fit=True)
    
    img = qr.make_image()
    img = img.convert("RGBA")
    
    icon = Image.open("QRcodeCenter.jpg")  # 这里是二维码中心的图片
    
    img_w, img_h = img.size
    factor = 4
    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
    icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS)
    
    w = int((img_w - icon_w) / 2)
    h = int((img_h - icon_h) / 2)
    icon = icon.convert("RGBA")
    img.paste(icon, (w, h), icon)
    img.show()   # 显示图片,可以通过save保存
    

    (三)识别二维码

    在工程QRcodeTest;新建PyDev包,命名为ScanQRcode:
    在这里插入图片描述
    运行结果:
    在这里插入图片描述 在这里插入图片描述
    源码:

    # -*- coding:utf-8 -*-
    
    '''
    ====================================
    test2:生成二维码保存及对二维码解码输出
    ====================================
    '''
    import os
    import qrcode
    from PIL import Image
    from pyzbar import pyzbar
    
    
    def make_qr_code(content, save_path=None):
        qr_code_maker = qrcode.QRCode(version=5,
                                      error_correction=qrcode.constants.ERROR_CORRECT_M,
                                      box_size=8,
                                      border=4,
                                      )
        qr_code_maker.add_data(data=content)
        qr_code_maker.make(fit=True)
        img = qr_code_maker.make_image(fill_color="black", back_color="white")
        if save_path:
            img.save(save_path)
        else:
            img.show()  # 中间图不显示
    
    
    def make_qr_code_with_icon(content, icon_path, save_path=None):
        if not os.path.exists(icon_path):
            raise FileExistsError(icon_path)
    
        # First, generate an usual QR Code image
        qr_code_maker = qrcode.QRCode(version=5,
                                      error_correction=qrcode.constants.ERROR_CORRECT_H,
                                      box_size=8,
                                      border=4,
                                      )
        qr_code_maker.add_data(data=content)
        qr_code_maker.make(fit=True)
        qr_code_img = qr_code_maker.make_image(
            fill_color="black", back_color="white").convert('RGBA')
    
        # Second, load icon image and resize it
        icon_img = Image.open(icon_path)
        code_width, code_height = qr_code_img.size
        icon_img = icon_img.resize(
            (code_width // 4, code_height // 4), Image.ANTIALIAS)
    
        # Last, add the icon to original QR Code
        qr_code_img.paste(icon_img, (code_width * 3 // 8, code_width * 3 // 8))
    
        if save_path:
            qr_code_img.save(save_path)  # 保存二维码图片
            qr_code_img.show()  # 显示二维码图片
        else:
            print("save error!")
    
    
    def decode_qr_code(code_img_path):
        if not os.path.exists(code_img_path):
            raise FileExistsError(code_img_path)
    
        # Here, set only recognize QR Code and ignore other type of code
        return pyzbar.decode(Image.open(code_img_path), symbols=[pyzbar.ZBarSymbol.QRCODE])
    
    
    if __name__ == "__main__":
        print("============QRcodetest===============")
        print("         1、Make a QRcode            ")
        print("         2、Scan a QRcode            ")
        print("=====================================")
        print("1、请输入编码信息:")
        code_Data = input('>>:').strip()
        print("正在编码:")
        # ==生成带中心图片的二维码
        make_qr_code_with_icon(
            code_Data, "QRcodeCenter.jpg", "qrcode.png")  # 内容,center图片,生成二维码图片
        print("图片已保存,名称为:qrcode.png")
        results = decode_qr_code("qrcode.png")
        print("2、正在解码:")
        if len(results):
            print("解码结果是:")
            print(results[0].data.decode("utf-8"))
        else:
            print("Can not recognize.")
    

    三、调用opencv库摄像头识别图像

    (一)用opencv找出(条形码&二维码)位置

    opencv抠图教程
    按照教程一步步调试运行(这里用一张条形码和一张二维码进行测试):

    • QRcodetest项目下新建ScanQRcode.py
      在这里插入图片描述
    • 并保存两张图片在项目目录下:分别为qrcode.pngtest2.jpg
      在这里插入图片描述
      运行测试:(不支持二维码)
      qrcode.png:
      在这里插入图片描述
      test2.jpg:
      在这里插入图片描述
      遇到问题:
      都只识别了部分条码,抠图也不是很成功!而且不能识别二维码!
      在这里插入图片描述

    源码:

    # -*- coding: UTF-8 -*-
    '''
    ==============================
    test3:找出图片中的条形码或二维码
    (ps.仅识别条形码成功)
    ==============================
    '''
    import numpy as np
    import argparse
    import cv2
    
    print("请输入解码图片完整名称:")
    code_name = input('>>:').strip()
    print("正在识别:")
    #image = cv2.imread("test2.jpg")
    image = cv2.imread(code_name)
    # 灰度
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # 使用opencv自带的Sobel算子进行过滤
    gradX = cv2.Sobel(gray, ddepth=cv2.cv2.CV_32F, dx=1, dy=0, ksize=-1)
    gradY = cv2.Sobel(gray, ddepth=cv2.cv2.CV_32F, dx=0, dy=1, ksize=-1)
    
    # 将过滤得到的X方向像素值减去Y方向的像素值
    gradient = cv2.subtract(gradX, gradY)
    # 先缩放元素再取绝对值,最后转换格式为8bit型
    gradient = cv2.convertScaleAbs(gradient)
    # 均值滤波取二值化
    blurred = cv2.blur(gradient, (9, 9))
    (_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
    
    # 腐蚀和膨胀的函数
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
    closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    closed = cv2.erode(closed, None, iterations=4)
    closed = cv2.dilate(closed, None, iterations=4)
    
    # 找到边界findContours函数
    (_, cnts, _) = cv2.findContours(closed.copy(),
                                    cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 计算出包围目标的最小矩形区域
    c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
    rect = cv2.minAreaRect(c)
    box = np.int0(cv2.boxPoints(rect))
    
    #======显示=======
    cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
    cv2.imshow("ScanQRcodeTest", image)
    cv2.waitKey(0)
    

    (二)调用解码函数进行解码

    • QRcodetest项目下新建ScanInvedio.py
      在这里插入图片描述
      运行测试:(不支持条形码)

    因为我自身电脑摄像头设置,颜色有点问题,请忽略

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

    源码:

    '''
    ================================
    test4:识别摄像头中的条形码或二维码
    (ps.仅识别二维码码成功)
    ================================
    '''
    import cv2
    import pyzbar.pyzbar as pyzbar
    
    def decodeDisplay(image):
        barcodes = pyzbar.decode(image)
        for barcode in barcodes:
            # 提取二维码的边界框的位置
            # 画出图像中条形码的边界框
            (x, y, w, h) = barcode.rect
            cv2.rectangle(image, (x, y), (x + w, y + h), (225, 225, 225), 2)
    
            # 提取二维码数据为字节对象,所以如果我们想在输出图像上
            # 画出来,就需要先将它转换成字符串
            barcodeData = barcode.data.decode("utf-8")
            barcodeType = barcode.type
    
            # 绘出图像上条形码的数据和条形码类型
            text = "{} ({})".format(barcodeData, barcodeType)
            cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,
                        .5, (225, 225, 225), 2)
    
            # 向终端打印条形码数据和条形码类型
            print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))
        return image
    
    
    def detect():
        camera = cv2.VideoCapture(0)
    
        while True:
            # 读取当前帧
            ret, frame = camera.read()
            # 转为灰度图像
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            im = decodeDisplay(gray)
    
            cv2.waitKey(5)
            cv2.imshow("camera", im)
            # 如果按键q则跳出本次循环
            if cv2.waitKey(10) & 0xFF == ord('q'):
                break
        camera.release()
        cv2.destroyAllWindows()
        
    if __name__ == '__main__':
        detect()
    

    大功告成!

    展开全文
  • 内网通扫码签到的二维码识别
    // 内网通扫码签到的二维码识别
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.FileSystems;
    import java.nio.file.Path;
    import java.util.HashMap;
    import java.util.Map;
    import javax.imageio.ImageIO;
    
    import com.google.gson.Gson;
    import com.google.zxing.*;
    import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
    import com.google.zxing.client.j2se.MatrixToImageWriter;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.common.HybridBinarizer;
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.lang.StringUtils;
    
    public class Test {
        private static final String fromDir = "/mnt/shared/qrcodes";
        private static final String toDir = "/mnt/shared/processedQRCodes";
        private static final String PNG = ".png";
    
        public static void main(String[] args) {
            File dir = new File(fromDir);
            if(dir.exists() && dir.isDirectory()){
                File[] files = dir.listFiles();
                for(File f:files){
                    if(f.isFile()&&f.getName().toLowerCase().endsWith(PNG)){
                        String res = decode(f);
                        System.out.println(res);
                        if(StringUtils.isNotBlank(res)){
                            // move to processed dir
                            boolean moved = move(f,new File(toDir+File.separator+f.getName().substring(0,f.getName().indexOf("."))+"_"+res+PNG));
                            System.out.println(moved==true?"Moved to processed dir.":"Can't move file: "+f.getAbsolutePath());
                        }
                    }
                }
            }
    
            encode("http://baike.baidu.com/link?url=BP7l08ZZZa7HBLL0g4RCuVsN3BlNbuokYRKCuUk8ZexPDjxSVNMXQq_08WI1xz5EUAjVrce4qgSisos9K-mq-q");
        }
    
        private static boolean  move(File f,File toDir){
            return f.renameTo(toDir);
        }
    
        /**
         * 解析图像
         */
        public static String decode(File file) {
            BufferedImage image;
            String res = null;
            try {
                image = ImageIO.read(file);
                LuminanceSource source = new BufferedImageLuminanceSource(image);
                Binarizer binarizer = new HybridBinarizer(source);
                BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
                Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
    //            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
                Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码
                String resultStr = result.getText();
    //            System.out.println(resultStr);
                String t = resultStr.substring(resultStr.indexOf("?")+3,resultStr.length());
                String base64 = new String(Base64.decodeBase64(t));
    //            System.out.println(t);
                System.out.print(base64+"   --->   ");
                DecodeResult decodeResult = new Gson().fromJson(base64,DecodeResult.class);
                res = decodeResult.getD();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotFoundException e) {
                e.printStackTrace();
            }
            return res;
        }
    
        public static void encode(String content){
            int width = 400; // 图像宽度
            int height = 400; // 图像高度
            String format = "png";// 图像类型
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            try{
                BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                        BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵
                Path path = FileSystems.getDefault().getPath(toDir, "code.png");
                MatrixToImageWriter.writeToPath(bitMatrix, format, path);// 输出图像
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    
    class DecodeResult{
        private String a;
        private String b;
        private String c;
        private String d;
        private String v;
    
        public String getA() {
            return a;
        }
    
        public void setA(String a) {
            this.a = a;
        }
    
        public String getB() {
            return b;
        }
    
        public void setB(String b) {
            this.b = b;
        }
    
        public String getC() {
            return c;
        }
    
        public void setC(String c) {
            this.c = c;
        }
    
        public String getD() {
            return d;
        }
    
        public void setD(String d) {
            this.d = d;
        }
    
        public String getV() {
            return v;
        }
    
        public void setV(String v) {
            this.v = v;
        }
    }


    展开全文
  • qrCode二维码的生成和识别

    千次阅读 2016-03-31 15:31:34
    有关二维码的介绍,我这里不做过多说明, 可以直接去基维百科查看,附上链接 QR code . IOS7之前,开发者进行扫码编程时,一般会借助第三方库。常用的是 ZBarSDKa 和 ZXingObjC ,IOS7之后,系统的...

    有关二维码的介绍,我这里不做过多说明, 可以直接去基维百科查看,附上链接 QR code .

    IOS7之前,开发者进行扫码编程时,一般会借助第三方库。常用的是 ZBarSDKa ZXingObjC ,IOS7之后,系统的AVMetadataObject类中,为我们提供了解析二维码的接口。经过测试,使用原生API扫描和处理的效率非常高,远远高于第三方库。

    扫描

    官方提供的接口非常简单,直接看代码,主要使用的是AVFoundation。

    @interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>//用于处理采集信息的代理
    {
        AVCaptureSession * session;//输入输出的中间桥梁
    }
    @end
    @implementation ViewController
     
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        //获取摄像设备
        AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        //创建输入流
        AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        if (!input) return;
        //创建输出流
        AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
        //设置代理 在主线程里刷新
        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        //设置有效扫描区域
        CGRect scanCrop=[self getScanCrop:_scanWindow.bounds readerViewBounds:self.view.frame];
         output.rectOfInterest = scanCrop;
        //初始化链接对象
        _session = [[AVCaptureSession alloc]init];
        //高质量采集率
        [_session setSessionPreset:AVCaptureSessionPresetHigh];
        
        [_session addInput:input];
        [_session addOutput:output];
        //设置扫码支持的编码格式(如下设置条形码和二维码兼容)
        output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
        
        AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
        layer.videoGravity=AVLayerVideoGravityResizeAspectFill;
        layer.frame=self.view.layer.bounds;
        [self.view.layer insertSublayer:layer atIndex:0];
        //开始捕获
        [_session startRunning];
    }
    
    -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
        if (metadataObjects.count>0) {
            //[session stopRunning];
            AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
            //输出扫描字符串
            NSLog(@"%@",metadataObject.stringValue);
        }
    }
    

    一些初始化的代码加上实现代理方法便完成了二维码扫描的工作,这里我们需要注意的是, 在二维码扫描的时候, 我们一般都会在屏幕中间放一个方框,用来显示二维码扫描的大小区间,这里我们在个 AVCaptureMetadataOutput 类中有一个 rectOfInterest 属性,它的作用就是设置扫描范围。

    这个CGRect参数和普通的Rect范围不太一样,它的四个值的范围都是0-1,表示比例。

    rectOfInterest都是按照横屏来计算的 所以当竖屏的情况下 x轴和y轴要交换一下。

    宽度和高度设置的情况也是类似。

    我们在上面设置有效扫描区域的方法如下

    #pragma mark-> 获取扫描区域的比例关系
    -(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)readerViewBounds
    {
        
        CGFloat x,y,width,height;
        
        x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds);
        y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds);
        width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds);
        height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds);
        
        return CGRectMake(x, y, width, height);
        
    }
    

    读取

    读取主要用到CoreImage 不过要强调的是读取二维码的功能只有在iOS8之后才支持,我们需要在相册中调用一个二维码,将其读取,代码如下

    #pragma mark-> 我的相册
    -(void)myAlbum{
        
        NSLog(@"我的相册");
        if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
            //1.初始化相册拾取器
            UIImagePickerController *controller = [[UIImagePickerController alloc] init];
            //2.设置代理
            controller.delegate = self;
            //3.设置资源:
            /**
             UIImagePickerControllerSourceTypePhotoLibrary,相册
             UIImagePickerControllerSourceTypeCamera,相机
             UIImagePickerControllerSourceTypeSavedPhotosAlbum,照片库
             */
            controller.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
            //4.随便给他一个转场动画
            controller.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
            [self presentViewController:controller animated:YES completion:NULL];
            
        }else{
            
            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"设备不支持访问相册,请在设置->隐私->照片中进行设置!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
            [alert show];
        }
        
    }
    

    完成相册代理, 我们在代理中添加读取二维码方法

    #pragma mark-> imagePickerController delegate
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
    {
        //1.获取选择的图片
        UIImage *image = info[UIImagePickerControllerOriginalImage];
        //2.初始化一个监测器
        CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
        
        [picker dismissViewControllerAnimated:YES completion:^{
            //监测到的结果数组
            NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
            if (features.count >=1) {
                /**结果对象 */
                CIQRCodeFeature *feature = [features objectAtIndex:0];
                NSString *scannedResult = feature.messageString;
                UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"扫描结果" message:scannedResult delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alertView show];
              
            }
            else{
                UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"该图片没有包含一个二维码!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alertView show];
                
            }
            
      
        }];
        
        
    }
    

    因为没用真机,所以这里没有给出太多的截图, 用模拟器读取自带图片,结果如下

    生成

    生成二维码,其实也是用到CoreImage,但是步骤繁琐一些,代码如下

    #pragma mark-> 二维码生成
    -(void)create{
        
        UIImage *image=[UIImage imageNamed:@"6824500_006_thumb.jpg"];
        NSString*tempStr;
        if(self.textField.text.length==0){
            
            tempStr=@"ddddddddd";
            
        }else{
            
            tempStr=self.textField.text;
            
        }
        UIImage*tempImage=[QRCodeGenerator qrImageForString:tempStr imageSize:360 Topimg:image withColor:RandomColor];
        
        _outImageView.image=tempImage;
        
    }
    +(UIImage*)qrImageForString:(NSString *)string imageSize:(CGFloat)size Topimg:(UIImage *)topimg withColor:(UIColor*)color{
        
        if (![string length]) {
            return nil;
        }
        
        QRcode *code = QRcode_encodeString([string UTF8String], 0, QR_ECLEVEL_L, QR_MODE_8, 1);
        if (!code) {
            return nil;
        }
        
        // create context
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGContextRef ctx = CGBitmapContextCreate(0, size, size, 8, size * 4, colorSpace, kCGImageAlphaPremultipliedLast);
        
        CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(0, -size);
        CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1, -1);
        CGContextConcatCTM(ctx, CGAffineTransformConcat(translateTransform, scaleTransform));
        
        // draw QR on this context
        [QRCodeGenerator drawQRCode:code context:ctx size:size withPointType:0 withPositionType:0 withColor:color];
        
        // get image
        CGImageRef qrCGImage = CGBitmapContextCreateImage(ctx);
        UIImage * qrImage = [UIImage imageWithCGImage:qrCGImage];
        
        if(topimg)
        {
            UIGraphicsBeginImageContext(qrImage.size);
            
            //Draw image2
            [qrImage drawInRect:CGRectMake(0, 0, qrImage.size.width, qrImage.size.height)];
            
            //Draw image1
            float r=qrImage.size.width*35/240;
            [topimg drawInRect:CGRectMake((qrImage.size.width-r)/2, (qrImage.size.height-r)/2 ,r, r)];
    
            qrImage=UIGraphicsGetImageFromCurrentImageContext();
            
            UIGraphicsEndImageContext();
        }
    
        // some releases
        CGContextRelease(ctx);
        CGImageRelease(qrCGImage);
        CGColorSpaceRelease(colorSpace);
        QRcode_free(code);
        
        return qrImage;
          
    }
    + (void)drawQRCode:(QRcode *)code context:(CGContextRef)ctx size:(CGFloat)size withPointType:(QRPointType)pointType withPositionType:(QRPositionType)positionType withColor:(UIColor *)color {
      unsigned char *data = 0;
      int width;
      data = code->data;
      width = code->width;
      float zoom = (double)size / (code->width + 2.0 * qr_margin);
      CGRect rectDraw = CGRectMake(0, 0, zoom, zoom);
        
      // draw
        const CGFloat *components;
        if (color) {
            components = CGColorGetComponents(color.CGColor);
        }else {
            components = CGColorGetComponents([UIColor blackColor].CGColor);
        }
        CGContextSetRGBFillColor(ctx, components[0], components[1], components[2], 1.0);
        NSLog(@"aad :%f  bbd :%f   ccd:%f",components[0],components[1],components[2]);
     
      for(int i = 0; i < width; ++i) {
        for(int j = 0; j < width; ++j) {
          if(*data & 1) {
            rectDraw.origin = CGPointMake((j + qr_margin) * zoom,(i + qr_margin) * zoom);
                    if (positionType == QRPositionNormal) {
                        switch (pointType) {
                            case QRPointRect:
                                CGContextAddRect(ctx, rectDraw);
                                break;
                            case QRPointRound:
                                CGContextAddEllipseInRect(ctx, rectDraw);
                                break;
                            default:
                                break;
                        }
                    }else if(positionType == QRPositionRound) {
                        switch (pointType) {
                            case QRPointRect:
                                CGContextAddRect(ctx, rectDraw);
                                break;
                            case QRPointRound:
                                if ((i>=0 && i<=6 && j>=0 && j<=6) || (i>=0 && i<=6 && j>=width-7-1 && j<=width-1) || (i>=width-7-1 && i<=width-1 && j>=0 && j<=6)) {
                                    CGContextAddRect(ctx, rectDraw);
                                }else {
                                    CGContextAddEllipseInRect(ctx, rectDraw);
                                }
                                break;
                            default:
                                break;
                        }
                    }
          }
          ++data;
        }
      }
      CGContextFillPath(ctx);
    }
    

    在textField输入,生成下图

    长按二维码识别

    这个功能有很多的地方在用, 最让人熟知的我想便是微信了,其实实现方法还是很简单的。

     #pragma mark-> 长按识别二维码
    -(void)dealLongPress:(UIGestureRecognizer*)gesture{
        
        if(gesture.state==UIGestureRecognizerStateBegan){
            
            _timer.fireDate=[NSDate distantFuture];
            
            UIImageView*tempImageView=(UIImageView*)gesture.view;
            if(tempImageView.image){
                //1. 初始化扫描仪,设置设别类型和识别质量
                CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
                //2. 扫描获取的特征组
                NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:tempImageView.image.CGImage]];
                //3. 获取扫描结果
                CIQRCodeFeature *feature = [features objectAtIndex:0];
                NSString *scannedResult = feature.messageString;
                UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"扫描结果" message:scannedResult delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alertView show];
            }else {
                
                UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"扫描结果" message:@"您还没有生成二维码" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alertView show];
            }
            
            
        }else if (gesture.state==UIGestureRecognizerStateEnded){
            
            
            _timer.fireDate=[NSDate distantPast];
        }
        
        
    }
    

    我们用刚才生成的二维码进行长按识别,效果如下

    结语

    本文demo下载地址请点这里 Demo ,

    转自 mokey1422 所写的仿支付宝二维码。

    系统原生的二维码扫描扫描识别速度,要比第三方好用得多,在没有特殊原因的情况下,比如7.0系统以下,我希望大家都能用系统原生的方法。

    文章若有问题请给予指正,感谢。

    展开全文
  • 功能:[修正版]修改ReportBuilder支持QRCode二维码 注: 1、DelphiZXIngQRCode.pas 为用到的二维码生成源码,来源https://github.com/foxitsoftware/DelphiZXingQRCode,版权由原作者所有 2、rbRCL106.bpl 为已经...
  • C# VS2017+EmguCV4.2 QRcode 二维码 检测,定位,标记,识别,划线标记支持任何角度二维码
  • QRCode - 二维码识别与生成

    千次阅读 2016-10-22 00:31:39
    有关二维码的介绍,我这里不做过多说明, 可以直接去基维百科查看,附上链接QR code(https://en.wikipedia.org/wiki/QR_code). IOS7之前,开发者进行扫码编程时,一般会借助第三方库。常用的是ZBar

    来源:Yi'mouleng(@丶伊眸冷)   

    链接:http://t.cn/R40WxcM


    前言


    有关二维码的介绍,我这里不做过多说明, 可以直接去基维百科查看,附上链接QR code(https://en.wikipedia.org/wiki/QR_code).

    IOS7之前,开发者进行扫码编程时,一般会借助第三方库。常用的是ZBarSDKa和ZXingObjC,IOS7之后,系统的AVMetadataObject类中,为我们提供了解析二维码的接口。经过测试,使用原生API扫描和处理的效率非常高,远远高于第三方库。


    扫描


    官方提供的接口非常简单,直接看代码,主要使用的是AVFoundation。


    @interface ViewController ()AVCaptureMetadataOutputObjectsDelegate>//用于处理采集信息的代理

    {

        AVCaptureSession * session;//输入输出的中间桥梁

    }

    @end

    @implementation ViewController

    - (void)viewDidLoad {

        [super viewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

        //获取摄像设备

        AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

        //创建输入流

        AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];

        if (!input) return;

        //创建输出流

        AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];

        //设置代理 在主线程里刷新

        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

        //设置有效扫描区域

        CGRect scanCrop=[self getScanCrop:_scanWindow.bounds readerViewBounds:self.view.frame];

         output.rectOfInterest = scanCrop;

        //初始化链接对象

        _session = [[AVCaptureSession alloc]init];

        //高质量采集率

        [_session setSessionPreset:AVCaptureSessionPresetHigh];

        

        [_session addInput:input];

        [_session addOutput:output];

        //设置扫码支持的编码格式(如下设置条形码和二维码兼容)

        output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];

        

        AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];

        layer.videoGravity=AVLayerVideoGravityResizeAspectFill;

        layer.frame=self.view.layer.bounds;

        [self.view.layer insertSublayer:layer atIndex:0];

        //开始捕获

        [_session startRunning];

    }

     

    -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{

        if (metadataObjects.count>0) {

            //[session stopRunning];

            AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];

            //输出扫描字符串

            NSLog(@"%@",metadataObject.stringValue);

        }

    }


    一些初始化的代码加上实现代理方法便完成了二维码扫描的工作,这里我们需要注意的是, 在二维码扫描的时候, 我们一般都会在屏幕中间放一个方框,用来显示二维码扫描的大小区间,这里我们在个AVCaptureMetadataOutput类中有一个rectOfInterest属性,它的作用就是设置扫描范围。


    这个CGRect参数和普通的Rect范围不太一样,它的四个值的范围都是0-1,表示比例。
    rectOfInterest都是按照横屏来计算的 所以当竖屏的情况下 x轴和y轴要交换一下。
    宽度和高度设置的情况也是类似。


    我们在上面设置有效扫描区域的方法如下


    #pragma mark-> 获取扫描区域的比例关系

    -(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)readerViewBounds

    {

        

        CGFloat x,y,width,height;

        

        x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds);

        y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds);

        width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds);

        height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds);

        

        return CGRectMake(x, y, width, height);

        

    }


    读取


    读取主要用到CoreImage 不过要强调的是读取二维码的功能只有在iOS8之后才支持,我们需要在相册中调用一个二维码,将其读取,代码如下


    #pragma mark-> 我的相册

    -(void)myAlbum{

        

        NSLog(@"我的相册");

        if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){

            //1.初始化相册拾取器

            UIImagePickerController *controller = [[UIImagePickerController alloc] init];

            //2.设置代理

            controller.delegate = self;

            //3.设置资源:

            /**

             UIImagePickerControllerSourceTypePhotoLibrary,相册

             UIImagePickerControllerSourceTypeCamera,相机

             UIImagePickerControllerSourceTypeSavedPhotosAlbum,照片库

             */

            controller.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;

            //4.随便给他一个转场动画

            controller.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;

            [self presentViewController:controller animated:YES completion:NULL];

            

        }else{

            

            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"设备不支持访问相册,请在设置->隐私->照片中进行设置!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];

            [alert show];

        }

        

    }


    完成相册代理, 我们在代理中添加读取二维码方法


    #pragma mark-> imagePickerController delegate

    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

    {

        //1.获取选择的图片

        UIImage *image = info[UIImagePickerControllerOriginalImage];

        //2.初始化一个监测器

        CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];

        

        [picker dismissViewControllerAnimated:YES completion:^{

            //监测到的结果数组

            NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];

            if (features.count >=1) {

                /**结果对象 */

                CIQRCodeFeature *feature = [features objectAtIndex:0];

                NSString *scannedResult = feature.messageString;

                UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"扫描结果" message:scannedResult delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];

                [alertView show];

              

            }

            else{

                UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"该图片没有包含一个二维码!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];

                [alertView show];

                

            }

            

      

        }];

        

        

    }


    因为没用真机,所以这里没有给出太多的截图, 用模拟器读取自带图片,结果如下



    生成


    生成二维码,其实也是用到CoreImage,但是步骤繁琐一些,代码如下


    #pragma mark-> 二维码生成

    -(void)create{

        

        UIImage *image=[UIImage imageNamed:@"6824500_006_thumb.jpg"];

        NSString*tempStr;

        if(self.textField.text.length==0){

            

            tempStr=@"ddddddddd";

            

        }else{

            

            tempStr=self.textField.text;

            

        }

        UIImage*tempImage=[QRCodeGenerator qrImageForString:tempStr imageSize:360 Topimg:image withColor:RandomColor];

        

        _outImageView.image=tempImage;

        

    }

    +(UIImage*)qrImageForString:(NSString *)string imageSize:(CGFloat)size Topimg:(UIImage *)topimg withColor:(UIColor*)color{

        

        if (![string length]) {

            return nil;

        }

        

        QRcode *code = QRcode_encodeString([string UTF8String], 0, QR_ECLEVEL_L, QR_MODE_8, 1);

        if (!code) {

            return nil;

        }

        

        // create context

        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

        CGContextRef ctx = CGBitmapContextCreate(0, size, size, 8, size * 4, colorSpace, kCGImageAlphaPremultipliedLast);

        

        CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(0, -size);

        CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1, -1);

        CGContextConcatCTM(ctx, CGAffineTransformConcat(translateTransform, scaleTransform));

        

        // draw QR on this context

        [QRCodeGenerator drawQRCode:code context:ctx size:size withPointType:0 withPositionType:0 withColor:color];

        

        // get image

        CGImageRef qrCGImage = CGBitmapContextCreateImage(ctx);

        UIImage * qrImage = [UIImage imageWithCGImage:qrCGImage];

        

        if(topimg)

        {

            UIGraphicsBeginImageContext(qrImage.size);

            

            //Draw image2

            [qrImage drawInRect:CGRectMake(0, 0, qrImage.size.width, qrImage.size.height)];

            

            //Draw image1

            float r=qrImage.size.width*35/240;

            [topimg drawInRect:CGRectMake((qrImage.size.width-r)/2, (qrImage.size.height-r)/2 ,r, r)];

     

            qrImage=UIGraphicsGetImageFromCurrentImageContext();

            

            UIGraphicsEndImageContext();

        }

     

        // some releases

        CGContextRelease(ctx);

        CGImageRelease(qrCGImage);

        CGColorSpaceRelease(colorSpace);

        QRcode_free(code);

        

        return qrImage;

          

    }

    + (void)drawQRCode:(QRcode *)code context:(CGContextRef)ctx size:(CGFloat)size withPointType:(QRPointType)pointType withPositionType:(QRPositionType)positionType withColor:(UIColor *)color {

    unsigned char *data = 0;

    int width;

    data = code->data;

    width = code->width;

    float zoom = (double)size / (code->width + 2.0 * qr_margin);

    CGRect rectDraw = CGRectMake(0, 0, zoom, zoom);

        

    // draw

        const CGFloat *components;

        if (color) {

            components = CGColorGetComponents(color.CGColor);

        }else {

            components = CGColorGetComponents([UIColor blackColor].CGColor);

        }

        CGContextSetRGBFillColor(ctx, components[0], components[1], components[2], 1.0);

        NSLog(@"aad :%f  bbd :%f   ccd:%f",components[0],components[1],components[2]);

    for(int i = 0; i

    for(int j = 0; j

    if(*data & 1) {

    rectDraw.origin = CGPointMake((j + qr_margin) * zoom,(i + qr_margin) * zoom);

                    if (positionType == QRPositionNormal) {

                        switch (pointType) {

                            case QRPointRect:

                                CGContextAddRect(ctx, rectDraw);

                                break;

                            case QRPointRound:

                                CGContextAddEllipseInRect(ctx, rectDraw);

                                break;

                            default:

                                break;

                        }

                    }else if(positionType == QRPositionRound) {

                        switch (pointType) {

                            case QRPointRect:

                                CGContextAddRect(ctx, rectDraw);

                                break;

                            case QRPointRound:

                                if ((i>=0 && i6 && j>=0 && j6) || (i>=0 && i6 && j>=width-7-1 && j-1) || (i>=width-7-1 && i-1 && j>=0 && j6)) {

                                    CGContextAddRect(ctx, rectDraw);

                                }else {

                                    CGContextAddEllipseInRect(ctx, rectDraw);

                                }

                                break;

                            default:

                                break;

                        }

                    }

    }

    ++data;

    }

    }

    CGContextFillPath(ctx);

    }


    在textField输入,生成下图



    长按二维码识别


    这个功能有很多的地方在用, 最让人熟知的我想便是微信了,其实实现方法还是很简单的。



    我们用刚才生成的二维码进行长按识别,效果如下



    结语


    本文demo:https://github.com/yimouleng/GBAliScan


    转自mokey1422所写的仿支付宝二维码。


    系统原生的二维码扫描扫描识别速度,要比第三方好用得多,在没有特殊原因的情况下,比如7.0系统以下,我希望大家都能用系统原生的方法。


    文章若有问题请给予指正,感谢。

    展开全文
  • 隐藏在QRCode二维码背后的秘密

    万次阅读 2013-04-28 17:19:06
    隐藏在QRCode二维码背后的秘密,您知道吗?1、容错级。二维码的容错级分别为:L,M,Q和H。其中,L最低,H最高。如何从二维码中一眼看出其容错级别呢?看下图:图1 容错级示例如上图所示,关键部分已用红色框框起来...
  • Java生成QRcode二维码

    2020-01-02 10:46:14
    QR code优点:识别速度快、数据密度大、占用空间小 生成二维码的办法: 借助第三方jar:zxing(谷歌研发)和QRcode.jar JavaScript,jQuery.qrcode.js 生成:http://www.swetake .com/qrcode/index-e.ht...
  • 很多公司为商业宣传之需,常将企业LOGO加入二维码中,但如果LOGO遮挡区域足够地大,二维码就变得无法识别。那么,有没有一种办法将上述区域预先“抠空”出来(以便专门放置LOGO),而其他区域则专门来放置二维码的...
  • qrcode二维码生成/解析

    2013-03-23 09:27:45
    开源的二维码生成/解析包有google的zxing和qrcode,之前用zxing写的二维码生成方法生成的二维码用手机无法识别,昨天用qrcode开源包写个了简单的二维码生成方法,生成的二维码可以用手机扫描识别。 package ...
  • 提要:很多公司为商业宣传之需,常将企业LOGO加入二维码中,但如果LOGO遮挡区域足够地大,二维码就变得无法识别。那么,有没有一种办法将上述区域预先“抠空”出来(以便专门放置LOGO),而其他区域则专门来放置...
  • iOS开发-QRCode-二维码识别与生成

    千次阅读 2016-06-01 19:43:57
    有关二维码的介绍,我这里不做过多说明, 可以直接去基维百科查看,附上链接 QR code .  IOS7之前,开发者进行扫码编程时,一般会借助第三方库。常用的是 ZBarSDKa 和 ZXingObjC ,IOS7之后,系统的...
  • QRcode 二维码中插入图像分析

    千次阅读 2013-01-20 20:16:08
    本文为翻译文章,英文原文请看这里[link],文中的QRcode中插入图片方法并非简单的利用容错,可以在保证识别正确率的同时加入非常大块的图像,文字等。正文如下———— QRcode是一种用来对字节符号进行编码的二维码...
  • Unity 基础 之 ZXing QRCode 二维码的生成和识别(可设置生成不同颜色的/带图标的二维码) 目录 Unity 基础 之 ZXing QRCode 二维码的生成和识别(可设置生成不同颜色的/带图标的二维码) 一、简单介绍 二、...

空空如也

1 2 3 4 5 ... 20
收藏数 15,213
精华内容 6,085
关键字:

qrcode