简单的验证码识别(opecv)

时间:2024-04-16 22:35:05

  opencv版本: 3.0.0

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

测试时间 :  一天+一晚

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

原理:

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

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

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

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

(3)物体轮廓检测

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

处理图片展示:

简单的验证码识别(opecv)简单的验证码识别(opecv) 简单的验证码识别(opecv)  简单的验证码识别(opecv)  简单的验证码识别(opecv)  简单的验证码识别(opecv) 简单的验证码识别(opecv) 简单的验证码识别(opecv)

代码演示:

 #include<opencv2/opencv.hpp>

 #include <iostream>
#include <string> struct DataBase{
int value; //库特征对应的值
vector<Mat> sample; //特征库
DataBase(int var , Mat & sam){
value = var;
sample.push_back(sam);
}
}; typedef struct DataBase dataBase; //加载图片
bool loadImage(Mat &src , Mat &gray ,String &filename){ Mat cbgray ; //合成后图像
int chans; //bgR分量
src = imread( filename , true );
if( src.empty() ) return false;
chans = src.channels();
vector<Mat> bgR( chans ) ;
//分割通道
split(src,bgR);
//直方图均衡化
for(int chan= ; chan < chans ; ++chan ){
equalizeHist(bgR[chan] , bgR[chan]);
}
//单通道合并
merge(bgR , cbgray );
//灰度化
cvtColor(cbgray ,gray ,CV_RGB2GRAY);
return true ;
} //二值化
bool binImage(Mat& src , Mat& dst , int _size , int lparam ,int mediansize){
//采用自适应二值化
adaptiveThreshold(src,src,,CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY,_size , lparam);
//中值滤波
medianBlur(src,dst,mediansize);
return true;
} //装载特征库
/*通常来说这个应该是预先被加载好,以数据库或者其他的形式保存起来
在这地方由于东西比较少,直接现场处理
*/
int loadProperty(vector<dataBase> &db ,int index[]
, int _size = , int lparam = , int mediansize = ){ //固定路径
char filename[]; for(int i=; i< ; ++i){
sprintf(filename,"D:\\yzm\\tzk\\%d.png",index[i]);
Mat tmp;
String path =filename;
loadImage(tmp,tmp,path); //装载并灰度化
binImage(tmp,tmp,_size,lparam,mediansize); //二值化
//imshow("sample",tmp);
//waitKey(0);
db.push_back( dataBase( index[i]% , tmp ) );
} return true;
} //对于模块进行匹配
int StartMatch(Mat src , vector< dataBase > db , Point &curpx){ int res ;
double maxValue , minValue ,resValue ;
Point minloc , maxloc ,resloc; vector< dataBase >::iterator it;
vector< Mat >::iterator m_it; Mat sample ,result;
int curcols , currows;
resValue =.; for( it = db.begin() ; it !=db.end() ; it++ ){ for( m_it = it->sample.begin() ; m_it != it->sample.end() ; m_it++ ){ sample = *m_it;
int res_rows = src.rows - sample.rows + ;
int res_cols = src.cols - sample.cols + ;
if( res_rows < || res_cols< ) break;
result = cv::cvarrToMat(cvCreateImage(cvSize(res_cols, res_rows), , )); matchTemplate(src, sample , result ,CV_TM_SQDIFF_NORMED); //模板匹配算法,平方差匹配 minMaxLoc(result, &minValue, &maxValue, &minloc, &maxloc,Mat() );
if(resValue > minValue){
resValue = minValue;
resloc = minloc;
res = it->value; //记录这个值的大小
curcols = sample.cols;
currows = sample.rows;
}
}
} // rectangle(srcResult, matchLoc, cvPoint(matchLoc.x + curtemplatW, matchLoc.y+ curtemplatH), cvScalar(0,0,255));
//设定一个阈值
if(resValue<0.2){
//++curpx.x;
curpx.x += resloc.x + curcols/.;
rectangle(src,resloc,cvPoint(resloc.x + curcols , resloc.y + currows ),cvScalar(,,));
}
else{
++curpx.x;
res=-;
}
return res;
} //逐步的扫描
vector< int > ScanImage( Mat &src , vector< dataBase > db , int window_width= ,int window_height= ){ Point srcp; window_height = src.rows;
vector< int > ans ;
while(srcp.x<src.cols){ if(srcp.x + window_width > src.cols)
window_width = src.cols - srcp.x;
Mat tmp = src( Rect(srcp.x,srcp.y,window_width,window_height) ); //轮廓检测
/* vector< vector <Point> >reg;
Mat newtmp = tmp.clone();
findContours(newtmp, reg,CV_RETR_EXTERNAL , CV_CHAIN_APPROX_NONE);
if( reg.empty() ) break;
Rect rect = boundingRect(Mat(reg[0]));
Mat ttmp = tmp(rect);
imshow("ttmp",ttmp);
waitKey(0);*/ int ansvalue =StartMatch(tmp,db,srcp);
if(ansvalue !=-){
ans.push_back( ansvalue);
printf("%d ",ansvalue);
}
}
puts("");
return ans;
} int main()
{ Mat check;
vector< dataBase > dblist;
int dex[];//{0,1,2,3,4,5,6,7,8,9}; //建立一个索引
for(int i=;i< ; dex[i]=i++);
loadProperty(dblist,dex,,,); for(int i=;i<;i++)
{
char path[]; if(i<) sprintf(path,"D:/yzm/%d.jpg",i+);
else sprintf(path,"D:/yzm/%d.png",i-); loadImage(check,check,String(path));
imshow("check",check);
waitKey(); binImage(check,check,,,); ScanImage(check,dblist,,);
imshow("final",check);
waitKey();
}
waitKey();
return ;
}

简单的验证码识别(opecv)         简单的验证码识别(opecv)

简单的验证码识别(opecv)简单的验证码识别(opecv)       简单的验证码识别(opecv)     简单的验证码识别(opecv)    简单的验证码识别(opecv)

简单的验证码识别(opecv)

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

识别出来!