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

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
基于特征匹配的英文印刷字符识别代码自己的注释_第1张图片

你可能感兴趣的:(matlab,图像处理)