二维码识别_二维码识别matlab - CSDN
精华内容
参与话题
  • Python二维码应用(一)QRcode二维码生成&识别

    万次阅读 多人点赞 2019-01-25 14:24:26
    基于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()
    

    大功告成!

    展开全文
  • 二维码的特征定位和信息识别

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

    二维码的特征定位和信息识别

    背景介绍

    视觉的方法可以用来估计位置和姿态。最容易想到的是在目标上布置多个容易识别的特征,这样使用opencv相机标定和、相机畸变矫正、轮廓提取、solvepnp来获取目标相对于相机的位姿。在实际使用中只要相机和目标一方是估计的,那就可以得到全局坐标。如果相机和靶标都在移动,那只能获取到相对坐标。但是受限于相机视角和景深,这样多个特征的识别虽然精度可以很高,但是范围却很小。

    对于如何扩大范围,使用二维码是一个很好的思路。首先,二维码本身具有多个特征,单个二维码可以用来实现上述方法的功能。其次,二维码本身带有信息,如果二维码的布置事先已知,那么位置和姿态估计的范围将只受限于二维码的数量。

    本文主要是二维码的特征识别和信息识别。

    二维码的的生成

    二维码是在一个网站上生成的,经过手机的测试,生成的二维码没有问题。http://www.liantu.com/,该网站是免费的,生成的图片及二维码各种参数可以自定义。
    本文的测试图片有20张,是数字1到5,每个数字隔90度旋转各一张。
    这里写图片描述

    二维码的特征识别

    二维码特征识别的思路是:第一步,寻找二维码的三个角的定位角点,需要对图片进行平滑滤波,二值化,寻找轮廓,筛选轮廓中有两个子轮廓的特征,从筛选后的轮廓中找到面积最接近的3个即是二维码的定位角点。第二步:判断3个角点处于什么位置,主要用来对图片进行透视校正(相机拍到的图片)或者仿射校正(对网站上生成的图片进行缩放拉伸旋转等操作后得到的图片)。需要判断三个角点围成的三角形的最大的角就是二维码左上角的点。然后根据这个角的两个边的角度差确定另外两个角点的左下和右上位置。第三步,根据这些特征识别二维码的范围。
    具体的代码:

            Mat src = imread( "pic\\456.jpg", 1 );
            if(src.empty())  
            {  
                fprintf(stderr, "Can not load image!\n");  
                return 0;  
            }  
    
            Mat src_all=src.clone();  
    
            //彩色图转灰度图  
            Mat src_gray;
            cvtColor( src, src_gray, CV_BGR2GRAY );  
    
            //对图像进行平滑处理  
            blur( src_gray, src_gray, Size(3,3) );  
    
            //使灰度图象直方图均衡化  
            equalizeHist( src_gray, src_gray );  
    
            namedWindow("src_gray");  
            imshow("src_gray",src_gray);         //灰度图
    
            //指定112阀值进行二值化
            Mat threshold_output;
            threshold( src_gray, threshold_output, 112, 255, THRESH_BINARY ); 
    
    #ifdef DEBUG
            namedWindow("二值化后输出");  
            imshow("二值化后输出",threshold_output);   //二值化后输出
    #endif
    
            //需要的变量定义
            Scalar color = Scalar(1,1,255 );  
            vector<vector<Point>> contours,contours2;  
            vector<Vec4i> hierarchy;  
            Mat drawing = Mat::zeros( src.size(), CV_8UC3 );  
            //Mat drawing2 = Mat::zeros( src.size(), CV_8UC3 );  
            Mat drawingAllContours = Mat::zeros( src.size(), CV_8UC3 ); 
    
            //利用二值化输出寻找轮廓
            findContours(threshold_output, contours, hierarchy,  CV_RETR_TREE, CHAIN_APPROX_NONE, Point(0, 0) );  
    
            //寻找轮廓的方法
            int tempindex1 = 0;
            int tempindex2 = 0;
    
            for(int i = 0;i<contours.size();i++)
            {
                if(hierarchy[i][2] == -1)
                    continue;
                else
                    tempindex1 = hierarchy[i][2];                //第一个子轮廓的索引
    
                if(hierarchy[tempindex1][2] == -1)
                    continue;
                else
                {
                    tempindex2 = hierarchy[tempindex1][2];        //第二个子轮廓的索引
                    //记录搜索到的有两个子轮廓的轮廓并把他们的编号存储
                    in.a1 = i;
                    in.a2 = tempindex1;
                    in.a3 = tempindex2;
                    vin.push_back(in);
                }
            }
    
            //按面积比例搜索
            vector<index>::iterator it;
            for(it = vin.begin();it != vin.end();)
            {
                vector<Point> out1Contours = contours[it->a1];
                vector<Point> out2Contours = contours[it->a2];
                double lenth1 = arcLength(out1Contours,1);
                double lenth2 = arcLength(out2Contours,1);
                if(abs(lenth1/lenth2-2)>1)
                {
                    it = vin.erase(it);
                }
                else
                {
                    drawContours( drawing, contours, it->a1,  CV_RGB(255,255,255) , CV_FILLED, 8); 
                    it++;
                }
            }
    
            //获取三个定位角的中心坐标  
            Point point[3];
            int i = 0;
            vector<Point> pointthree;
            for(it = vin.begin(),i = 0;it != vin.end();i++,it++)
            {
                point[i] = Center_cal( contours, it->a1 );
                pointthree.push_back(point[i]);
            }
    
            if(pointthree.size() <3)
            {
                cout << "找到的定位角点不足3个"<<endl;
                return 0;  
            }
    
            //计算轮廓的面积,计算定位角的面积,从而计算出边长
            double area = contourArea(contours[vin[0].a1]);
            int area_side = cvRound (sqrt (double(area)));  
            for(int i=0; i<3; i++)  
            {  
                //画出三个定位角的中心连线  
                line(drawing,point[i%3],point[(i+1)%3],color,area_side/10,8);  
            }  
    
            //清除找到的3个点,以便处理下一幅图片使用
            vin.clear();
    
            //由3个定位角校正图片
            //=========================================
            //找到角度最大的点
            double ca[2];
            double cb[2];
    
            ca[0] =  pointthree[1].x - pointthree[0].x;
            ca[1] =  pointthree[1].y - pointthree[0].y;
            cb[0] =  pointthree[2].x - pointthree[0].x;
            cb[1] =  pointthree[2].y - pointthree[0].y;
            double angle1 = 180/3.1415*acos((ca[0]*cb[0]+ca[1]*cb[1])/(sqrt(ca[0]*ca[0]+ca[1]*ca[1])*sqrt(cb[0]*cb[0]+cb[1]*cb[1])));
            double ccw1;
            if(ca[0]*cb[1] - ca[1]*cb[0] > 0) ccw1 = 0;
            else ccw1 = 1;
    
            ca[0] =  pointthree[0].x - pointthree[1].x;
            ca[1] =  pointthree[0].y - pointthree[1].y;
            cb[0] =  pointthree[2].x - pointthree[1].x;
            cb[1] =  pointthree[2].y - pointthree[1].y;
            double angle2 = 180/3.1415*acos((ca[0]*cb[0]+ca[1]*cb[1])/(sqrt(ca[0]*ca[0]+ca[1]*ca[1])*sqrt(cb[0]*cb[0]+cb[1]*cb[1])));
            double ccw2;
            if(ca[0]*cb[1] - ca[1]*cb[0] > 0) ccw2 = 0;
            else ccw2 = 1;
    
            ca[0] =  pointthree[1].x - pointthree[2].x;
            ca[1] =  pointthree[1].y - pointthree[2].y;
            cb[0] =  pointthree[0].x - pointthree[2].x;
            cb[1] =  pointthree[0].y - pointthree[2].y;
            double angle3 = 180/3.1415*acos((ca[0]*cb[0]+ca[1]*cb[1])/(sqrt(ca[0]*ca[0]+ca[1]*ca[1])*sqrt(cb[0]*cb[0]+cb[1]*cb[1])));
            double ccw3;
            if(ca[0]*cb[1] - ca[1]*cb[0] > 0) ccw3 = 0;
            else ccw3 = 1;
    
            CvPoint2D32f poly[4];
            if(angle3>angle2 && angle3>angle1)
            {
                if(ccw3)
                {
                    poly[1] = pointthree[1];
                    poly[3] = pointthree[0];
                }
                else
                {
                    poly[1] = pointthree[0];
                    poly[3] = pointthree[1];
                }
                poly[0] = pointthree[2];
                Point temp(pointthree[0].x + pointthree[1].x - pointthree[2].x , pointthree[0].y + pointthree[1].y - pointthree[2].y );
                poly[2] = temp;
            }
            else if(angle2>angle1 && angle2>angle3)
            {
                if(ccw2)
                {
                    poly[1] = pointthree[0];
                    poly[3] = pointthree[2];
                }
                else
                {
                    poly[1] = pointthree[2];
                    poly[3] = pointthree[0];
                }
                poly[0] = pointthree[1];
                Point temp(pointthree[0].x + pointthree[2].x - pointthree[1].x , pointthree[0].y + pointthree[2].y - pointthree[1].y );
                poly[2] = temp;
            }
            else if(angle1>angle2 && angle1 > angle3)
            {
                if(ccw1)
                {
                    poly[1] = pointthree[1];
                    poly[3] = pointthree[2];
                }
                else
                {
                    poly[1] = pointthree[2];
                    poly[3] = pointthree[1];
                }
                poly[0] = pointthree[0];
                Point temp(pointthree[1].x + pointthree[2].x - pointthree[0].x , pointthree[1].y + pointthree[2].y - pointthree[0].y );
                poly[2] = temp;
            }
    
            CvPoint2D32f trans[4];
            int temp = 50;
            trans[0] = Point2f(0+temp,0+temp);  
            trans[1] = Point2f(0+temp,100+temp);  
            trans[2] = Point2f(100+temp,100+temp);  
            trans[3] = Point2f(100+temp,0+temp);
    
            //获取透视投影变换矩阵
            CvMat *warp_mat = cvCreateMat(3, 3, CV_32FC1);
            cvGetPerspectiveTransform(poly, trans, warp_mat);
    
            //计算变换结果
            IplImage ipl_img(src_all);
            IplImage *dst = cvCreateImage(cvSize(1000, 1000), 8, 3);
            cvWarpPerspective(&ipl_img,dst,warp_mat);
            //=========================================
    
    #ifdef DEBUG
            namedWindow("透视变换后的图");  
            cvShowImage("透视变换后的图",dst);         //透视变换后的图
    
            drawContours( drawingAllContours, contours, -1,  CV_RGB(255,255,255) , 1, 8);
            namedWindow("DrawingAllContours");  
            imshow( "DrawingAllContours", drawingAllContours );  
    
            namedWindow(pathtemp);  
            imshow(pathtemp , drawing );    //3个角点填充
    #endif
    
            //接下来要框出这整个二维码  
            Mat gray_all,threshold_output_all;  
            vector<vector<Point> > contours_all;  
            vector<Vec4i> hierarchy_all;  
            cvtColor( drawing, gray_all, CV_BGR2GRAY );  
    
            threshold( gray_all, threshold_output_all, 45, 255, THRESH_BINARY ); 
    
            findContours( threshold_output_all, contours_all, hierarchy_all,  RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0) );//RETR_EXTERNAL表示只寻找最外层轮廓  
    
            Point2f fourPoint2f[4];  
            //求最小包围矩形  
            RotatedRect rectPoint = minAreaRect(contours_all[0]);  
    
            //将rectPoint变量中存储的坐标值放到 fourPoint的数组中  
            rectPoint.points(fourPoint2f);  
            for (int i = 0; i < 4; i++)  
            {  
                line(src_all, fourPoint2f[i%4], fourPoint2f[(i + 1)%4],
                    Scalar(20,21,237), 3);  
            }  
    
            namedWindow(pathtemp);  
            imshow(pathtemp , src_all ); 
    
            //截取二维码区域
            CvSize size= cvSize(200,200);//区域大小
            cvSetImageROI(dst,cvRect(0,0,size.width, size.height));//设置源图像ROI
            IplImage* pDest = cvCreateImage(size,dst->depth,dst->nChannels);//创建目标图像
            cvCopy(dst,pDest); //复制图像
            cvSaveImage("Roi.jpg",pDest);//保存目标图像

    二维码的信息识别

    二维码的信息识别使用的是zbar,一个开源的二维码识别库,经过测试,对图像进行平滑,灰度等处理后识别效率还是很高的。zbar的算法流程简介:http://blog.csdn.net/u013738531/article/details/54574262

            //对截取后的区域进行解码
            Mat imageSource = cv::Mat(pDest); 
            cvResetImageROI(pDest);//源图像用完后,清空ROI
            cvtColor( imageSource, imageSource, CV_BGR2GRAY );  //zbar需要输入灰度图像才能很好的识别
    
            //Zbar二维码识别
            ImageScanner scanner;
            scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);   
            int width1 = imageSource.cols;        
            int height1 = imageSource.rows;        
            uchar *raw = (uchar *)imageSource.data;    
    
            Image imageZbar(width1, height1, "Y800", raw, width1 * height1);          
            scanner.scan(imageZbar); //扫描条码      
            Image::SymbolIterator symbol = imageZbar.symbol_begin();    
            if(imageZbar.symbol_begin()==imageZbar.symbol_end())    
            {    
                cout<<"查询条码失败,请检查图片!"<<endl;    
            }    
    
            for(;symbol != imageZbar.symbol_end();++symbol)      
            {        
                cout<<"类型:"<<endl<<symbol->get_type_name()<<endl;      
                cout<<"条码:"<<endl<<symbol->get_data()<<endl;         
            }
    
            imageZbar.set_data(NULL,0);    

    程序运行结果

    运行结果1:网站上生成的二维码,依次是原图,二值化,角点定位,旋转矫正,识别结果。
    这里写图片描述

    运行结果2:相机拍摄的名片上二维码,依次是灰度图,二值化,角点定位,透视矫正,识别结果。

    这里写图片描述
    本文程序中一些代码参考以下博客:
    http://blog.csdn.net/nick123chao/article/details/77573675
    http://blog.csdn.net/u010925447/article/details/77996455

    本文用到的的程序和图片素材在csdn资源下载区,下载链接稍后会在评论区发布。

    展开全文
  • 二维码识别算法

    热门讨论 2020-07-29 23:06:17
    针对解码识别过程,详细分析了基于图像处理的预处理方法,包括二维码灰度化处理、图像平滑和二值化过程,同时针对二维码实际情况,设计了基于Canny和Hough变换的二维码旋转校正算法,几何形变校正算法,并通过QR...
  • opencv二维码识别解码

    万次阅读 2017-08-25 15:17:38
    使用opencv库识别QR二维码,框出图片中的二维码,并使用开源库Zxing解码,在这过程中学习理解opencv库相应的函数。 环境: 1. window7系统  2. QT create 1.准备 首先安装QT和QT create开发环境,window下使用...

    目的:

    使用opencv库识别QR二维码,框出图片中的二维码,并使用开源库Zxing解码,在这过程中学习理解opencv库相应的函数。

    环境:

    1. window7系统

          2. QT create

    1.准备

    首先安装QT和QT create开发环境,window下使用cmake编译opencv生产lib库。这部分内容网上很多资料,直接搜索安装就行。

    2.工程代码

    QT create配置使用opencv库。在工程的pro文件下面添加指定opencv库的头文件和lib的路径。如下:
    INCLUDEPATH+=C:\Qt\opencv\include\opencv\
                 C:\Qt\opencv\include\opencv2\
                 C:\Qt\opencv\include
    
    LIBS+=C:\Qt\opencv\lib\libopencv_calib3d320.dll.a\
          C:\Qt\opencv\lib\libopencv_core320.dll.a\
          C:\Qt\opencv\lib\libopencv_features2d320.dll.a\
          C:\Qt\opencv\lib\libopencv_flann320.dll.a\
          C:\Qt\opencv\lib\libopencv_highgui320.dll.a\
          C:\Qt\opencv\lib\libopencv_imgcodecs320.dll.a\
          C:\Qt\opencv\lib\libopencv_imgproc320.dll.a\
          C:\Qt\opencv\lib\libopencv_ml320.dll.a\
          C:\Qt\opencv\lib\libopencv_objdetect320.dll.a\
          C:\Qt\opencv\lib\libopencv_photo320.dll.a\
          C:\Qt\opencv\lib\libopencv_shape320.dll.a\
          C:\Qt\opencv\lib\libopencv_stitching320.dll.a\
          C:\Qt\opencv\lib\libopencv_superres320.dll.a\
          C:\Qt\opencv\lib\libopencv_video320.dll.a\
          C:\Qt\opencv\lib\libopencv_videoio320.dll.a\
          C:\Qt\opencv\lib\libopencv_videostab320.dll.a

    opencv识别定位二维码的代码如下:
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    #include <QDebug>
    
    using namespace cv;
    using namespace std;
    
    
    Mat src; Mat src_gray;
    
    
    RNG rng(12345);
    //Scalar colorful = CV_RGB(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
    
    //获取轮廓的中心点
    Point Center_cal(vector<vector<Point> > contours,int i)
    {
          int centerx=0,centery=0,n=contours[i].size();
          //在提取的小正方形的边界上每隔周长个像素提取一个点的坐标,
          //求所提取四个点的平均坐标(即为小正方形的大致中心)
          centerx = (contours[i][n/4].x + contours[i][n*2/4].x + contours[i][3*n/4].x + contours[i][n-1].x)/4;
          centery = (contours[i][n/4].y + contours[i][n*2/4].y + contours[i][3*n/4].y + contours[i][n-1].y)/4;
          Point point1=Point(centerx,centery);
          return point1;
    }
    
    
    int main( int argc, char** argv[] )
    {
        src = imread( "core.jpg", 1 );
        Mat src_all=src.clone();
    
    
        //彩色图转灰度图
        cvtColor( src, src_gray, CV_BGR2GRAY );
        //对图像进行平滑处理
        blur( src_gray, src_gray, Size(3,3) );
        //使灰度图象直方图均衡化
        equalizeHist( src_gray, src_gray );
        namedWindow("src_gray");
        imshow("src_gray",src_gray);
    
    
        Scalar color = Scalar(1,1,255 );
        Mat threshold_output;
        vector<vector<Point> > contours,contours2;
        vector<Vec4i> hierarchy;
        Mat drawing = Mat::zeros( src.size(), CV_8UC3 );
        Mat drawing2 = Mat::zeros( src.size(), CV_8UC3 );
        Mat drawingAllContours = Mat::zeros( src.size(), CV_8UC3 );
    
        //指定112阀值进行二值化
        threshold( src_gray, threshold_output, 112, 255, THRESH_BINARY );
    
        namedWindow("Threshold_output");
        imshow("Threshold_output",threshold_output);
    
    
        /*查找轮廓
         *  参数说明
            输入图像image必须为一个2值单通道图像
            contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示
            hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],
                分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。
            mode表示轮廓的检索模式
                CV_RETR_EXTERNAL 表示只检测外轮廓
                CV_RETR_LIST 检测的轮廓不建立等级关系
                CV_RETR_CCOMP 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
                CV_RETR_TREE 建立一个等级树结构的轮廓。具体参考contours.c这个demo
            method为轮廓的近似办法
                CV_CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
                CV_CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
                CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法
            offset表示代表轮廓点的偏移量,可以设置为任意值。对ROI图像中找出的轮廓,并要在整个图像中进行分析时,这个参数还是很有用的。
         */
        findContours( threshold_output, contours, hierarchy,  CV_RETR_TREE, CHAIN_APPROX_NONE, Point(0, 0) );
    
        int c=0,ic=0,k=0,area=0;
    
        //通过黑色定位角作为父轮廓,有两个子轮廓的特点,筛选出三个定位角
        int parentIdx=-1;
        for( int i = 0; i< contours.size(); i++ )
        {
            //画出所以轮廓图
            drawContours( drawingAllContours, contours, parentIdx,  CV_RGB(255,255,255) , 1, 8);
            if (hierarchy[i][2] != -1 && ic==0)
            {
                parentIdx = i;
                ic++;
            }
            else if (hierarchy[i][2] != -1)
            {
                ic++;
            }
            else if(hierarchy[i][2] == -1)
            {
                ic = 0;
                parentIdx = -1;
            }
    
            //有两个子轮廓
            if ( ic >= 2)
            {
                //保存找到的三个黑色定位角
                contours2.push_back(contours[parentIdx]);
                //画出三个黑色定位角的轮廓
                drawContours( drawing, contours, parentIdx,  CV_RGB(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)) , 1, 8);
                ic = 0;
                parentIdx = -1;
            }
        }
    
        //填充的方式画出三个黑色定位角的轮廓
        for(int i=0; i<contours2.size(); i++)
            drawContours( drawing2, contours2, i,  CV_RGB(rng.uniform(100,255),rng.uniform(100,255),rng.uniform(100,255)) , -1, 4, hierarchy[k][2], 0, Point() );
    
        //获取三个定位角的中心坐标
        Point point[3];
        for(int i=0; i<contours2.size(); i++)
        {
            point[i] = Center_cal( contours2, i );
        }
    
        //计算轮廓的面积,计算定位角的面积,从而计算出边长
        area = contourArea(contours2[1]);
        int area_side = cvRound (sqrt (double(area)));
        for(int i=0; i<contours2.size(); i++)
        {
            //画出三个定位角的中心连线
            line(drawing2,point[i%contours2.size()],point[(i+1)%contours2.size()],color,area_side/2,8);
        }
    
        namedWindow("DrawingAllContours");
        imshow( "DrawingAllContours", drawingAllContours );
    
        namedWindow("Drawing2");
        imshow( "Drawing2", drawing2 );
    
        namedWindow("Drawing");
        imshow( "Drawing", drawing );
    
    
        //接下来要框出这整个二维码
        Mat gray_all,threshold_output_all;
        vector<vector<Point> > contours_all;
        vector<Vec4i> hierarchy_all;
        cvtColor( drawing2, gray_all, CV_BGR2GRAY );
    
    
        threshold( gray_all, threshold_output_all, 45, 255, THRESH_BINARY );
        findContours( threshold_output_all, contours_all, hierarchy_all,  RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0) );//RETR_EXTERNAL表示只寻找最外层轮廓
    
    
        Point2f fourPoint2f[4];
        //求最小包围矩形
        RotatedRect rectPoint = minAreaRect(contours_all[0]);
    
        //将rectPoint变量中存储的坐标值放到 fourPoint的数组中
        rectPoint.points(fourPoint2f);
    
    
        for (int i = 0; i < 4; i++)
        {
            line(src_all, fourPoint2f[i%4], fourPoint2f[(i + 1)%4]
                , Scalar(20,21,237), 3);
        }
    
        namedWindow("Src_all");
        imshow( "Src_all", src_all );
    
        //框出二维码后,就可以提取出二维码,然后使用解码库zxing,解出码的信息。
        //或者研究二维码的排布规则,自己写解码部分
    
        waitKey(0);
        return(0);
    }
    

    下面是代码运行的图片,代码处理过程的图片都有,包括二值化图片,轮廓图,找到的定位角图和最终的框出二维码图都显示出来了。如下:


    这部分的代码主要是修改自guanyonglai博主的代码,在此基础上学习了相应的opencv库函数,并根据自己的理解添加了一些注释。实现的主要功能是根据QR二维码三个定位角的特点找出定位角的坐标,并框出整个QR二维码。
    框出二维码后能做的事情就多了,可以使用相应的开源解码库解出二维码的信息,比如Zxing库,libdmtx库。Zxing库能解码的格式和支持的语音格式挺多的,网址:https://github.com/zxing/zxing。libdmtx库主要解码data matrix二维码,网址:http://libdmtx.sourceforge.net/这个库我使用过,很简单,直接调用几个函数就可以解出码的信息。
    解码部分使用libdmtx库的方式已经实现的了,有时间再补充。去除opencv库,直接用算法处理图片并定位二维码并解码的也写了demo,这部分内容较多,有时间再补充,需要大概思路的可以留言。

    展开全文
  • 此代码是基于二维码识别的python代码,将视频中的二维码识别的数据进行解析,并在屏幕上面打印出来,并解析成为坐标的形式,最后由于要控制步进电机进行相应的操作,因此在解析挖成之后并把坐标转换成为数控编码的...
  • 二维码识别

    2018-07-20 19:32:58
    //二维码识别 compile 'com.acker:simplezxing:1.5' 二、在Mactivity的Xml中做的操作 &lt;Button android:id="@+id/mBtn" android:text="点击识别识别二维码" a...

    首先再次此声明,根据我的思路一步一步实现,简单明了的实现基础功能,至于拓展有待于你的后续开发。。。

    一、倒依赖

    //二维码识别
    compile 'com.acker:simplezxing:1.5'

    二、在Mactivity的Xml中做的操作

    <Button
        android:id="@+id/mBtn"
        android:text="点击识别识别二维码"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    三、在Activity中

    (1)在Button的点击事件中:

    startActivityForResult(new Intent(getContext(), CaptureActivity.class), CaptureActivity.REQ_CODE);

    (2)在点击事件的方法外:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        String s = CaptureActivity.EXTRA_SCAN_RESULT;
        text = data.getStringExtra(s);
        //mText.setText(text);
    
        Intent intent = new Intent(getContext(), Main2Activity.class);
        intent.putExtra("uri", text);
        startActivity(intent);
    }

    四、在跳转的Main2Activity的Xml中

    <WebView
        android:id="@+id/mWeb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
    </WebView>
    

    五、、在跳转的Main2Activity中

    (1)在OnCreat方法中:

    Intent intent = getIntent();
    uri = intent.getStringExtra("uri");

    (2)Web初始化后面:

    mWeb.loadUrl(uri);

    六、在网页里创建属于你的二维码

    网页为:http://www.liantu.com/

     

    展开全文
  • 简单的二维码识别(实现代码)

    千次阅读 2018-08-10 16:55:13
    //二维码识别 compile 'com.acker:simplezxing:1.5' 二、在Activity的Xml中 &lt;Button android:id="@+id/mBtn" android:text="点击识别" android:layout_width="wrap_content&...
  • 微信长按图片无法弹出识别二维码选项解决方案

    万次阅读 多人点赞 2016-11-28 19:54:27
    1.首先页面中有两个二维码的兄弟别忙活了,一个页面中只可以识别其中一个二维码,两个的话需提示用户双击放大二维码进行二维码识别. 2.网页内有一张图片进行二维码识别时长按没有反应这个就是我所遇到的问题。需要调...
  • 提高二维码识别

    万次阅读 2013-12-09 12:02:32
    一般情况下的二维码都是很容易识别的,这里指的是直接在电脑上或手机上生成的二维码图片,这类图片由于直接生成的,所以都很清晰,很容易识别出来。 我这里所说的二维码识别率指的下类的二维码: 1.二维码打印...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • 为了实现app扫描二维码,我想了很多办法,最后还是用原生的来挑战自己,下面是链接 http://www.html5plus.org/doc/zh_cn/barcode.html
  • Android 二维码扫描,识别率非常高

    万次阅读 热门讨论 2017-05-23 19:47:02
    这是我在GitHub看到的一个开源二维码码扫描例子,识别率非常高。支出二维码,条形码,以及图片识别。 效果图与示例 apk   点击下载 ZXingDemo.apk或扫描下面的二维码安装 点击下载 ZBarDemo.apk或...
  • 写过小程序的都知道小程序里面都只能识别小程序码,但是小程序码明显没有二维码用得广泛。 我目前所解决的方案就是利用小程序的客服组件,通过客服给用户发送的二维码可以长按识别并分享给好友,保存图片 前端代码...
  • 二维码解码工具

    万次阅读 2017-04-01 11:47:19
    http://tool.chinaz.com/qrcode/?jdfwkey=weexu
  • 微信小程序长按识别二维码,小程序相关问题总结 开发小程序中,长按识别二维码,小程序码跳转,已知问题整理:小程序中,不支持长按识别二维码,和小程序码。可利用小程序 图片预览功能识别 小程序码并进行跳转,...
  • h5识别二维码功能

    千次阅读 2017-07-04 09:41:57
    页面是H5的,我首先是...查了资料说是因为:二维码识别感应区域x,y坐标相对偏原目标大概偏离了200px 所以得加个样式啊 .qrcode{ padding:200px 0 0 200px !important; margin:-200px 0 0 -200px !important;
  • 安卓和IOS两个平台微信识别二维码的机制分别是什么?这两个平台解码的步骤是?
  • 1.小程序中的图片不能识别除小程序码以外的二维码 2.并且仅在 wx.previewImage 中支持长按识别 官方文档(wx.previewImage组件) html代码(这里我就简单的添加了一张图片做测试) &lt;image src="/image...
  • JS识别二维码、JS生成二维码

    万次阅读 2018-09-10 11:39:55
    最近的项目中使用到了识别二维码和生成二维码,都是用JS生成的,应用在了移动端,在网上搜罗了许多进行验证,下面是我在项目中应用的: 识别二维码 1.JS文件和测试页面压缩包:...
  • 我返回的二维码怎么按都不弹出保存图片、识别二维码这些菜单,最多弹出个放大镜.... ``` <!-- 名片二维码" src=""> --> ``` 不知道这些样式要怎么设置,或者还是有别的标签? 到底怎样才能识别呢?
1 2 3 4 5 ... 20
收藏数 60,118
精华内容 24,047
关键字:

二维码识别