【手写数字识别】基于matlab GUI知识库手写数字识别【含Matlab源码 1227期】

997 阅读10分钟

一、手写数字识别技术简介

1 案例背景 手写体数字识别是图像识别学科下的一个分支,是图像处理和模式识别研究领域的重要应用之一,并且具有很强的通用性。由于手写体数字的随意性很大,如笔画粗细、字体大小、倾斜角度等因素都有可能直接影响到字符的识别准确率,所以手写体数字识别是一个很有挑战性的课题。在过去的数十年中,研究者们提出了许多识别方法,并取得了一定的成果。手写体数字识别的实用性很强,在大规模数据统计如例行年检、人口普查、财务、税务、邮件分拣等应用领域都有广阔的应用前景"。 本案例讲述了图像中手写阿拉伯数字的识别过程,对手写数字识别的基于统计的方法进行了简要介绍和分析,并通过开发一个小型的手写体数字识别系统来进行实验。手写数字识别系统需要实现手写数字图像的读取功能、特征提取功能、数字的模板特征库的建立功能及识别功能。

2 理论基础 2.1算法流程 首先,读入手写数字图片进行图像归一化处理,统一尺寸,默认为24x24图像块,并通过ostu算法进行二值化; 其次, 对二值化图像进行图像细化等形态学操作,并按照算法要求进行特征提取;最后,载入模板矩阵进行比对,选用欧式距离测度,得到识别结果。其算法流程图如图所示。 在这里插入图片描述 2.2 特征提取 根据手写数字图像本身的结构特征,通过计算端点、指定方向直线的交叉点个数来作为特征向量。其主要步骤如下。 (1)垂直交点 对细化后的手写数字图像分别在其列宽的:5/12 1/2 7/12处生成垂直的三条直线,提取这三条垂直直线与数字笔划的交点数并存储。 (2)水平交点 对细化后的手写数字图像分别在其列宽的号号处生成水平的三条直线,提取这1/3 1/2 2/3三条水平直线与数字笔划的交点数并存储。 (3)对角交点 对细化后的手写数字图像分别取两条对角直线,提取这两条对角直线与数字笔划的交点数并存储。 由于以上步骤均作用于经细化后的数字图像,其笔划简单且特征稳定,因此对其提取的基本交点及结构端点能反映数字的本质特征,可快速、有效地识别数字字符,并达到较好的识别正确率。 其中,提取笔划结构端点特征的算法如下。 ①目标定位 对细化后的手写数字图像按行从上到下、按列从左到右进行顺序扫描,定位选择黑像素点P作为手写笔划目标。 ②邻域统计 计算黑色像素P的8邻域之和N,若N=1,则像素P为端点,端点计数器加1;否则舍弃该点。 ③遍历图像 遍历整个图像,重复进行目标定位、邻域统计的操作流程,提取端点特征。依据上述对手写数字图像的交点、端点特征提取方法, 本案例中的特征向量VEC由9个分量组成,其排列如下: VEC=[垂直5/12处交点数, 垂直中线交点数, 垂直7/12处交点数,水平1/3处交点数,水平中线交点数,水平2/3处交点数,左对角线交点数,右对角线交点数,端点数]

2.3 模式识别 本案例采用的是基于模式知识库的识别方法,所以系统调研的关键步骤就是对数字字符的结构特征的分析及其模型的构造。因此,本案例首先对09这10个数字字符进行结构分析并建模,然后提取相关特征,最后构造模板库。在实验过程中,我们选择规范手写和自由手写两组样本作为训练样本对知识库进行参数调整,这些训练样本由200个规范手写体样本和200个自由手写体样本组成,通过计算样本对应分量的算术平均值获得知识库中特征向量的每个分量。 通过上述步骤得到的知识库由两套模板组成,在本次实验过程中,我们选择基于模板匹配的识别方法,通过计算欧式距离来衡量匹配程度。识别系统中的特征向量包含9个分量,且计算距离公式是欧式距离: 在这里插入图片描述 因此,在识别过程中分别计算待识别图像与知识库中各个模板特征向量之间的欧式距离,即与09这10个数字逐个比较,选择最小距离对应的数字作为最后的识别结果。

二、部分源代码

function varargout = NumDemo(varargin)
% NUMDEMO MATLAB code for NumDemo.fig
%      NUMDEMO, by itself, creates a new NUMDEMO or raises the existing
%      singleton*.
%
%      H = NUMDEMO returns the handle to a new NUMDEMO or the handle to
%      the existing singleton*.
%
%      NUMDEMO('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in NUMDEMO.M with the given input arguments.
%
%      NUMDEMO('Property','Value',...) creates a new NUMDEMO or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before NumDemo_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to NumDemo_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help NumDemo

% Last Modified by GUIDE v2.5 28-Jun-2021 11:22:33

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @NumDemo_OpeningFcn, ...
                   'gui_OutputFcn',  @NumDemo_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before NumDemo is made visible.
function NumDemo_OpeningFcn(hObject, ~, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to NumDemo (see VARARGIN)

% Choose default command line output for NumDemo
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes NumDemo wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = NumDemo_OutputFcn(~, ~, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;
axis([0 250 0 250]);
clc;

% --- Executes on mouse press over figure background, over a disabled or
% --- inactive control, or over an axes background.
function figure1_WindowButtonDownFcn(~, ~, handles)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global ButtonDown pos1
if strcmp(get(gcf, 'SelectionType'), 'normal')
    ButtonDown = 1;
    pos1 = get(handles.axes1, 'CurrentPoint');
end

% --- Executes on mouse motion over figure - except title and menu.
function figure1_WindowButtonMotionFcn(~, ~, handles)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global ButtonDown pos1
if(ButtonDown == 1)
    pos = get(handles.axes1,'CurrentPoint');
    line([pos1(1,1) pos(1,1)], [pos1(1,2) pos(1,2)], 'Color','Black','LineStyle','-', 'LineWidth',8,'Marker','.', 'MarkerSize',20);
    pos1 = pos;
end

% --- Executes on mouse press over figure background, over a disabled or
% --- inactive control, or over an axes background.
function figure1_WindowButtonUpFcn(~, ~, ~)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global ButtonDown
ButtonDown = 0;


% --- Executes on button press in pushbutton_clear.
function pushbutton_clear_Callback(~, ~, handles)
% hObject    handle to pushbutton_clear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%cla;
cla(handles.axes1);

% --- Executes on button press in pushbutton_save.
function pushbutton_save_Callback(~, ~, handles)
% hObject    handle to pushbutton_save (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[f, p] = uiputfile({'*.bmp'},'Save Image');
str = strcat(p, f);
px  = getframe(handles.axes3);
curImg = frame2im(px);
imwrite(curImg, str,'bmp');

% --- Executes on button press in pushbutton_classify.
function pushbutton_classify_Callback(~, ~, handles)
% hObject    handle to pushbutton_classify (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
%strSample = 'Data.mat';
cla(handles.axes4,handles.axes5,handles.axes6);
load 'Data.mat';
I1=handles.I1;
curFea = GetFeature(I1);
I2 = Normalize_Img(I1);
bw1 = Bw_Img(I1);
bw2 = Thin_Img(bw1);
bw = bw2;
sz = size(bw);
[r, c] = find(bw==1);
rect = [min(c) min(r) max(c)-min(c) max(r)-min(r)];
vs = rect(1)+rect(3)*[5/12 1/2 7/12];
hs = rect(2)+rect(4)*[1/3 1/2 2/3];
pt1 = [rect(1:2); rect(1:2)+rect(3:4)];
pt2 = [rect(1)+rect(3) rect(2); rect(1) rect(2)+rect(4)];
k1 = (pt1(1,2)-pt1(2,2)) / (pt1(1,1)-pt1(2,1));
x1 = 1:sz(2);
y1 = k1*(x1-pt1(1,1)) + pt1(1,2);
k2 = (pt2(1,2)-pt2(2,2)) / (pt2(1,1)-pt2(2,1));
x2 = 1:sz(2);
y2 = k2*(x2-pt2(1,1)) + pt2(1,2);
    axes(handles.axes4);
    imshow(I2,[]); 
    handles.I2 = I2;
    hold on;
    h = rectangle('Position', [rect(1:2)-1 rect(3:4)+2], 'EdgeColor', 'r', 'LineWidth', 2);
    legend(h, '数字区域标记', 'Location', 'South');
    axes(handles.axes5);
    imshow(bw1,[]);
    handles.bw1 = bw1;
    axes(handles.axes6);
    imshow(bw,[],'Border', 'Loose');
    handles.bw = bw;
    hold on;
    h = [];
    for i = 1 : length(hs)
        h = [h plot([1 sz(2)], [hs(i) hs(i)], 'r-')];
    end
    for i = 1 : length(vs)
        h = [h plot([vs(i) vs(i)], [1 sz(1)], 'g-')];
    end
    h = [h plot(x1, y1, 'y-')];
    h = [h plot(x2, y2, 'm-')];
    legend([h(1) h(4) h(7) h(8)], {'水平线', '竖直线', '左对角线', '右对角线'}, 'Location', 'BestOutside');
    hold off;

%yLabel = euclid(curFea);
yLabel = MaskRecon(Data, curFea);
h = warndlg(num2str(yLabel),'识别结果');



% --- Executes on mouse press over axes background.
function axes1_ButtonDownFcn(hObject, eventdata, handles)
% hObject    handle to axes1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)


% --- If Enable == 'on', executes on mouse press in 5 pixel border.
% --- Otherwise, executes on mouse press in 5 pixel border or over pushbutton_clear.
function pushbutton_clear_ButtonDownFcn(hObject, eventdata, handles)
% hObject    handle to pushbutton_clear (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
function testsample = GetFeature(I)
clc;
testsample = zeros(1,9);  %19列的矩阵
%提取特征
I1 = Normalize_Img(I);
bw1 = Bw_Img(I1);
bw2 = Thin_Img(bw1);
bw = bw2;
sz = size(bw);
[r, c] = find(bw==1);
rect = [min(c) min(r) max(c)-min(c) max(r)-min(r)];
vs = rect(1)+rect(3)*[5/12 1/2 7/12];
hs = rect(2)+rect(4)*[1/3 1/2 2/3];
pt1 = [rect(1:2); rect(1:2)+rect(3:4)];
pt2 = [rect(1)+rect(3) rect(2); rect(1) rect(2)+rect(4)];
k1 = (pt1(1,2)-pt1(2,2)) / (pt1(1,1)-pt1(2,1));
x1 = 1:sz(2);
y1 = k1*(x1-pt1(1,1)) + pt1(1,2);
k2 = (pt2(1,2)-pt2(2,2)) / (pt2(1,1)-pt2(2,1));
x2 = 1:sz(2);
y2 = k2*(x2-pt2(1,1)) + pt2(1,2);
if flag
   % figure('Name', '数字识别', 'NumberTitle', 'Off', 'Units', 'Normalized', 'Position', [0.2 0.45 0.5 0.3]);
    %subplot(2, 2, 1); imshow(I1, []); title('原图像', 'FontWeight', 'Bold');
    %subplot(2, 2, 2); imshow(I2, []); title('归一化图像', 'FontWeight', 'Bold');
    axes(handles.axes4);
    imshow(I2,[]); title('归一化图像', 'FontWeight', 'Bold');
    handles.I2 = I2;
    hold on;
    h = rectangle('Position', [rect(1:2)-1 rect(3:4)+2], 'EdgeColor', 'r', 'LineWidth', 2);
  

  %  subplot(2, 2, 3); imshow(bw1, []); title('二值化图像', 'FontWeight', 'Bold');
 

 %   subplot(2, 2, 4); imshow(bw, [], 'Border', 'Loose'); title('细化图像', 'FontWeight', 'Bold');
    hold on;
    h = [];
    for i = 1 : length(hs)
        h = [h plot([1 sz(2)], [hs(i) hs(i)], 'r-')];
    end
    for i = 1 : length(vs)
        h = [h plot([vs(i) vs(i)], [1 sz(1)], 'g-')];
    end
  
    hold off;
end
v{1} = [1:sz(2); repmat(hs(1), 1, sz(2))]';
v{2} = [1:sz(2); repmat(hs(2), 1, sz(2))]';
v{3} = [1:sz(2); repmat(hs(3), 1, sz(2))]';
v{4} = [repmat(vs(1), 1, sz(1)); 1:sz(1)]';
v{5} = [repmat(vs(2), 1, sz(1)); 1:sz(1)]';
v{6} = [repmat(vs(3), 1, sz(1)); 1:sz(1)]';
v{7} = [x1; y1]';
v{8} = [x2; y2]';

for i = 1 : 8
    num(i) = GetImgLinePts(bw, round(v{i})-1);
end
num(9) = sum(sum(endpoints(bw)));
testsample=num;

三、运行结果

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

四、matlab版本及参考文献

1 matlab版本 2014a

2 参考文献 [1] 蔡利梅.MATLAB图像处理——理论、算法与实例分析[M].清华大学出版社,2020. [2]杨丹,赵海滨,龙哲.MATLAB图像处理实例详解[M].清华大学出版社,2013. [3]周品.MATLAB图像处理与图形用户界面设计[M].清华大学出版社,2013. [4]刘成龙.精通MATLAB图像处理[M].清华大学出版社,2015.