基于Matlab的数字识别(摄像头版)

基于Matlab的数字识别(摄像头版)

学校的机器视觉课程发布的大作业课题为基于Matlab的数字识别,但因为疫情缘故,网课又不怎么好,导致这个课程基本没学,这就很为难我了,于是乎我通过大量搜索数字识别,人脸识别,车牌识别的matlab程序,参考了不少大佬写的内容,每个函数我都单独拿出来查看意思和作用,最终弄出来一个看上去还行的matlab数字识别。

这个第一段是主程序,顺序为对数据识别库库进行处理裁剪,开摄像头,将摄像头的图像进行处理,裁剪,对照数据库找出最符合的图片所在的数字库位置,然后返回所识别出来的数字

clear 
clc

 %统一图片大小
y=28;
z=28;
%导入数据库各数字个数
geshu=11;
zongshu=geshu*10;
%导入数据库
 u=[];
 picSize=[y,z];
 shang=1;xia=1;zuo=1;you=1;
 %预处理数据库,要求图片黑底白色数字
for s=0:9
for t=0:geshu-1
        q=im2double(imread(strcat('D:\Documents\MATLAB\shujuku\',num2str(s),'_', num2str(t),'.jpg')));
        q=im2bw(q,0.1);
        [heng,zong]=size(q);
        hs=sum(q);
        hs0=sum(q,2);  %这里表示行之和,这时应该是竖着写了两个数字及其以上,除了那种奇葩写得贼长那种
        hs1=hs0';       %将行之和转置
    while(hs1(xia)==0&&xia<heng)   %找到图中白像素点,即有数字的部分,按行之和找
        xia=xia+1;
    end
    shang=xia;
    while(hs1(shang)>0&&shang<heng)  %按列找找到不存在白像素的列,由于找到上边最先出现白像素的列直到找到最下边没有白像素的行,之间的就是整个数字
        shang=shang+1;
    end
    
    while(hs(zuo)==0&&zuo<zong)   %找到图中白像素点,即有数字的部分,按列之和找
        zuo=zuo+1;
    end
    you=zuo;
    while(hs(you)>0&&you<zong)  %按列找找到不存在白像素的列,由于找到左边最先出现白像素的列直到找到最右边没有白像素的列,之间的就是整个数字
        you=you+1;
    end
    
    q=q(xia:shang,zuo:you);
    
        q=imresize(q,picSize);
        
        u=[u,q];
    shang=1;xia=1;zuo=1;you=1;
end
end
d=[];

%打开摄像头
obj = videoinput('winvideo',1,'MJPG_640x480');
h=preview(obj);
start(obj);
figure;



while ishandle(h)

    frame = getsnapshot(obj);  % 获取帧
    
    %图像增强
    % h=ones(5,5)/25; %过滤器h
 % I=imfilter(I,h);%真彩色增强
 % figure('name','真彩色增强');imshow(I);title('真彩色增强');

 I1=rgb2gray(frame); % RGB图像转灰度图像
 
 I1=imadjust(I1,[0.3,0.7],[]);

 I1=medfilt2(I1);
%  figure,imshow(I1);title('中值滤波');

%边缘检测:sobel,roberts,canny,prewitt等
 I2=edge(I1,'roberts',0.25,'both'); %边缘检测算法,强度小于阈值0.15的边缘被省略掉,'both'两个方向检测(缺省默认)
% figure('name','边缘检测'),imshow(I2);title('robert算子边缘检测') 
 se=[1];
 I3=imerode(I2,se);% 腐蚀Imerode(X,SE).其中X是待处理的图像,SE是结构元素对象
% figure('name','腐蚀后图像'),imshow(I3);title('腐蚀后的图像');
 se=strel('rectangle',[30,30]);% 25X25的矩形 strel???
 I4=imclose(I3,se);%25*25的矩形对图像进行闭运算(先膨胀后腐蚀)有平滑边界作用
%  figure('name','平滑处理'),imshow(I4);title('平滑图像的轮廓');
 I5=bwareaopen(I4,800);% 从二进制图像中移除所有少于2000像素的连接对象,消失的是连续的白色像素数量少于2000的字符
% figure('name','移除小对象'),imshow(I5);title('从对象中移除小对象');
 
 %裁剪程序
[r,c]=find(I5);%找出I5中即只剩下数字的图里白元素所在行列,r记录行,c记录列
nextresult=I5(min(r) :max(r),min(c):max(c));
 subplot(121),imshow(nextresult);title('抓取的数字图');
cj1=min(r) ;%记录裁剪尺寸
cj2=max(r);
cj3=min(c);
cj4=max(c);
[g,w]=size(nextresult);
[splitfs,points]=shuziqiege(nextresult,r,c,g,w);

xs=[splitfs,points];
dechushuzi=[];

jishu0=zeros(1,geshu);jishu1=ones(1,geshu);jishu2=ones(1,geshu)*2;jishu3=ones(1,geshu)*3;jishu4=ones(1,geshu)*4;jishu5=ones(1,geshu)*5;
jishu6=ones(1,geshu)*6;jishu7=ones(1,geshu)*7;jishu8=ones(1,geshu)*8;jishu9=ones(1,geshu)*9;
jishuqi=[jishu0,jishu1,jishu2,jishu3,jishu4,jishu5,jishu6,jishu7,jishu8,jishu9];


x=1;
for m_520=1:size(xs,2)-1
    p=xs{m_520};
    p=imresize(p,picSize);
    for n_520=1:zongshu
        nn=(n_520-1)*z+1;
        ff=n_520*z;
        d=u(1:y,nn:ff);   %取识别库一张图所化为的矩阵
        matchrs(n_520)=corr2(p,d);
    end
    [~,k]=max(matchrs);
    dechushuzi(x)=jishuqi(k);
%     lastresult=strcat(lastresult, fonts(k));
    x=x+1;
end

x=1;


%开始标记

label_str = ['The number is: ' num2str(dechushuzi,'%d') ''];

cj5=cj2-cj1;
cj6=cj4-cj3;
cj=[cj3 cj1 cj6 cj5];
rgb = insertObjectAnnotation(frame, 'rectangle', cj, label_str,'textboxopacity', 0.9, 'fontsize', 18,'color','r');
subplot(122),imshow(rgb),title('数字识别系统');



    
    drawnow
end
delete(obj);

然后下面是数字切割,针对于摄像头图像处理后的切割,程序有对横着顺序写数字或者对竖着顺序写的数字切割处理。

function[splitfs,points]=shuziqiege(nextresult,r,c,g,w)
%r非零元素行
%c非零元素对应列
%w多数字图的长
%g多数字图高
%hs一行w列矩阵,每列数字为g行数字相加,用来找到哪列有数字的白元素
%nextresult所有数字所在的区域
a=1;b=1;c=1;d=1;e=1;i=1;
splitfs={};points=[];

hs=sum(nextresult);  %将图片矩阵转化为一行w列矩阵,每列数字为h行数字相加
hs0=sum(nextresult,2);  %这里表示行之和,这时应该是竖着写了两个数字及其以上,除了那种奇葩写得贼长那种
hs1=hs0';%将行之和转置
if c<g
    while(hs1(c)==0&&c<g)   %找到图中白像素点,即有数字的部分,按行之和找
        c=c+1;
    end
    d=c;
    while(hs1(d)>0&&d<g)  %按列找找到不存在白像素的列,由于找到上边最先出现白像素的列直到找到最下边没有白像素的行,之间的就是整个数字
        d=d+1;
    end
end
    e=d+1;
    if e<g
     while(hs1(e)==0&&e<g)  %按列找找到不存在白像素的列,由于找到下边最先出现白像素的列直到找到最上边没有白像素的行,之间的就是整个数字
        e=e+1;
     end
    end
     
 %判断多数字横向写还是纵向写    
if e<g||7*w<2*g   %这里说明纵向发现第二个数字,这里有一大限制,如果纵向写,却数字在纵向上没有空隙,且还把数字在竖向上写的扁扁的团在一起,这种是我能力有限,没办法编出来
 
  %执行裁剪      
 while(a<g)    %这里是横向裁剪程序,适用于数字竖着写的图
    while(hs1(a)==0&&a<g)   %找到图中白像素点,即有数字的部分,按行之和找
        a=a+1;
    end
    b=a;
    while(hs1(b)>0&&b<g)  %按列找找到不存在白像素的列,由于找到下边最先出现白像素的列直到找到最上边没有白像素的列,之间的就是整个数字
        b=b+1;
    end
    
        
    
    if(b-a>2)    %如果左右能差两列像素
        hresult=nextresult(a:b,:);   %图片按列的横线切割
        [r,c]=find(hresult);
%         result2=hresult(:,min(c):max(c));   %图片按横线切   
        m=min(c);n=max(c); 
        xi=hresult(:,m:n);   %图片按纵线切
        splitfs{i}=xi;
        points=[points;a,b,m,n];%a下,b上,m左,n右
%         subplot(3,6,i),imshow(result2),title('裁剪出的数字');
        i=i+1;
    end
    a=b;
end
        
else
        
while(a<w)   %这里是数字横着写,进行纵向裁剪
    while(hs(a)==0&&a<w)   %找到图中白像素点,即有数字的部分,按列之和找
        a=a+1;
    end
    b=a;
    while(hs(b)>0&&b<w)  %按列找找到不存在白像素的列,由于找到左边最先出现白像素的列直到找到最右边没有白像素的列,之间的就是整个数字
        b=b+1;
    end
    
        
    
    if(b-a>2)    %如果左右能差两列像素
        hresult=nextresult(:,a:b);   %图片按列的竖线切割
        [r,c]=find(hresult);
%         result2=hresult(min(r):max(r),:);   %图片按横线切   
        m=min(r);n=max(r); 
        xi=hresult(m:n,:);   %图片按横线切
        splitfs{i}=xi;
        points=[points;m,n,a,b];%m下,n上,a左,b右
%         subplot(3,6,i),imshow(result2),title('裁剪出的数字');
        i=i+1;
    end
    a=b;
end
end

这个是主程序开头处理的数据库,是我做大作业小组的伙伴们自己写的,所以不标准,要靠我开头程序切割处理下识别才好一些。

在这里插入图片描述
然后这是我开摄像头得到的结果
在这里插入图片描述
在这里插入图片描述
我参考的大佬们程序很多,我列举部分:
插入框文字
摄像头安装
车牌识别
人脸识别
有的大佬博客我找不到了,还请见谅。
学校matlab没怎么教,我也没有让程序整洁的习惯,整个程序它就有点。。。。乱,而且应该有很多地方可以优化,如果有建议希望得到指点,万分感谢。
这个是我程序加数据库压缩包链接matlab数字识别
这个资源积分老是在上涨,都重新上传两次了,不知道咋回事。。。。反正我全部程序都在博客上,数据库可以自己拿一个黑底板用画笔直接画的,资源包有很多积分就下载一下,积分少就不用了

  • 13
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值