基于BP网络的数字验证码识别系统 【验证码识别】基于bp网络,基于计算机视觉,matlab代码,含GUI界面 功能: 构建bp网络,样本训练,网络检验 生成制作数字验证码,多方法识别验证码。 步骤:灰度化,二值化,中值滤波,去噪,分割字符,BP识别。

数字验证码识别一直是个挺有意思的实战项目。今天咱们用Matlab撸个带GUI界面的BP神经网络识别系统,顺便聊聊那些踩过的坑。先上效果图镇楼——识别率能到92%左右,对付普通四位数字验证码够用了。

先说验证码生成,毕竟训练样本得自己造。用Matlab的绘图功能搞点带扭曲的数字,加点干扰线和噪点:

function create_captcha()
    img = zeros(80,200,'uint8');
    for i=1:4
        num = randi([0,9]);
        position = [i*40-35 20]; 
        img = insertText(img, position, num,'FontSize',40,'BoxOpacity',0);
    end
    img = imnoise(img,'salt & pepper',0.05); % 加点椒盐噪声
    imwrite(255*img,['samples/',num2str(randi(10000)),'.png']);
end

这段代码生成了白底黑字的数字,加了位置偏移和噪声。注意insertText的位置参数要调,不然字符会重叠。建议生成2000+样本,别舍不得硬盘空间。

预处理环节最费劲。先灰度化简单,rgb2gray一行搞定。但二值化阈值得动脑子:

gray = rgb2gray(img);
thresh = graythresh(gray)*0.8; % 系数自己试出来的
bw = imbinarize(gray, thresh);

为什么用0.8?因为有些验证码背景有渐变,直接用Otsu容易误伤。中值滤波倒是标准操作:

filtered = medfilt2(bw,[3 3]);

去噪后得分割字符,这里用投影法找边界:

vertical_sum = sum(~filtered,1);
split_pos = find(diff(vertical_sum>2)); % 阈值2根据实际情况调

分割完记得resize成统一尺寸,我用的24x24像素。这里经常遇到字符粘连,可以加个腐蚀操作:

se = strel('square',2);
eroded = imerode(filtered,se);

重点来了——BP网络搭建。输入层24x24=576节点,隐层用120个,输出层10节点对应0-9:

net = feedforwardnet([120]);
net.layers{1}.transferFcn = 'logsig'; % 隐层用sigmoid
net.trainFcn = 'traingdx'; % 带动量的梯度下降
net.divideParam.trainRatio = 0.8;

参数设置有个坑:初始学习率别超过0.1,不然容易震荡。样本要记得打乱顺序,不然网络会"偏科"。

训练时发现个现象:当训练误差降到0.5%以下,测试误差反而上升,典型的过拟合。对策是早停法+数据增强——把训练样本做随机旋转(±15度)和平移(±2像素)。

最后在GUI里集成整个流程,回调函数里关键代码:

function recognize_Callback()
    img = preprocess(imread('test.png')); % 预处理流水线
    chars = segment(img); % 字符分割
    for k=1:4
        input = double(chars{k}(:))'; 
        output = sim(net, input); % 前向传播
        [~,result(k)] = max(output);
    end
    set(result_text,'String',num2str(result-1)); 
end

实战中发现,数字"5"和"6"容易混淆,解决方法是在样本里增加这两种字的变体。还有个反直觉的技巧——适当保留一些噪声,反而能提升模型鲁棒性。

完整代码在GitHub(假装有链接),注意路径设置和MATLAB版本要求R2018b以上。下回试试用CNN搞这个,准确率应该能再涨5个点,不过训练时间嘛...你懂的。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐