基于特征匹配的英文印刷字符识别代码自己的注释

2019-04-15 14:28发布

function MainForm global bw; global bl; global bll; global s; global fontSize; global charpic; global hMainFig; global pic; global hText; clc; close all; warning off all; %目录检,如果当前目录不存在pic文件,则创建 if ~exist(fullfile(pwd, 'pic'), 'dir') mkdir(fullfile(pwd, 'pic')); end picname = fullfile(pwd, 'image.jpg'); pic = imread(picname);%读取图片 s = size(pic); %计算图片尺寸--s为二维/三维矩阵 if length(s) == 3 pic = rgb2gray(pic);%如果s是三维,表明是rgb图片,转为灰度 end bw = im2bw(pic, 0.7);%二值化 bw = ~bw; %二值图像取反,将英文字母部分变为1,背景为0 for i = 1 : s(1) %扫描每一行 if sum(bw(i,:) ~=0) > 0 %如果找到一行的所有像素加起来>0 FontSize_s = i; %表明从这行开始有字,前面均为空白 break; end end for i = FontSize_s : s(1) %从有字的那行像素开始扫描 if sum(bw(i,:) ~=0) == 0 %直到有一行的所有像素加起来得0 FontSize_e = i; %表明从这行之后为空白 break; end end FontSizeT = FontSize_e - FontSize_s;%字体的高度 fontName = '宋体'; fontSize = FontSizeT; bw1 = imclose(bw, strel('line', 4, 90));%对图像进行闭运算,先加粗再细化 %figure,imshow(bw1); bw2 = bwareaopen(bw1, 20);%删除bw1中面积小于20的对象 bwi2 = bwselect(bw2, 368, 483, 4);%选中一个对象,在图像中是问号的所在位置,绝对是个大缺陷! bw2(bwi2) = 0;%令此对象=0,即删除问号 bw3 = bw .* bw2;%过滤掉标点符号 bw4 = imclose(bw3, strel('square', 4));%闭运算,把单词闭合成一个区域 % figure,imshow(bw); % figure,imshow(bw2); % figure,imshow(bwi2); % figure,imshow(bw3); % figure,imshow(bw4); [Lbw4, numbw4] = bwlabel(bw4);%把每个单词(此时已连通)贴上标签 %Lbw4为贴标签之后的矩阵,numbw4为标签(即单词)个数 stats = regionprops(Lbw4);%获取区域的某个属性(面积、最小包围矩形的坐标长宽等)的值 %imshow(bw);hold on; for i = 1 : numbw4 tempBound = stats(i).BoundingBox;%获取每个连通区域的最小矩形(左上角坐标、长宽) %rectangle('position',tempBound,'edgecolor','r'); tempPic = imcrop(pic, tempBound);%在原图中,剪裁单词区域 tempStr = fullfile(pwd, sprintf('pic\%03d.jpg', i));%获取存放路径,将剪裁单词命名 imwrite(tempPic, tempStr);%将剪裁的单词命名保存 end [bl, num] = bwlabel(bw1, 4);%bw1为粗化后未去标点,未连通的单词 chars = [char(uint8('A'):uint8('Z')), uint8('a'):uint8('z'), uint8('0'):uint8('9')]; %chars保存26个大写字母和小写字母以及0~9数字 eleLen = length(chars);%26+26+10=62 charpic = cell(1,eleLen);%创建62个数组 %%%%%%%%以下先生成宋体的字符集的图片,然后截图保存,用于后面的匹配%%%%%%%%%%%%%%%%%% %hf1 = figure('Visible', 'Off');%后台建立窗口,不显示,返回窗口句柄 hf1 = figure; %%%%set (gcf,'Position',[400,100,300,300], 'color','y') imshow(zeros(40,40));%建立一块0矩阵,以下在空矩阵上写出一个宋体18号的字母'a' h = text(15, 15, 'a', 'Color', 'w', 'Fontname', fontName, 'FontSize', fontSize); for p = 1 : eleLen %1到64 set(h, 'String', chars(p)); %fh = getframe(hf1,[85,58,30,30]);%截屏,此截屏方法不保证截到字符的全部(需改进) % %%%%以下为改进%%%%%%%%% fh=getframe(hf1);%%%%%加 temp = fh.cdata;%获取图像数据 temp = im2bw(temp, graythresh(temp)); [rt,ct]=find(temp==0);%%%(加) temp=temp(min(rt):max(rt),min(ct):max(ct));%%%加 %%%%%%%%以上为改进%%%%%% [f1, f2] = find(temp == 1);%查找包含字符像素的坐标 temp = temp(min(f1)-1:max(f1)+1,min(f2)-1:max(f2)+1);%分割出字符 charpic{p} = temp;%保存字符 end delete(hf1);%截图保存标准字符之后删除句柄 %%%%产生辨识区域,使得鼠标即使指向字符的空心位置也能准确指向字符%%%%%%%%%% bll = zeros(size(bl));%bl为贴标签的未连通图 for i = 1:num %num为字母个数,非单词个数 [f1, f2] = find(bl == i); bll(min(f1):max(f1), min(f2):max(f2)) = i;%包围了字符的整个矩形区域,不管空心实心 end hMainFig = figure(1); imshow(picname, 'Border', 'loose'); hold on;%显示原图 for i = 1 : numbw4 %numbw4为单词个数 tempBound = stats(i).BoundingBox; rectangle('Position', tempBound, 'EdgeColor', 'r');%使用矩形包围单词区域 end hText = axes('Units', 'Normalized', 'Position', [0 0 0.1 0.1]); axis off; set(hMainFig, 'WindowButtonMotionFcn', @ShowPointData); end function ShowPointData(hObject, eventdata, handles) global bw; global bl; global bll; global s; global charpic; global hMainFig; global pic; global hText; p = get(gca,'currentpoint');%获取鼠标点击屏幕的点 x = p(3);%p为2X3矩阵,因为Matlab的坐标为三维坐标,虽然看着是二维 y = p(1);%等价于x=p(1,2),y=(1,1),(为何要xy对调???) if x<1 || x>s(1) || y<1 || y>s(2) return; end curlabel = bll(uint32(x), uint32(y)); if curlabel ~= 0 [f1, f2] = find(bl == curlabel); minx = min(f1); maxx = max(f1); miny = min(f2); maxy = max(f2); tempic = pic(minx:maxx, miny:maxy);%图片中字符位置 temp = bw(minx:maxx, miny:maxy);%二值图像的字符分割出来保存到temp tempIm = zeros(round(size(temp)*2));%创建一个比字符大2倍的0矩阵 tempIm = logical(tempIm);%矩阵转为逻辑矩阵 tempIm(round((size(tempIm, 1)-size(temp, 1))/2):round((size(tempIm, 1)-size(temp, 1))/2)+size(temp, 1)-1, ... round((size(tempIm, 2)-size(temp, 2))/2):round((size(tempIm, 2)-size(temp, 2))/2)+size(temp, 2)-1) = temp; set(0, 'CurrentFigure', hMainFig); imshow(tempIm, [], 'Parent', hText); mincost = 100000; mark = 1; for i = 1 : length(charpic) temp1 = charpic{i}; ss = size(temp); temp1 = imresize(temp1, ss); tempcost = sum(sum(abs(temp - temp1))); if tempcost < mincost mincost = tempcost; mark = i; end end end end