c++ 基于opencv 识别、定位二维码
前言
因工作需要,需要定位图片中的二维码;我遂查阅了相关资料,也学习了opencv开源库。通过一番努力,终于很好的实现了二维码定位。本文将讲解如何使用opencv定位二维码。
定位二维码不仅仅是为了识别二维码;还可以通过二维码对图像进行水平纠正以及相邻区域定位。定位二维码,不仅需要图像处理相关知识,还需要分析二维码的特性,本文先从二维码的特性讲起。
1二维码特性
二维码在设计之初就考虑到了识别问题,所以二维码有一些特征是非常明显的。
二维码有三个“回“”字形图案,这一点非常明显。中间的一个点位于图案的左上角,如果图像偏转,也可以根据二维码来纠正。
思考题:
为什么是三个点,而不是一个、两个或四个点。
一个点:特征不明显,不易定位。不易定位二维码倾斜角度。
两个点:两个点的次序无法确认,很难确定二维码是否放正了。
四个点:无法确定4个点的次序,从而无法确定二维码是否放正了。
识别二维码,就是识别二维码的三个点,逐步分析一下这三个点的特性
1每个点有两个轮廓。就是两个口,大“口”内部有一个小“口”,所以是两个轮廓。
2如果把这个“回”放到一个白色的背景下,从左到右,或从上到下画一条线。这条线经过的图案黑白比例大约为:黑白比例为1:1:3:1:1。
3如何找到左上角的顶点?这个顶点与其他两个顶点的夹角为90度。
通过上面几个步骤,就能识别出二维码的三个顶点,并且识别出左上角的顶点。
2使用opencv识别二维码
1)查找轮廓,筛选出三个二维码顶点
opencv一个非常重要的函数就是查找轮廓,就是可以找到一个图中的缩所有的轮廓,“回”字形图案是一个非常的明显的轮廓,很容易找到。
intQrParse::FindQrPoint(Mat&srcImg,vector>&qrPoint){ //彩色图转灰度图 Matsrc_gray; cvtColor(srcImg,src_gray,CV_BGR2GRAY); namedWindow("src_gray"); imshow("src_gray",src_gray); //二值化 Matthreshold_output; threshold(src_gray,threshold_output,0,255,THRESH_BINARY|THRESH_OTSU); Matthreshold_output_copy=threshold_output.clone(); namedWindow("Threshold_output"); imshow("Threshold_output",threshold_output); //调用查找轮廓函数 vector >contours; vector hierarchy; findContours(threshold_output,contours,hierarchy,CV_RETR_TREE,CHAIN_APPROX_NONE,Point(0,0)); //通过黑色定位角作为父轮廓,有两个子轮廓的特点,筛选出三个定位角 intparentIdx=-1; intic=0; for(inti=0;i 找到了两个轮廓的图元,需要进一步分析是不是二维码顶点,用到如下函数:
boolQrParse::IsQrPoint(vector&contour,Mat&img) { //最小大小限定 RotatedRectrotatedRect=minAreaRect(contour); if(rotatedRect.size.height<10||rotatedRect.size.width<10) returnfalse; //将二维码从整个图上抠出来 cv::MatcropImg=CropImage(img,rotatedRect); intflag=i++; //横向黑白比例1:1:3:1:1 boolresult=IsQrColorRate(cropImg,flag); returnresult; } 黑白比例判断函数:
//横向和纵向黑白比例判断 boolQrParse::IsQrColorRate(cv::Mat&image,intflag) { boolx=IsQrColorRateX(image,flag); if(!x) returnfalse; booly=IsQrColorRateY(image,flag); returny; } //横向黑白比例判断 boolQrParse::IsQrColorRateX(cv::Mat&image,intflag) { intnr=image.rows/2; intnc=image.cols*image.channels(); vectorvValueCount; vector vColor; intcount=0; ucharlastColor=0; uchar*data=image.ptr (nr); for(inti=0;i 0) color=255; if(i==0) { lastColor=color; count++; } else { if(lastColor!=color) { vValueCount.push_back(count); count=0; } count++; lastColor=color; } } if(count!=0) vValueCount.push_back(count); if(vValueCount.size()<5) returnfalse; //横向黑白比例1:1:3:1:1 intindex=-1; intmaxCount=-1; for(inti=0;i maxCount) { index=i; maxCount=vValueCount[i]; } } } //左边右边都有两个值,才行 if(index<2) returnfalse; if((vValueCount.size()-index)<3) returnfalse; //黑白比例1:1:3:1:1 floatrate=((float)maxCount)/3.00; cout<<"flag:"< boolQrParse::IsQrRate(floatrate) { //大概比例不能太严格 returnrate>0.6&&rate<1.9; }2)确定三个二维码顶点的次序
通过如下原则确定左上角顶点:二维码左上角的顶点与其他两个顶点的夹角为90度。
//pointDest存放调整后的三个点,三个点的顺序如下 //pt0----pt1 // //pt2 boolQrParse::AdjustQrPoint(Point*pointSrc,Point*pointDest){ boolclockwise; intindex1[3]={ 2,1,0 } ; intindex2[3]={ 0,2,1 } ; intindex3[3]={ 0,1,2 } ; for(inti=0;i<3;i++){ int*n=index1; if(i==0) n=index1;elseif(i==1) n=index2;else n=index3; if(angle>80&&angle<99){ pointDest[0]=pointSrc[n[2]]; if(clockwise){ pointDest[1]=pointSrc[n[0]]; pointDest[2]=pointSrc[n[1]]; }else{ pointDest[1]=pointSrc[n[1]]; pointDest[2]=pointSrc[n[0]]; } returntrue; } } returntrue; }3)通过二维码对图片矫正。
图片有可能是倾斜的,倾斜夹角可以通过pt0与pt1连线与水平线之间的夹角确定。二维码的倾斜角度就是整个图片的倾斜角度,从而可以对整个图片进行水平矫正。
//二维码倾斜角度 Pointhor(pointAdjust[0].x+300,pointAdjust[0].y);//水平线 doubleqrAngle=QrParse::Angle(pointAdjust[1],hor,pointAdjust[0],clockwise); //以二维码左上角点为中心旋转 MatdrawingRotation=Mat::zeros(Size(src.cols,src.rows),CV_8UC3); doublerotationAngle=clockwise?-qrAngle:qrAngle; Mataffine_matrix=getRotationMatrix2D(pointAdjust[0],rotationAngle,1.0);//求得旋转矩阵 warpAffine(src,drawingRotation,affine_matrix,drawingRotation.size());4)二维码相邻区域定位
一般情况下,二维码在整个图中的位置是确定的。识别出二维码后,根据二维码与其他图的位置关系,可以很容易的定位别的图元。
后记
作者通过查找大量资料,仔细研究了二维码的特征,从而找到了识别二维码的方法。网上也有许多识别二维码的方法,但是不够严谨。本文是将二维码的多个特征相结合来识别,这样更准确。这种识别方法已应用在公司的产品中,识别效果还是非常好的。
以上就是c++基于opencv识别、定位二维码的详细内容,更多关于c++opencv识别、定位二维码的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。