• 简单的验证码识别(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 }

              

                     

       

      

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

    识别出来!

        

                             

  • 相关阅读:
    Jmeter学习笔记-初级
    python selenium利用 126.com id自动生成
    Python代码无法保存
    卸载python2.7出错
    python pip用法
    pycharm 连接数据库
    Python打包PyPI上传实践
    Python实现Api的Mock测试
    抓包工具使用
    Jenkins+Ant可持续集成Jmeter脚本
  • 原文地址:https://www.cnblogs.com/gongxijun/p/5152099.html
Copyright © 2020-2023  润新知