Opencv+Zbar二维码识别(二维码校正)

来源:互联网 发布:甲骨文java培训骗局 编辑:程序博客网 时间:2024/05/16 05:08

二维码和车牌识别基本都会涉及到图像的校正,主要是形变和倾斜角度的校正,一种二维码的畸变如下图:


这个码用微信扫了一下,识别不出来,但是用Zbar还是可以准确识别的~~。

这里介绍一种二维码校正方法,通过定位二维码的4个顶点,利用仿射变换校正。基本思路:滤波->二值化->膨胀(腐蚀)操作->形态学边界->寻找直线->定位交点->仿射变换校正->Zbar识别。


滤波、二值化:


腐蚀操作:



形态学边界:



寻找直线:



角点定位:



仿射变换校正:



Zbar识别:



Code实现:

[cpp] view plain copy print?
  1. #include "zbar.h"        
  2. #include "cv.h"        
  3. #include "highgui.h"        
  4. #include <iostream>        
  5.   
  6. using namespace std;        
  7. using namespace zbar;  //添加zbar名称空间      
  8. using namespace cv;        
  9.   
  10. int main(int argc,char*argv[])      
  11. {    
  12.     Mat imageSource=imread(argv[1],0);    
  13.     Mat image;  
  14.     imageSource.copyTo(image);  
  15.     GaussianBlur(image,image,Size(3,3),0);  //滤波  
  16.     threshold(image,image,100,255,CV_THRESH_BINARY);  //二值化  
  17.     imshow("二值化",image);      
  18.     Mat element=getStructuringElement(2,Size(7,7));  //膨胀腐蚀核  
  19.     //morphologyEx(image,image,MORPH_OPEN,element);   
  20.     for(int i=0;i<10;i++)  
  21.     {  
  22.         erode(image,image,element);  
  23.         i++;  
  24.     }     
  25.     imshow("腐蚀s",image);  
  26.     Mat image1;  
  27.     erode(image,image1,element);  
  28.     image1=image-image1;  
  29.     imshow("边界",image1);  
  30.     //寻找直线 边界定位也可以用findContours实现  
  31.     vector<Vec2f>lines;  
  32.     HoughLines(image1,lines,1,CV_PI/150,250,0,0);  
  33.     Mat DrawLine=Mat::zeros(image1.size(),CV_8UC1);  
  34.     for(int i=0;i<lines.size();i++)  
  35.     {  
  36.         float rho=lines[i][0];  
  37.         float theta=lines[i][1];  
  38.         Point pt1,pt2;  
  39.         double a=cos(theta),b=sin(theta);  
  40.         double x0=a*rho,y0=b*rho;  
  41.         pt1.x=cvRound(x0+1000*(-b));  
  42.         pt1.y=cvRound(y0+1000*a);  
  43.         pt2.x=cvRound(x0-1000*(-b));  
  44.         pt2.y=cvRound(y0-1000*a);  
  45.         line(DrawLine,pt1,pt2,Scalar(255),1,CV_AA);  
  46.     }  
  47.     imshow("直线",DrawLine);  
  48.     Point2f P1[4];  
  49.     Point2f P2[4];  
  50.     vector<Point2f>corners;  
  51.     goodFeaturesToTrack(DrawLine,corners,4,0.1,10,Mat()); //角点检测  
  52.     for(int i=0;i<corners.size();i++)  
  53.     {  
  54.         circle(DrawLine,corners[i],3,Scalar(255),3);  
  55.         P1[i]=corners[i];         
  56.     }  
  57.     imshow("交点",DrawLine);  
  58.     int width=P1[1].x-P1[0].x;  
  59.     int hight=P1[2].y-P1[0].y;  
  60.     P2[0]=P1[0];  
  61.     P2[1]=Point2f(P2[0].x+width,P2[0].y);  
  62.     P2[2]=Point2f(P2[0].x,P2[1].y+hight);  
  63.     P2[3]=Point2f(P2[1].x,P2[2].y);  
  64.     Mat elementTransf;  
  65.     elementTransf=  getAffineTransform(P1,P2);  
  66.     warpAffine(imageSource,imageSource,elementTransf,imageSource.size(),1,0,Scalar(255));  
  67.     imshow("校正",imageSource);     
  68.     //Zbar二维码识别  
  69.     ImageScanner scanner;        
  70.     scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);   
  71.     int width1 = imageSource.cols;        
  72.     int height1 = imageSource.rows;        
  73.     uchar *raw = (uchar *)imageSource.data;           
  74.     Image imageZbar(width1, height1, "Y800", raw, width * height1);          
  75.     scanner.scan(imageZbar); //扫描条码      
  76.     Image::SymbolIterator symbol = imageZbar.symbol_begin();    
  77.     if(imageZbar.symbol_begin()==imageZbar.symbol_end())    
  78.     {    
  79.         cout<<"查询条码失败,请检查图片!"<<endl;    
  80.     }    
  81.     for(;symbol != imageZbar.symbol_end();++symbol)      
  82.     {        
  83.         cout<<"类型:"<<endl<<symbol->get_type_name()<<endl<<endl;      
  84.         cout<<"条码:"<<endl<<symbol->get_data()<<endl<<endl;         
  85.     }        
  86.     namedWindow("Source Window",0);  
  87.     imshow("Source Window",imageSource);          
  88.     waitKey();      
  89.     imageZbar.set_data(NULL,0);    
  90.     return 0;    
  91. }