简单的验证码识别(opecv)

       opencv版本: 3.0.0

           处理验证码: 纯数字验证码 (颜色不同,有噪音,和带有较多的划痕)

             测试时间 :  一天+一晚

                  效果: 比较挫,可能是由于测试的图片是在太小了的缘故.

               原理:

         验证码识别作为身份证号机器识别的一个衍生,夹杂了很多干扰的噪音,所以加大了二值化的难度。以及轮廓追踪的不好协调。

        操作过程大过程有以下几个:

                  (1) 待测试的图片灰度化并二值化

                  (2)预先装载特征库(这里分为多样,形式不一)

                  (3)物体轮廓检测                  

                  (4)扫描待测图片,并进行特征码比对,匹配优先

       处理图片展示:

        代码演示:

  1 #include<opencv2/opencv.hpp>
  2 
  3 #include <iostream>  
  4 #include <string>
  5 
  6 struct DataBase{
  7    int  value;        //库特征对应的值
  8    vector<Mat> sample;   //特征库
  9    DataBase(int var , Mat & sam){
 10        value = var;
 11        sample.push_back(sam);
 12    }
 13 };
 14 
 15 typedef struct DataBase dataBase;
 16 
 17 
 18 
 19 
 20 //加载图片
 21 bool loadImage(Mat &src , Mat &gray ,String &filename){
 22 
 23     Mat cbgray ; //合成后图像
 24     int chans;    //bgR分量
 25     src = imread( filename , true ); 
 26     if( src.empty() )    return false;
 27     chans = src.channels();
 28     vector<Mat> bgR(  chans ) ;
 29     //分割通道
 30     split(src,bgR);
 31     //直方图均衡化
 32     for(int chan=0 ; chan < chans ; ++chan ){
 33         equalizeHist(bgR[chan] , bgR[chan]);
 34     }
 35     //单通道合并
 36     merge(bgR , cbgray );
 37     //灰度化
 38     cvtColor(cbgray ,gray ,CV_RGB2GRAY);
 39     return true ;
 40 }
 41 
 42 //二值化
 43 bool binImage(Mat& src , Mat& dst , int _size , int lparam  ,int mediansize){
 44    //采用自适应二值化
 45     adaptiveThreshold(src,src,255,CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY,_size , lparam);
 46    //中值滤波
 47     medianBlur(src,dst,mediansize);
 48    return true;
 49 }
 50 
 51 //装载特征库
 52 /*通常来说这个应该是预先被加载好,以数据库或者其他的形式保存起来
 53   在这地方由于东西比较少,直接现场处理
 54 */
 55 int loadProperty(vector<dataBase> &db  ,int index[]
 56     , int _size = 31 , int lparam = 7 , int mediansize = 3 ){
 57 
 58       //固定路径
 59      char filename[30];
 60      
 61     for(int i=0; i<20 ; ++i){
 62          sprintf(filename,"D:\\yzm\\tzk\\%d.png",index[i]);
 63          Mat tmp;
 64          String path =filename;
 65          loadImage(tmp,tmp,path);    //装载并灰度化 
 66          binImage(tmp,tmp,_size,lparam,mediansize);   //二值化
 67         //imshow("sample",tmp);
 68         //waitKey(0);
 69          db.push_back( dataBase( index[i]%10 , tmp ) );         
 70      }
 71 
 72   return true;
 73 }
 74 
 75 
 76 //对于模块进行匹配
 77 int StartMatch(Mat src , vector< dataBase > db , Point  &curpx){
 78  
 79     int res ;
 80     double maxValue , minValue ,resValue ;
 81     Point  minloc , maxloc ,resloc;
 82 
 83     vector< dataBase >::iterator it;
 84     vector< Mat >::iterator m_it;
 85     
 86     Mat sample ,result;
 87     int curcols , currows;
 88     resValue =1.;
 89 
 90   for( it = db.begin() ; it !=db.end() ; it++ ){
 91 
 92      for( m_it = it->sample.begin() ; m_it != it->sample.end() ; m_it++ ){
 93 
 94           sample = *m_it;
 95           int res_rows = src.rows - sample.rows + 1 ;
 96           int res_cols = src.cols - sample.cols + 1 ;
 97           if( res_rows < 1 || res_cols< 1 ) break;
 98           result = cv::cvarrToMat(cvCreateImage(cvSize(res_cols, res_rows), 1, 1)); 
 99           
100           matchTemplate(src, sample , result ,CV_TM_SQDIFF_NORMED);  //模板匹配算法,平方差匹配
101           
102           minMaxLoc(result, &minValue, &maxValue, &minloc, &maxloc,Mat() );
103           if(resValue > minValue){
104               resValue = minValue;
105               resloc = minloc;
106               res = it->value; //记录这个值的大小
107               curcols = sample.cols;
108               currows = sample.rows;
109          }
110    }
111  }
112  
113 //  rectangle(srcResult, matchLoc, cvPoint(matchLoc.x + curtemplatW, matchLoc.y+ curtemplatH), cvScalar(0,0,255));
114   //设定一个阈值
115   if(resValue<0.2){
116    //++curpx.x;
117     curpx.x += resloc.x + curcols/2.; 
118     rectangle(src,resloc,cvPoint(resloc.x + curcols , resloc.y + currows ),cvScalar(0,0,255));
119   }
120   else{
121       ++curpx.x;
122      res=-1;
123    }
124   return res;
125 }
126 
127 //逐步的扫描
128 vector< int > ScanImage( Mat &src  , vector< dataBase > db , int window_width=12 ,int  window_height=12 ){
129  
130     Point srcp;
131 
132     window_height = src.rows;
133     vector< int > ans ; 
134     while(srcp.x<src.cols){
135 
136      if(srcp.x + window_width > src.cols)
137          window_width = src.cols - srcp.x;
138      Mat tmp = src( Rect(srcp.x,srcp.y,window_width,window_height) );
139 
140      //轮廓检测
141     /* vector< vector <Point> >reg;
142      Mat newtmp = tmp.clone();
143      findContours(newtmp, reg,CV_RETR_EXTERNAL , CV_CHAIN_APPROX_NONE);
144      if( reg.empty() ) break;
145      Rect rect = boundingRect(Mat(reg[0]));
146      Mat ttmp = tmp(rect);
147      imshow("ttmp",ttmp);
148      waitKey(0);*/
149 
150      int ansvalue =StartMatch(tmp,db,srcp);
151      if(ansvalue !=-1){
152       ans.push_back( ansvalue);
153       printf("%d ",ansvalue);
154     }
155   }
156     puts("");
157   return ans;
158 }
159 
160 int main()
161 {
162 
163     Mat check;
164     vector< dataBase > dblist;
165     int dex[20];//{0,1,2,3,4,5,6,7,8,9}; //建立一个索引
166     for(int i=0;i<20 ; dex[i]=i++);
167     loadProperty(dblist,dex,7,33,3);    
168 
169     for(int i=0;i<9;i++)
170   {
171     char path[30];
172 
173     if(i<9)    sprintf(path,"D:/yzm/%d.jpg",i+1);
174     else     sprintf(path,"D:/yzm/%d.png",i-8);
175     
176     loadImage(check,check,String(path));
177     imshow("check",check);
178     waitKey(0);
179 
180     binImage(check,check,17,50,3);
181 
182     ScanImage(check,dblist,11,3);
183     imshow("final",check);
184     waitKey(0);
185     }
186     waitKey(0);
187     return 0;
188 }

   可能是由于测试的图片太小了,导致二值化的时候,图片很不理想,只好取消轮廓检测,然后改为手动设置窗口大小,虽然比较原始,,但是对于比较清晰的图片多能较好的

识别出来!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xdecode

Java调用PDFBox打印自定义纸张PDF

打印对象 一份设置为A3纸张, 页面边距为(10, 10, 10, 10)mm的PDF文件. ? PageFormat  默认PDFPrintable无法设置页...

65650
来自专栏小鹏的专栏

kinect v2.0原理介绍之十一:录制视频

不小心误删了,再加上。 ~~有兴趣的小伙伴,加kinect算法交流群:462964980。 录制视频是结合openCV来做的。  代码如下: // 19...

28790
来自专栏小鹏的专栏

工业器件检测和识别

有问题欢迎微信交流:lp9628 工业器件标定与识别(如下图所示): ?  ----> ? ----> ? 代码实现: 主要流程:直方图均衡化,去除噪声,二值化...

352100
来自专栏Vamei实验室

纸上谈兵: 伸展树 (splay tree)

我们讨论过,树的搜索效率与树的深度有关。二叉搜索树的深度可能为n,这种情况下,每次搜索的复杂度为n的量级。AVL树通过动态平衡树的深度,单次搜索的复杂度为log...

224100
来自专栏贾志刚-OpenCV学堂

教程 | OpenCV深度神经网络实现人体姿态评估

OpenCV自从发布了DNN模块之后,就开始以开挂的方式支持各种深度学习预训练模型的调用,DNN模块的全称为深度神经网络,但是并不是所有深度学习模型导出到Ope...

30920
来自专栏wym

opencv学习笔记--ROI与泛洪填充

官方定义为:floodFill(InputOutputArray image, Point seedPoint, Scalar newVal, Rect* re...

25620
来自专栏贾志刚-OpenCV学堂

OpenCV中图像修复技术介绍与演示

现实中图像经常出现划伤或者被噪声腐蚀或者有污渍点,对于这类图像可以通过修复(inpainting)相关的算法来说恢复损害的图像。一般情况下这些算法都是基于污染区...

58790
来自专栏一棹烟波

ffmpeg中avframe的YUV格式数据到OpenCV中Mat的BGR格式转换

ffmpeg实现音视频编解码是非常常用的工具,视频解码出来的raw数据是yuv格式,用来进行后续的图像处理一般是RGB格式的。所以需要从yuv到rgb或者bgr...

50090
来自专栏张善友的专栏

Prism Training Kit 4.0

上周刚刚发布的支持Windows Phone 7的Prism 4.0最终版,Damian, Diego, Guido 和Ezequiel更新了Prism Tra...

193100
来自专栏Petrichor的专栏

opencv: 轮廓绘制 详细拆解(图示+源码)

19850

扫码关注云+社区

领取腾讯云代金券