OpenCV 数字验证码识别
更新后代码下载链接在此!
!!
点我下载
本文针对OpenCv入门人士。由于我也不是专门做图像的,仅仅是为了完毕一次模式识别的小作业。
主要完毕的功能就是自己主动识别图片中的数字。图片包含正常图片,有划痕图像和有噪点图像。
分别例如以下
先上图。看识别效果!
接下来開始来点干货了:
- opencv的安装与配置:这个要是展开讲能够再写一篇博文了,我当时什么都不会配个opencv麻烦死了,最后參考网上studio2012的配置方法成功了,在此略过。看到这里你的opencv还不能用的话,赶紧别往下看了,先把opencv配好再来吧!
- opencv基本图片操作:
- 由于opencv有2.0 和 3.0 的版本号差别,所以网上搜到的函数或类型都是两种格式,建议用新版的,什么impImage* 类型的都是2.0版本号的写法。我所有使用的是Mat。一定要统一好,不要一会新的一会旧的,会报错的。
- 读图片imread,显示imshow,等待waitKey等等。这些要先熟悉
- opencv的强大之处在于差点儿所有的图像操作它都有现成的函数可供调用,非常方便。多谷歌,一定会有函数已经实现了你想完毕的功能。
- 二值化:不论是原图还是有划痕或噪点的图,背景都不干净。这对识别的影响还是挺不好的,所以要先二值化。把黑白像素点区分的开一些。可是图片右側明显要比左側更暗,所以在阈值选取的时候比較难办,非常难用一个固定的值将两部分图像都二值化得非常理想,所以就用到了逼格更高的自适应二值化(adaptiveThreshold),tips:二值化前先直方图均衡一下效果会更好。
- 中值滤波:针对有噪点和有划痕的图像,中值滤波是非常好的处理方案。中值的參数可调,能够非常好的消除噪音的影响。缺点就是參数不好调啊,调的想死。。
- 模板匹配:模板的来源能够是自己从待识别的图片中抠图,只是我们作业提供了模板图片,所以这一步就能够省掉了。opencv提供了非常强大的matchTemplate函数。能够将给定图片与模板依照你规定的计算方法计算一个类似度的值。并将相应的坐标存储下来。你须要做的仅仅是将值比較大(或小,与你规定计算类似度的函数有关)的图像框出来就可以
- 窗体扫描:为了提高识别率。我设定了一个窗体对原图进行扫描,扫描窗体的移动设定了一点规则,就是假设前一个窗体没有匹配到数字就微调窗体位置,假设匹配到数字就将窗体左轴移动到匹配到的数字的右側。再反复扫描。
基本干货就这么多了。剩下的就是不断的调參数和扫描窗体的位置了,这种方法的缺陷就是针对不同的图片。參数和扫描窗都要变,比方来一张一行或三行的数字,那就必须改动扫描窗体的函数了。还有每一步的步长之类的。还是相当蛋疼的!
以下是部分核心代码
预处理。包含自适应二值化和中值滤波
void preProcess(){ //自适应二值化&中值滤波
Mat out;
//自适应二值化
adaptiveThreshold(source, source, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, adaptiveBiSize, adaptiveBiParam);
//中值滤波
namedWindow("binary");
imshow("binary",source);
waitKey(0);
medianBlur( source, out, medianBlurSize);
namedWindow("medianblur");
imshow("medianblur",out);
waitKey(0);
source = out;
srcResult = out; //用来显示
}
匹配
bool match(Mat src){
int srcW,srcH,templatW, templatH, curtemplatW,curtemplatH,resultH, resultW;
Mat templat,result;
srcW = src.cols;
srcH = src.rows;
double currentMin = 1;
int currentIndex=0;
double minValue, maxValue;
Point minLoc, maxLoc,matchLoc;
/*
** 类似度计算方法
** 0:CV_TM_SQDIFF 平方差匹配法。最好的匹配值为0;匹配越差,匹配值越大
** 1:CV_TM_SQDIFF_NORMED 归一化平方差匹配法
** 2:CV_TM_CCORR 相关匹配法:该方法採用乘法操作;数值越大表明匹配程度越好
** 3:CV_TM_CCORR_NORMED 归一化相关匹配法
** 4:CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配。-1表示最差的匹配。
** 5:CV_TM_CCOEFF_NORMED 归一化相关系数匹配法
*/
int methodType=1;
//循环推断8个数字哪个数字模板最为接近被測试图像
for (int i=0;i<8;i++){
templat = templatVec[i];
templatW = templat.cols;
templatH = templat.rows;
if(srcW < templatW || srcH < templatH)
{
cout <<"模板不能比原图像大" << endl;
return 0;
}
resultW = srcW - templatW + 1;
resultH = srcH - templatH + 1;
result = cvCreateImage(cvSize(resultW, resultH), 1, 1);
matchTemplate(src, templat, result, methodType);
minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc,Mat() );
//假设比当前最小还小,则储存该值,下标和坐标
if (minValue<currentMin){
currentMin = minValue;
currentIndex=i;
matchLoc.x=minLoc.x+window_x;
matchLoc.y=minLoc.y+window_y;
curtemplatW = templatW;
curtemplatH = templatH;
}
}
//cout<<"Min:"<<currentMin<<endl;
//最小值比设定阈值小。则推断识别出这个数字
if (currentMin<threshold){
numresult.push_back(index[currentIndex]);
cout<<"第"<<countnumbers<<"个数字是:"<<index[currentIndex]<<endl;
/*cout<<"左上角坐标为:("<<matchLoc.x<<","<<matchLoc.y<<")"<<endl;
cout<<"右上角坐标:("<<matchLoc.x+templatW<<","<<matchLoc.y<<")"<<endl;
cout<<"左下角坐标:("<<matchLoc.x<<","<<matchLoc.y+templatH<<")"<<endl;*/
countnumbers++;
rectangle(srcResult, matchLoc, cvPoint(matchLoc.x + curtemplatW, matchLoc.y+ curtemplatH), cvScalar(0,0,255));
/*namedWindow("tmpresult");
imshow("tmpresult",srcResult);
waitKey(0);*/
window_x =matchLoc.x+curtemplatW-1;
return true;
}
//比阈值大则判定为非字符。扫描窗右移一个单位
window_x++;
return false;
}
窗体扫描,虚函数须要被实现
virtual void processScan(){
sourceW = source.cols;
sourceH = source.rows;
window_x = 0;
window_y = 3;
//加十以提高容错率
bool last = false;
while(window_x<sourceW-scanWindowW+5){
if (window_x+scanWindowW>sourceW){
window_x = sourceW - scanWindowW;
last = true;
}
Mat tmp = scanWindow(window_x,window_y);
match(tmp);
if (last) break;
}
window_x = 30;
scanWindowH = 35;
window_y=sourceH - scanWindowH;
while (window_x<=sourceW - scanWindowW-10){
Mat tmp = scanWindow(window_x,window_y);
match(tmp);
}
}
针对不同图片建立了不同的类来实现:
//识别有噪点的图像
class noisyPic:public Picture{
public:
noisyPic(){
Picture();
threshold = 0.5;
path="test\\noisy.bmp";
adaptiveBiSize = 17;
adaptiveBiParam= 19;
medianBlurSize = 5;
scanWindowW = 38;
scanWindowH = 38;
}
void displayResult(){
cout<<"当前识别的是有噪点的图像。识别结果为:"<<endl;
for (unsigned int i=0;i<numresult.size();i++){cout<<numresult[i]<<" ";}
cout<<endl;
cout<<"====================================================="<<endl;
namedWindow("final");
imshow("final", srcResult);
waitKey(0);
}
};
//有划痕的图像
class dirtyPic:public Picture{
public:
dirtyPic(){
Picture();
threshold = 0.48;
path="test\\dirty.bmp";
adaptiveBiSize = 21;
adaptiveBiParam= 23;
medianBlurSize = 7;
scanWindowW = 36;
scanWindowH = 38;
}
virtual void displayResult(){
cout<<"当前识别的是有划痕的图像,识别结果为:"<<endl;
for (unsigned int i=0;i<numresult.size();i++){cout<<numresult[i]<<" ";}
cout<<endl;
cout<<"====================================================="<<endl;
namedWindow("final");
imshow("final", srcResult);
waitKey(0);
}
};
主函数
int main()
{
//正常图像,构造函数不指定參数时。默认识别第一张图
//构造函数能够指定识别第几张图。以下以第三张为例
Picture pic = Picture(3);
pic.startRecognize();
//识别有噪声图像
noisyPic noisyPic;
noisyPic.startRecognize();
//识别有划痕图像
dirtyPic dirtyPic;
dirtyPic.startRecognize();
//识别放大缩小图像
scalePic scale = scalePic(1);
scale.startRecognize();
return 0;
}
为了方便童鞋们參考,提供了下载链接,只是要花一点积分的哦!(LZ下别的也是要积分的啊!
)
戳我戳我
OpenCV 数字验证码识别的更多相关文章
- 17、OpenCV Python 数字验证码识别
__author__ = "WSX" import cv2 as cv import numpy as np from PIL import Image import pytess ...
- 使用Python基于OpenCV的验证码识别
Blog:https://blog.csdn.net/qq_40962368/article/details/89312429(Verification_Code_Identification) 步骤 ...
- 简单验证码识别(matlab)
简单验证码识别(matlab) 验证码识别, matlab 昨天晚上一个朋友给我发了一些验证码的图片,希望能有一个自动识别的程序. 1474529971027.jpg 我看了看这些样本,发现都是很规则 ...
- 第二十三节:scrapy爬虫识别验证码(二)图片验证码识别
图片验证码基本上是有数字和字母或者数字或者字母组成的字符串,然后通过一些干扰线的绘制而形成图片验证码. 例如:知网的注册就有图片验证码 首先我们需要获取验证码图片,通过开发者工具我们可以得到验证码ur ...
- python之基于libsvm识别数字验证码
1. 参考 字符型图片验证码识别完整过程及Python实现 2.图片预处理和手动分类 (1)分析图片 from PIL import Image img = Image.open('nums/ttt. ...
- 最邻近算法(KNN)识别数字验证码
应用场景 对于简单的数字型验证码的自动识别.前期已经完成的工作是通过切割将验证码图片切割成一个一个的单个数字的图片,并按照对应的数字表征类别进行分类(即哪些图片表示数字7,哪些表示8),将各种数字 ...
- selenium来识别数字验证码
用python写一爬虫,需要模拟登陆,并且有数字验证码.通过selenium+pytesseract+PIL可以实现验证码识别并登陆.三大步: 用selenium截屏,此时截取的是整个页面的 用PIL ...
- opencv +数字识别
现在很多场景需要使用的数字识别,比如银行卡识别,以及车牌识别等,在AI领域有很多图像识别算法,大多是居于opencv 或者谷歌开源的tesseract 识别. 由于公司业务需要,需要开发一个客户端程序 ...
- 强智教务系统验证码识别 OpenCV
强智教务系统验证码识别 OpenCV 强智教务系统验证码验证码字符位置相对固定,比较好切割 找准切割位置,将其分为四部分,匹配自建库即可,识别率近乎100%,如果觉得不错,点个star吧
随机推荐
- c#中的 数组
数组即是一组相同类型组合在一起,使用一个通用的名称,通过分配的下标访问的数据集合中的元素. 数组是具有相同类型的一组数据.当访问数组中的数据时,可以通过下标来指明.c#中数组元素可以为任何数据类型,数 ...
- Go语言之进阶篇文件传输
一.文件传输 1.文件传输原理 2.文件传输 示例: 发送方: send_file.go package main import ( "fmt" "io" &q ...
- Luban 鲁班 图片压缩 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 【Scala】Scala学习资料
Scala学习资料 java 树形 分类器_百度搜索 决策树分类器-Java实现 - CSDN博客 KNN分类器-Java实现 - CSDN博客 学习:java设计模式—分类 - 飞翔荷兰人 - 博客 ...
- Documentation/PCI/pci-iov-howto.txt
Chinese translated version of Documentation/PCI/pci-iov-howto.txt If you have any comment or update ...
- Extend一个web application没有反应怎么办?
通过SharePoint管理中心Extend一个web application的时候, 点完确定按钮后,没有反应,怎么回事? [解决方法] 多等一会,不要连续点. 等待的过程中看看iis, 过一会 ...
- java 上传图片压缩图片
package com.bitspace.flame.util; import java.io.File; import java.awt.Image;import java.awt.image.Bu ...
- Redis实战总结-Redis的高可用性
在之前的博客<Redis实战总结-配置.持久化.复制>给出了一种Redis主从复制机制,简单地实现了Redis高可用.然后,如果Master服务器宕机,会导致整个Redis瘫痪,这种方式的 ...
- 开源的DirectUI界面库
1. duilib简介 duilib是一个开源的DirectUI界面库,简洁但是功能强大.而且还是BSD的license,所以即便是在商业上,大家也可以安心使用.现在大家可以从这个网站获取到他们所有的 ...
- [React] Write a stateful Component with the React useState Hook and TypeScript
Here we refactor a React TypeScript class component to a function component with a useState hook and ...