基于MATLAB的图片文字提取和识别——算法复现

基于MATLAB的图片文字提取和识别

基本流程:
彩色图片转成灰度图片
灰度图片二值化:使用阈值分隔,腐蚀膨胀优化显示效果
黑白图片提取出文字区域
文字区域分隔成单个字符
获取识别结果:和字库进行匹配

由于主要为了体验过程,这里直接在word里面写了一些文字,直接截图用于测试。

在这里插入图片描述

图像预处理

I_RGB = imread("words.png");
figure;imshow(I_RGB);title("原始图片");
% 彩转灰
I_GRAY = rgb2gray(I_RGB);  
figure;imshow(I_GRAY);title("灰度图片");
% 阈值分割,使用 Otsu 方法计算全局图像阈值,最大类间方差法
% thresh = graythresh(I_GRAY);
% I_THRESH = im2bw(I_GRAY,thresh);
% I_THRESH = imbinarize(I_GRAY);  %默认使用Otsu方法,有字符被去除
% I_THRESH = imbinarize(I_GRAY,'adaptive','Sensitivity',0.62);
I_THRESH = imbinarize(I_GRAY,0.9);

figure;imshow(I_THRESH);title("阈值处理,二值化");
% 腐蚀膨胀处理,相对亮的区域来说
% 膨胀,使白色区域扩大;
% 腐蚀,使黑色区域扩大;
% Y方向腐蚀
Seed_Y= [1;1;1];
I_TEMP = imdilate(I_THRESH,Seed_Y);
figure;imshow(I_TEMP);title("Y膨胀");
I_TEMP = imerode(I_TEMP,Seed_Y);
figure;imshow(I_TEMP);title("Y腐蚀");

% X方向腐蚀
Seed_X = [1 1 1];
I_TEMP = imdilate(I_TEMP,Seed_X);
figure;imshow(I_TEMP);title("X膨胀");
I_TEMP = imerode(I_TEMP,Seed_X);
figure;imshow(I_TEMP);title("X腐蚀");
% 预处理结果
I_PRE = I_TEMP;

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

字符提取

反色和截取
由于使用的图片是非常标准的,每个字符都连在一起,可以直接用行为零或者列为零作为图像的分隔标准。

% 反色
I_REGION = (I_PRE ~= 1);
figure;imshow(I_REGION);title("反色");

% 区域提取函数(和前面的功能重复了)
I_CUT = cutting(I_REGION);
figure;imshow(I_CUT);title("完整有效区域截取");
% 提取字符
k=0; 
while size(I_CUT,2) > 10
    [word{k+1},I_CUT] = getting(I_CUT);
    k = k+1;
end
cnt = k;


for j = 1:cnt    
    set(gcf,'color',[0.9 0.4 0.2]);%任意RGB色 如果背景是白色的话,会和字符的颜色掺和在一起
    figure(5);subplot(10,5,j);imshow(word{j});title(int2str(j));
    word{j} = imresize(word{j},[40,30]);
    set(gcf,'color',[0.9 0.4 0.2]);%任意RGB色 如果背景是白色的话,会和字符的颜色掺和在一起
    figure(6),subplot(10,5,j);imshow(word{j});title(int2str(j));
end

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

在这里插入图片描述

字符库制作

采用与字符分割相同的方式获取单个字符,进行标注,保存图片

chars = getting_chars_from_file("characters.png");
for i = 1 : size(chars,2)
    name = sprintf("./characters/%c.png",i+64);
    %name = strcat(int2str(i+64),".png");
    imwrite(chars{i},name);
end

在这里插入图片描述

字符匹配及结果

codecollection = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

for p=1:cnt
    alarm = zeros(1,26);
    for o = 1:26
        filename = sprintf("./characters/%c.png",o+'A'-1);
        refer = imread(filename);
        %refer = im2bw(refer);
        for i=1:40
            for j = 1:30
                if(word{p}(i,j)) == refer(i,j)
                    alarm(1,o) = alarm(1,o)+1;
                end
            end
        end

        number = 1;
        for q = 1:26
            if alarm(1,q) > alarm(1,number)
                number = q;
            end
        end
        final(1,p) = codecollection(number);
    end
end
final
final = 'ABCDEFGHIJKLMN'

封装识别接口和测试

final = character_recognition("characters.png")
final = character_recognition("hello.png")
final = character_recognition("matlab.png")

在这里插入图片描述

在这里插入图片描述

函数

function y=cutting(I)   % 获取图像的有效数据区域(多个字符或者单个字符均可使用)
[m,n] = size(I);
top = 1;
bottom = m;
left =1;
right = n;
while sum(I(top,:)) == 0 && top < m
    top = top+1;
end
while sum(I(bottom,:)) == 0 && bottom >= 1
    bottom = bottom - 1;
end
while sum(I(:,left)) == 0 &&  left<n
    left = left+1;
end
while sum(I(:,right)) == 0 && right >= 1
    right = right -1;
end
height = bottom - top;
width = right - 1;
y = imcrop(I,[left,top,width,height]);
end
function [word,result] = getting(I)
word = [];
flag = 0;
y1 = 8;
y2 = 0.5;
% word:字符矩阵、flag:标志位、y1/y2:字符大小阈值
while flag == 0
    [m,n] = size(I);
    wide = 0;
    
    if m==0 | n==0  % 无空余字符,提取完毕
        break;
    end
    % 从左至右寻找为0的列作为分割线,由于前面的处理左侧肯定不为零
    while  (sum(I(:,wide+1)) ~= 0  && wide <= n-2 ) 
        wide = wide + 1;
    end
    
    % 裁剪出第一个字符区域
    temp = cutting(imcrop(I,[1,1,wide,m]));
    [m1,n1] = size(temp);
    if wide < y1 && n1/m1 > y2  %判断是否是一个字符
        I(:,1:wide) = 0;        %判定为无效字符,清零,下面肯定是零
        if sum(sum(I)) ~= 0     %不为零,说明还有字符
            I = cutting(I);
            flag = 1;
        else                    %为零,说明没有字符
            word = []; 
            flag = 1;
        end
    else
        word = cutting(imcrop(I,[1,1,wide,m]));     %有效字符,提取
        I(:,1:wide) = 0;
        if sum(sum(I)) ~= 0
            I = cutting(I);
            flag =  1;
        else
            I = [];
        end
    end
end
result = I;
end
function words = getting_chars_from_file(filename)

I_RGB = imread(filename);
% 彩转灰
I_GRAY = rgb2gray(I_RGB); 
I_THRESH = imbinarize(I_GRAY,0.9);

% 腐蚀膨胀处理,相对亮的区域来说
% 膨胀,使白色区域扩大;
% 腐蚀,使黑色区域扩大;
% Y方向腐蚀
Seed_Y= [1;1;1];
I_TEMP = imdilate(I_THRESH,Seed_Y);
I_TEMP = imerode(I_TEMP,Seed_Y);
% X方向腐蚀
Seed_X = [1 1 1];
I_TEMP = imdilate(I_TEMP,Seed_X);
I_TEMP = imerode(I_TEMP,Seed_X);

% 预处理结果
I_PRE = I_TEMP;

% 反色
I_REGION = (I_PRE ~= 1);

% 区域提取函数(和前面的功能重复了)
I_CUT = cutting(I_REGION);

% 提取字符

k=0; %Wmax: 字符集最大容量
while size(I_CUT,2) > 10
    [words{k+1},I_CUT] = getting(I_CUT);
    k = k+1;
end

% 大小标准化
cnt = k;
for j = 1:cnt    
    words{j} = imresize(words{j},[40,30]);
end

end
function  final = character_recognition(filename)
codecollection = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
word = getting_chars_from_file(filename);
cnt = size(word,2);
for p=1:cnt
    alarm = zeros(1,26);
    for o = 1:26
        char_name = sprintf("./characters/%c.png",o+'A'-1);
        refer = imread(char_name);
        %refer = im2bw(refer);
        for i=1:40
            for j = 1:30
                if(word{p}(i,j)) == refer(i,j)
                    alarm(1,o) = alarm(1,o)+1;
                end
            end
        end

        number = 1;
        for q = 1:26
            if alarm(1,q) > alarm(1,number)
                number = q;
            end
        end
        final(1,p) = codecollection(number);
    end
end
end

遇到问题

  1. 阈值选择,一些字符未被正常提取出来,手动去选择阈值
  2. 代码出现下标越界,定位问题。

总结

二值图像处理

数学形态学图像处理:基于形态学进行图像处理

  • 腐蚀(Erosion)
    子图原点在原图中应被完全包含。
    腐蚀区域会变小,可以消除物体之间的粘连,
  • 膨胀(Dilation)
    目标变大,将对象进行连接起来。
    可以填补空洞,如一个字符不连续
  • 开运算
    先腐蚀后膨胀,消除细小物体、纤细处分离物体、平滑边界,如有细小噪声的图。
    去除图像中的某些部分。
  • 闭运算
    先膨胀后腐蚀,填充空洞、连接物体、平滑边界。

形态学滤波器应用
指纹处理(先开运算在闭运算)
开运算去除细小噪声,但是指纹出现断裂,再执行一次闭运算。

基本形态学办法
提取物体边界:将内部的点删除,原图减去腐蚀结果。
区域填充:膨胀与补集做交集。
细化:中轴变换或者焚烧草地
抽骨架

参考文章

  1. MOOC 数字图像处理大作业
  • 9
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值