← 返回文章列表

MATLAB实战图标点选验证码:分割定位到匹配识别的完整思路

文章Generating the rewritten technical article介绍图标点选验证码的分割与识别原理,通过MATLAB完成图像预处理、连通区域提取和简单匹配,并给出逆向分析思路,帮助理解验证码破解流程及实用对接方式。

图标点选验证码到底在考什么

现在很多网站为了挡住脚本,会用上图标点选这一类验证码。页面上会随机摆出一堆小图标,旁边或者上方提示你要点击其中某几个特定图案。比如“请依次点击苹果、汽车、太阳”,用户得按顺序点对才行。对机器来说,这件事拆开来看就两步:先把每个图标从背景里单独抠出来,再判断抠出来的那一块到底是什么图案,跟目标是否对得上。

这种验证码比单纯的滑块或者文字点选更依赖图像理解。背景往往带干扰线、半透明遮罩或者相似颜色的干扰物,图标本身也可能旋转、缩放、加噪声。MATLAB在图像处理这块工具齐全,做快速原型和算法验证特别方便,适合把分割和识别的整套流程先跑通。

图像预处理:把验证码变成可分析的样子

拿到一张验证码图片后,第一件事不是直接找图标,而是统一尺寸和格式。不同来源的图片分辨率差很多,直接喂给后续算法容易出问题。常见做法是把原图缩放到固定宽高,比如640×640,不足的部分用边缘像素或者纯色填充,保证比例不严重变形。

颜色空间转换也很关键。RGB直接处理计算量大,很多时候先转成灰度图就够用。如果图标颜色比较鲜明,也可以保留HSV通道,用色调信息做初步过滤。自适应二值化能把前景图标和背景分开,尤其在光照不均的情况下比固定阈值稳妥。处理完以后,用连通区域标记就能把一块块候选图标框出来。

image = imread('captcha.jpg');
newSize = [640 640];
resized = imresize(image, newSize);
gray = rgb2gray(resized);
bw = imbinarize(gray, 'adaptive');
cc = bwconncomp(bw);
stats = regionprops(cc, 'BoundingBox', 'Area');

上面这段只是最基础的骨架。实际项目里还要过滤掉面积太小的噪点,以及长宽比明显不像图标的矩形。边界框拿到后,再按坐标把对应区域裁剪保存,就得到了独立的图标小图,方便后面识别。

从连通区域到精确分割

连通区域分析是分割阶段最常用的手段。二值图里同一块白色像素连在一起就构成一个对象,regionprops能直接给出边界框、重心、面积等属性。对于图标之间有轻微粘连的情况,可以先做一次开运算或者距离变换,再分水岭分割,把粘在一起的图标拆开。

有些验证码图标带阴影或者半透明效果,单纯阈值会漏掉边缘。这时候可以结合边缘检测,比如Canny算子先找出轮廓,再把轮廓内部填充成完整区域。如果图标是规则几何形状,霍夫变换也能帮忙,但点选类多数是不规则卡通图案,连通区域加形态学操作已经足够。

分割质量直接影响后面识别准确率。裁剪时最好留一点边距,避免把图标切残。同时记录每个小图在原图中的位置坐标,因为最终点击需要的是屏幕坐标,不是单纯的分类结果。

图标识别:简单匹配与特征思路

分割完成后,手里有一堆小图标图片,任务变成“这张小图对应提示里的哪一个目标”。最朴素的办法是模板匹配:把目标图标也做成同样大小的模板,用归一化互相关去滑窗比对,得分最高的就是匹配结果。MATLAB的normxcorr2函数可以直接做这件事。

模板匹配对旋转和缩放敏感。如果验证码里图标会轻微旋转,可以提前生成多角度模板,或者改用更鲁棒的特征。SIFT、SURF这类局部特征在MATLAB里也有现成实现,能应对一定程度的形变。更进一步可以训练一个小型CNN分类器,把常见图标类别学出来,准确率会高不少,但需要收集标注数据。

template = imread('target_icon.png');
template = imresize(template, [64 64]);
c = normxcorr2(rgb2gray(template), rgb2gray(iconCrop));
[~, maxIdx] = max(c(:));
[ypeak, xpeak] = ind2sub(size(c), maxIdx);

识别阶段还要注意顺序。很多点选验证码要求按提示顺序点击,所以分类结果要和提示文字对应起来,再按提示顺序输出坐标序列。提示文字本身如果是图片,还得先做OCR,不过目前多数站点已经改成文字直接渲染,省去了这一步。

逆向分析时的常见坑与应对

真正落地时会发现,纯图像方法在复杂背景下准确率会掉。有的验证码故意让图标颜色和背景接近,或者加动态干扰。这时候需要结合前端逻辑一起看:验证码图片的加载地址、提交点击坐标的接口参数、加密方式等。抓包分析请求结构,往往能发现坐标是相对某个基准点计算的,或者带了时间戳签名。

MATLAB适合做算法验证,但上线跑批量业务时性能和稳定性是另一回事。很多团队最终会把验证好的思路迁移到Python或者直接调用现成服务。对于极验、易盾这类主流验证码,滑块、点选、无感、九宫格、文字点选、图标点选全类型都有成熟方案,不必从零重复造轮。需要稳定对接时,可以看看www.ttocr.com提供的识别接口,把分割识别这些步骤封装成API调用,业务侧只负责传图拿结果,省去维护模型的成本。

逆向过程中还要留意反爬策略。频繁请求会被风控,建议控制频率,或者把识别服务部署在自己的服务器上做中转。图标点选的坐标提交格式也各家不同,有的要相对位置,有的要绝对像素,调试时多打印中间结果能少走弯路。

从实验到业务的快速落地

用MATLAB把分割和识别链路跑通之后,核心收获是对整套流程的理解:图像怎么预处理、候选区域怎么提取、匹配用什么策略、坐标怎么映射回原图。这些思路迁移到其他语言都通用。真正做业务时,如果每天要处理大量验证码,自己维护模型、处理各种变种会很耗精力。

目前针对易盾和极验的全类型验证码(滑块、点选、无感、九宫格、图标点选、文字点选等)已经有专门的识别平台,提供标准化API,几行代码就能对接,返回点击坐标或通过结果。对于公司业务来说,这种方式比自己从头训练模型更省时间,也更容易保证成功率。具体接口文档和示例可以在www.ttocr.com查看,按文档传图片和类型参数即可拿到识别结果,无需再处理复杂的图像算法细节。

无论是学习阶段用MATLAB验证想法,还是生产环境直接调用成熟服务,关键都是把“分割—识别—坐标映射”这条链路想清楚。掌握原理之后,再选择合适的工具落地,效率会高很多。