验证码识别技术
来源:互联网 发布:思迅软件好不好 编辑:程序博客网 时间:2024/04/28 01:23
验证码识别技术 收藏
程序实现分样本下载器、用户交互程序、MLP建构程序三块,使用OpenCV,喜欢的可以留意下AnnMLP的使用方法,国内这方面的资料还是比较少的,欢迎交流QQ:13895354。
预处理技术是专门针对某种特定验证码设计的,其特点有:英文+数字,彩色,倾斜,无粘连,有不规则噪声,有删除线,至于具体哪家网站的验证码,我就不方便透露了
(用户交互程序)
- #include <cv.h>
- #include <highgui.h>
- #include <ml.h>
- #include <iostream>
- using namespace std;
- int main( int argc, char** argv )
- {
- cvNamedWindow("1");
- cvNamedWindow("2");
- IplConvKernel* se = cvCreateStructuringElementEx(2, 2, 1, 1, CV_SHAPE_CROSS);
- CvANN_MLP mlp;
- mlp.load( "mpl.xml" );
- for(int i=1; i<=100; i++)
- {
- // 产生文件名
- char fn[1024];
- sprintf(fn, ".//sample//%d.jpg", i);
- // 读取图片
- IplImage* gray = cvLoadImage(fn, CV_LOAD_IMAGE_GRAYSCALE);
- // 二值化
- cvThreshold(gray, gray, 180, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
- // 去边框
- cvRectangle(gray, cvPoint(0, 0), cvPoint(gray->width-1, gray->height-1), CV_RGB(255, 255, 255));
- // 去噪
- cvDilate(gray, gray, se);
- /*
- // 调整角度
- cvShowImage("1", gray);
- IplImage* rote = cvCreateImage( cvGetSize(gray), IPL_DEPTH_8U, 1 );
- double t = tan(10.0 / 180.0 * CV_PI);
- int w = gray->width;
- int h = gray->height;
- for(int i = 0; i<h; i++)
- {
- unsigned char* lineGray = (unsigned char*)gray->imageData + gray->widthStep * i;
- unsigned char* lineRote = (unsigned char*)rote->imageData + rote->widthStep * i;
- for(int j = 0; j<w; j++)
- {
- int j2 = j - ((int)(i*t+0.5));
- if (j2<0)
- j2+=w;
- *(lineRote+j) = *(lineGray+j2);
- }
- }
- cvCopy(rote, gray);
- cvReleaseImage(&rote);
- */
- // 计算连通域contour
- cvXorS(gray, cvScalarAll(255), gray, 0);
- cvShowImage("1", gray);
- CvMemStorage* storage = cvCreateMemStorage();
- CvSeq* contour = NULL;
- cvFindContours(gray, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
- // 分析连通域
- CvSeq* p = contour;
- while(p)
- {
- CvRect rect = cvBoundingRect(p, 0);
- if( rect.height>=10 )// 文字需要有10像素高度
- {
- // 绘制该连通区域到character
- cvZero(gray);
- IplImage* character = cvCreateImage(cvSize(rect.width, rect.height), IPL_DEPTH_8U, 1);
- cvZero(character);
- cvDrawContours(character, p, CV_RGB(255, 255, 255), CV_RGB(0, 0, 0), -1, -1, 8, cvPoint(-rect.x, -rect.y));
- // 归一化
- IplImage* normal = cvCreateImage(cvSize(16, 16), IPL_DEPTH_8U, 1);
- cvResize(character, normal, CV_INTER_AREA);
- cvThreshold(normal, normal, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);// 修正
- // 计算输入向量
- float input[256];
- for(int i=0; i<256; i++)
- input[i] = (normal->imageData[i]==-1);
- #if 0
- // 用户输入结果
- cvShowImage("2", normal);
- char c = cvWaitKey(0);
- if(c==27)
- return 0;
- // 编码0-9:0-9 a-z:10-35
- unsigned char cc = 255;
- if(c>='A'&&c<='Z')
- cc=c-'A'+10;
- else if(c>='a'&&c<='z')
- cc=c-'a'+10;
- else if(c>='0'&&c<='9')
- cc=c-'0';
- if(cc!=255)
- {
- // 转换成输出向量
- float output[36];
- for(int i=0; i<36; i++)
- output[i] = 0.0f;
- output[cc] = 1.0f;
- // 存储到批处理文件
- static FILE* batch = fopen("batch", "wb");
- fwrite(output, 4*36, 1, batch);
- fwrite(input, 4*256, 1, batch);
- static int count = 0;
- cout<<count++<<endl;
- }
- #else
- // 识别
- CvMat* output = cvCreateMat( 1, 36, CV_32F );
- CvMat inputMat = cvMat( 1, 256, CV_32F, input);
- mlp.predict( &inputMat, output );
- CvPoint max_loc = {0,0};
- cvMinMaxLoc( output, NULL, NULL, NULL, &max_loc, NULL );
- int best = max_loc.x;// 识别结果
- char c = (char)( best<10 ? '0'+best : 'A'+best-10 );
- cout<<c<<"("<<rect.x<<")"<<" ";
- cvReleaseMat( &output );
- #endif
- cvReleaseImage(&character);
- cvReleaseImage(&normal);
- }
- p = p->h_next;
- }
- cout<<endl;
- cvWaitKey(0);
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&gray);
- }
- cvReleaseStructuringElement(&se);
- cvDestroyAllWindows();
- return 0;
- }
事实上更有价值的是OpenCV中的AnnMLP,其技术很成熟,参考了letter_recg范例程序
(MLP建构程序)
- #include <iostream>
- #include <ml.h>
- using namespace std;
- void print_mat(CvMat& mat)
- {
- int count = 0;
- for(int i=0; i<4/*mat.rows*/; i++)
- {
- for(int j=0; j<mat.cols; j++)
- {
- cout<<mat.data.fl[i*(mat.step/4)+j]/*<<" "*/;
- }
- cout<<endl<<endl;
- }
- }
- int main( int argc, char *argv[] )
- {
- // 读入结果responses 特征data
- FILE* f = fopen( "batch", "rb" );
- fseek(f, 0l, SEEK_END);
- long size = ftell(f);
- fseek(f, 0l, SEEK_SET);
- int count = size/4/(36+256);
- CvMat* batch = cvCreateMat( count, 36+256, CV_32F );
- fread(batch->data.fl, size-1, 1, f);
- CvMat outputs, inputs;
- cvGetCols(batch, &outputs, 0, 36);
- cvGetCols(batch, &inputs, 36, 36+256);
- // 新建MPL
- CvANN_MLP mlp;
- int layer_sz[] = { 256, 20, 36 };
- CvMat layer_sizes = cvMat( 1, 3, CV_32S, layer_sz );
- mlp.create( &layer_sizes );
- // 训练
- system( "time" );
- mlp.train( &inputs, &outputs, NULL, NULL,
- CvANN_MLP_TrainParams(cvTermCriteria(CV_TERMCRIT_ITER,300,0.01), CvANN_MLP_TrainParams::RPROP, 0.01)
- );
- system( "time" );
- // 存储MPL
- mlp.save( "mpl.xml" );
- // 测试
- int right = 0;
- CvMat* output = cvCreateMat( 1, 36, CV_32F );
- for(int i=0; i<count; i++)
- {
- CvMat input;
- cvGetRow( &inputs, &input, i );
- mlp.predict( &input, output );
- CvPoint max_loc = {0,0};
- cvMinMaxLoc( output, NULL, NULL, NULL, &max_loc, NULL );
- int best = max_loc.x;// 识别结果
- int ans = -1;// 实际结果
- for(int j=0; j<36; j++)
- {
- if( outputs.data.fl[i*(outputs.step/4)+j] == 1.0f )
- {
- ans = j;
- break;
- }
- }
- cout<<(char)( best<10 ? '0'+best : 'A'+best-10 );
- cout<<(char)( ans<10 ? '0'+ans : 'A'+ans-10 );
- if( best==ans )
- {
- cout<<"+";
- right++;
- }
- //cin.get();
- cout<<endl;
- }
- cvReleaseMat( &output );
- cout<<endl<<right<<"/"<<count<<endl;
- cvReleaseMat( &batch );
- system( "pause" );
- return 0;
- }
上面的代码都是vc6控制台程序,OpenCV入门的都懂的吧。
发表于 @ 2009年05月04日 09:33:00 | 评论( 11 ) | 举报| 收藏
旧一篇:控制台的小游戏 | 新一篇:GPS/GPRS定位
- 查看最新精华文章 请访问博客首页相关文章
- ACM_1906
- 刚学C写的东西,纪念下:)
- 用C语言绘制中空的N边形
- RGB和HSV的相互转换的代码
- zoj 2857
- 嵌入式系统C语言编程大赛初赛
- itoa
- C/C++的大小写转换方法
- loven_11 发表于2010年5月21日 16:50:39 IP:举报回复删除
- Hi, 孙文赟 我正在尝试如何使用ML的训练与识别技术. 可是刚开始无从下手, 借由你的这篇范例, 有了那么点认识了. 请问下, 第二段代码中的batch是什么意思啊? 是letter_recog.cpp里面的"./letter-recognition.data"? 我看了opencv2.0的sample里面的这个例子, 能跑,但是生成的文件看了很费解, 不是很明白是什么意思. 我用你的例子,将上面的那个data导入进去了, 也生成一个mpl.xml文件, 但是再跑第一个例子, 什么都解析不出来. 我使用的内容: 1. sample/1.jpg来自这个网页的截屏 2. 原始data使用的opencv2.0/sample/c/letter-recognition.data 3. 代码均来自你的这个页面 希望能得到你支持, 不胜感激啊. QQ & MSN: loven_11@163.com Email: lu_feng@hoperun.com
- anders0821 发表于2010年5月26日 16:40:12 IP:举报回复删除
- 回复 loven_11: batch是一个二进制格式的文件,用它把人工输入的教师数据保存起来,对于网络学习来讲就是样本输入了,你可以编程序查看或者用WinHEX查看(其实数据太多也看不出什么) 你那边只有1张网页的截屏是不够建立mlp的我用了100张 你的mlp.xml肯定和我这里产生的不一样 letter_recog.cpp比我这个简单点,没有图像预处理部分,你甚至可以试着做一个更简单的异或问题,你会有所收获的
- loven_11 发表于2010年5月28日 12:25:27 IP:举报回复删除
- 回复 anders0821:感谢你给我回复啊. 我这两天一直在摸索中, 麻烦你帮我看下我理解的一整套还对啊. 1. 我准备好了26张字母的图片(黑底白字), 然后用findContours得到每个字母的像素值, 最后resize成8*8的矩阵大小; 2. 然后将这些像素按照A,x,x,x,x,x,x...形式保存在文件中 3. 用CvANN_MLP的train方法,将目标值与输入值传入其中,进行训练,最后生成一个xml文件 4. 使用CvANN_MLP加载这个xml, 我做了一张包含多个字母的图片,进行识别. 我试验的思路大致如上, 有不对的地方还望能指正我一下啊.
- loven_11 发表于2010年5月28日 12:25:51 IP:举报回复删除
- 我现在碰到些问题是, 1) 按照你的例子里面的findContours时,用了CV_RETR_CCOMP双层结构, 结果在遍历这些contours的时候,总是找不全,不知道问题出在哪; 2) 你给的例子中的处理方式,是不是对字体要求不能太小的,否则不能识别? 3) 我在生成data数据的时候, 是否还能再经过一些变化或者处理,能减少输入数据的长度呢? 譬如你的例子中用的是256(16*16), 我看opencv自带的例子中, 才16个, 这个是我比较费解的地方,为什么opencv的letter.data里面才那么一点输入数据啊. 用的时候,应该怎么生成这些输入数据的. 啊, 写了那么,希望您能有耐心看下来啊. 再次谢谢了啊.
- anders0821 发表于2010年5月30日 19:03:47 IP:举报回复删除
- 回 复 loven_11: 我这个里是将连通区域,在保持宽高比的情况下,规格化(缩放)到16*16像素的二值图像上来,总共256个输入,这是一种比较笨的方法,不是我最先提出 的,但实验表明确实有用;CV范例上那个16个特征是从标准库(代码最前注释有讲)得到的,它们的含义分别为x y重心x平方之类的,专门用于某种印刷体英文识别。 findContours的用法你参考手册上试试看,这个不是难点
- loven_11 发表于2010年6月1日 15:34:16 IP:举报回复删除
- 回复 anders0821:谢谢, 我平时看东西比较粗心大意, 尤其是对英文反应很愚钝, 没注意那里描述. 我先看看这个网址的内容吧 http://archive.ics.uci.edu/ml/datasets/Letter+Recognition
- loven_11 发表于2010年6月3日 10:26:04 IP:举报回复删除
- 回复 anders0821:你有邮箱或者即时通讯工具(MSN,GTALK)么? 有些琐碎的问题希望能请教你下啊, 在这上面交流起来比较麻烦,且慢啊
- loven_11 发表于2010年6月3日 10:27:09 IP:举报回复删除
- 我的邮箱是 lu_feng@hoperun.com, Msn是 loven_11@163.com .
- bios8086 发表于2010年10月5日 15:03:01 IP:218.95.73.*举报回复删除
- 回复 loven_11: 哥们 你还在研究这个东西吗?
- crystal8700 发表于2010年11月29日 11:06:12 IP:202.203.41.*举报回复删除
- 我现在正在做分类,就是从我提取出来的轮廓中提取出若干个特征,然后跟据这些特征值来分类。关于怎么分类没有思路,还望多多指典!
- anders0821 发表于2011年3月20日 16:56:03 IP:114.226.193.*举报回复删除
- 回复 crystal8700: 关键是特征提取困难,分类的方法很多,且比较成熟。CV提供的神经网络是可以考虑使用的
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别技术
- 验证码识别与反识别技术
- 图像识别技术 验证码识别
- 验证码识别技术专题
- java面向对象程序设计(三)
- java面向对象程序设计(四)
- java面向对象程序设计(五)-----异常处理
- java面向对象程序设计(六)-----包
- C++ 引用的作用和用法
- 验证码识别技术
- MFC中实现用DC画线
- 欢迎本校各位同学加入烟台大学CSDN俱乐部
- JSON入门详解-转载
- matlab编写的进退法,黄金分割法,抛物线法(二次插值法),wolfe不精确一维搜索
- 原来还有D语言。。。
- 新手C++
- MSP430F147无线温度接收
- MSP430F5438无线温度发送