20170814二维码的识别

1. 本次小玩意主要是运用OpenCV的图像识别技术,同时又用到了zbar。opencv相信大家应该比较熟悉了,我就不废话了吐舌头

我就给大家简单介绍一下zbar吧。

ZBar 是款桌面电脑用条形码/二维码扫描工具,支持摄像头及图片扫描,支持多平台包括 iPhone 手机。同时 ZBar 提供了二维码扫描的 API 开发包。

ZBar 目前支持扫描,除了 Windows 平台外,还支持 Linux 及 iPhone 平台。可扫描以下类型,常见的都有。

EAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 39, Interleaved 2 of 5 and QR Code.。

2. 那如何使用zbar来识别二维码呢? 首先我们需要下载zbar的源码,源码下载地址在http://download.csdn.NET/detail/cjj1130320082/9586128

3. 在虚拟机ubuntu12.04安装zbar

    3.1 解压 tar -zxvf zbar-0.10-tar.gz

    3.2 cd zbar-0.10

    3.3 配置 执行 ./configure

    3.4 编译与安装 make && make install 

经过上面几个简单的步骤之后,zbar就安装好了

下面就具体的看代码吧大笑



/*

  程序功能 -- 二维码图片检测和解码
  用的是opencv1版本的函数用到了 1 边缘检测Sobel
                                2  二值化threshold
                                3 形态学操作膨胀腐蚀 erode dilate
                                4 轮廓寻找findContours
                                5 二维码解码
  参考资料:http://blog.jobbole.com/80448/
*/
#include <stdio.h>
#include <opencv/highgui.h>
#include <zbar.h>
#include <time.h>
#include <opencv2/opencv.hpp>
#include <opencv/cv.h>
#include <iostream>
 

using namespace std;
using namespace cv;
using namespace zbar;

#define FLOAT 10
#define PICTURE "13.bmp"
int main(int argc,char *argv[])
{
    
    //加载原图
    IplImage *srcImage = cvLoadImage(PICTURE,1);
    //cvNamedWindow("1.原图",0);
    //cvShowImage("1.原图",image);

    //测时
    clock_t start, finish;
    double duration;
    start = clock();
    //转变为灰度图
    IplImage *Grayimage = cvCreateImage(cvGetSize(srcImage),IPL_DEPTH_8U, 1);
    cvCvtColor(srcImage,Grayimage,CV_BGR2GRAY);

     //cvNamedWindow("Grayimage",0);
   // cvShowImage("Grayimage",Grayimage);

    //通过sobel来对图片进行竖向边缘检测,输入图像是8位时,输出必须是16位,然后再将图像转变成8位深
    IplImage *sobel = cvCreateImage(cvGetSize(Grayimage),IPL_DEPTH_16S,1);
    cvSobel(Grayimage,sobel,2,0,7);
    
    IplImage *temp = cvCreateImage(cvGetSize(sobel),IPL_DEPTH_8U,1);
    cvConvertScale(sobel,temp,0.002,0);

    //cvNamedWindow("temp",0);
    //cvShowImage("temp",temp);

    //对图像进行二值化处理
    IplImage *threshold = cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,1);
    cvThreshold(temp,threshold,13,100,CV_THRESH_BINARY/*| CV_THRESH_OTSU*/);
     //cvThreshold(temp, threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);

    //cvNamedWindow("threshold",0);
    //cvShowImage("threshold",threshold);

     //自定义1*3的核进行X方向的膨胀腐蚀  
    IplImage *erode_dilate=cvCreateImage(cvGetSize(threshold),IPL_DEPTH_8U,1);
    IplConvKernel* kernal = cvCreateStructuringElementEx(3,1, 1, 0, CV_SHAPE_RECT);
    cvDilate(threshold, erode_dilate, kernal, 15);//X方向膨胀连通数字
    cvErode(erode_dilate, erode_dilate, kernal, 6);//X方向腐蚀去除碎片
    cvDilate(erode_dilate, erode_dilate, kernal, 1);//X方向膨胀回复形态

    //自定义3*1的核进行Y方向的膨胀腐蚀
    kernal = cvCreateStructuringElementEx(1,3, 0, 1, CV_SHAPE_RECT);
    //cvDilate(erode_dilate, erode_dilate, kernal, 5);
    cvErode(erode_dilate, erode_dilate, kernal, 2);// Y方向腐蚀去除碎片
    cvDilate(erode_dilate, erode_dilate, kernal, 6);//回复形态

    //cvNamedWindow("erode_dilate",0);
    //cvShowImage("erode_dilate",erode_dilate);

    //图形检测
    IplImage* copy = cvCloneImage(erode_dilate);//直接把erode_dilate的数据复制给copy
    IplImage* copy1 = cvCloneImage(srcImage);//直接把image的数据复制给copy1
    CvMemStorage* storage = cvCreateMemStorage();
    CvSeq* contours;
    cvFindContours(copy, storage, &contours);
    int i=0,k=0,j=0;
    CvRect RECT[100];
    CvRect Rect[100];
    
    while(contours != NULL)
    {
        //绘制轮廓的最小外接矩形,如果满足条件,将该矩形绘制在显示图片dst
        /*
           矩形要求:
               1.宽度与高度的比值在(2,5)之间
               2.面积大于图像的 1/20000
               3.y轴的位置在图像高度减去50以下
        */
        CvRect rect=cvBoundingRect( contours, 1 );  //cvBoundingRect计算点集的最外面(up-right)矩形边界。
        if(rect.width/rect.height>0.8
            &&rect.width/rect.height<1.2
            &&rect.height*rect.height*FLOAT>copy1->height*copy1->width
            &&rect.y<copy1->height-50
            )
        {
            printf("rect.x = %d  rect.y = %d  rect.width = %d  rect.height = %d\n",rect.x,rect.y,rect.width,rect.height);
            //rect.x-=10;
           // rect.y-=10;
           // rect.width+=20;
           // rect.height+=20;
            RECT[i]=rect; //将图片中符合的矩形区域存到RECT
            i++;
        }
                contours= contours->h_next;
        
    }
    printf("Find the rect %d!\n",i);
    for(j=0;j<i;j++)
    {
        if(j==0)
        {
            cvRectangleR(copy1,RECT[j],CV_RGB(255,0,0),3);
            Rect[k]=RECT[j];
            k++;
            //printf("j = %d\n",j);
            //printf("The j is the %d!\n",j);
        }
        else if(RECT[j-1].y-RECT[j].y>100
                ||(RECT[j-1].x-RECT[j].x>200
                ||RECT[j].x-RECT[j-1].x>200))
        {
              cvRectangleR(copy1,RECT[j],CV_RGB(255,0,0),3);
              Rect[k]=RECT[j];
              k++;
              //printf("The jj is the %d!\n",j);
        }
    }
    
    cvNamedWindow("copy1",0);
    cvShowImage("copy1",copy1);
    //cvWaitKey(0);
    //cvReleaseImage(&Grayimage);
    cvReleaseImage(&temp);
    cvReleaseImage(&threshold);
    cvReleaseImage(&erode_dilate);
    cvReleaseImage(&srcImage);
    cvReleaseImage(&copy);
    cvReleaseImage(&copy1);
    // create a reader
    //srcImage = cvLoadImage(PICTURE,1);
    srcImage = Grayimage;//解码图片必需位灰度图
    ImageScanner scanner;

    // configure the reader
    scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);

    // obtain image data
    
    const void *raw = NULL;
    //int width=srcImage->width;  
    //int height=srcImage->height;   
    //raw = srcImage->imageDataOrigin;
    //cvMat(int rows, int cols, int type, void * data CV_DEFAULT(NULL))
    //cout<<"The number is the one!"<<endl;
    Mat im(srcImage, TRUE);
    int width=im.cols;  
    int height=im.rows;   
    raw = im.data;
    // wrap image data
    zbar::Image image(width, height, "Y800", raw, width * height);

    // scan the image for barcodes
    int n = scanner.scan(image);
   
    std::string strTemp="";
    // extract results
     //cout<<"The number is the two!"<<endl;
    zbar::Image::SymbolIterator symbol = image.symbol_begin();
    //cout<<"The number is the three!"<<endl;
    cout << "decoded " << symbol->get_type_name()<<endl;
    
    for(;symbol != image.symbol_end();++symbol)
    {
            // do something useful with results
            
            strTemp =strTemp +symbol->get_data()+";";
            cout << "decoded " << symbol->get_type_name()<< " symbol \"" << symbol->get_data() << '"' << endl;
    }

    // clean up
    image.set_data(NULL, 0);
    
    cvWaitKey(0);
    cvReleaseImage(&Grayimage);
        return(0);
}

看一下代码执行的效果:

rect.x = 1  rect.y = 1  rect.width = 298  rect.height = 298
Find the rect 1!
decoded QR-Code
decoded QR-Code symbol "http://www.baidu.com1sfsdfsdf212334344343334334"  //解码后的结果

代码的下载地址http://download.csdn.net/detail/cjj1130320082/9585923


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值