图像识别基于形态学和模板匹配实现扑克牌识别matlab源码
Posted Matlab走起
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图像识别基于形态学和模板匹配实现扑克牌识别matlab源码相关的知识,希望对你有一定的参考价值。
一、简介
1 灰度化 (grayscale)
将彩色图像转化为灰度图像的过程称为图像灰度化。彩色图像中的像素值由RGB三个分量决定,每个分量都有0-255(256种)选择,这样一个像素点的像素值可以有1600万种可能(256*256*256),而灰度图的像素点的像素值是RGB三个分量值相同的一种特殊的彩色图像, 只有256种可能。所以在图像处理中,往往将各种图像首先灰度化成灰度图像以便后续处理,降低计算量。灰度是指只含亮度信息,不含色彩信息的图像。黑白照片就是灰度图,特点是亮度由暗到明,变化是连续的。灰度图像的描述与彩色图像一样仍然反映了整幅图像的整体和局部的色度和亮度等级的分布和特征,
使用灰度图的好处:
① RGB的值都一样。
② 图像数据即调色板索引值,就是实际的RGB值,也就是亮度值。
③ 因为是256色调色板,所以图像数据中一个字节代表一个像素,很整齐。
所以,做图像处理时一般都采用灰度图。
要表示灰度图,就需要把亮度值进行量化,有四种方法:
(1)分量法
将彩色图像中的三分量的亮度作为三个灰度图像的灰度值,可根据应用需要选取一种灰度图像。
(2)最大值法
将彩色图像中的三分量亮度的最大值作为灰度图的灰度值。
(3)均值法
将彩色图像中的三分量亮度求平均得到灰度图的灰度值。
(4)加权平均法
根据重要性及其它指标,将三个分量以不同的权值进行加权平均。由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像,f(i,j)=0.30R(i,j)+0.59G(i,j)+0.11B(i,j))。
2 二值化(binaryzation)
图像的二值化是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果。将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然可以反映图像整体和局部特征的二值化图像。所有灰度大于或等于阀值的像素被判定为属于特定物体,其灰度值为255,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。在数字图像处理中,二值图像占有非常重要的地位,首先,图像的二值化有利于图像的进一步处理,使图像变得简单,而且数据量减小,能凸显出感兴趣的目标的轮廓。其次,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像。
二值化的常用算法有:
全局二值化: 一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,最常用的方法就是设定一个全局的阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。将大于T的像素群的像素值设定为白色(或者黑色),小于T的像素群的像素值设定为黑色(或者白色)。全局二值化,在表现图像细节方面存在很大缺陷。为了弥补这个缺陷,出现了局部二值化方法。
局部二值化:按照一定的规则将整幅图像划分为N个窗口,对这N个窗口中的每一个窗口再按照一个统一的阈值T将该窗口内的像素划分为两部分,进行二值化处理。局部二值化也有一个缺陷。这个缺陷存在于那个统一阈值的选定。这个阈值是没有经过合理的运算得来,一般是取该窗口的平局值。这就导致在每一个窗口内仍然出现的是全局二值化的缺陷。为了解决这个问题,就出现了局部自适应二值化方法。
局部自适应二值化:在局部二值化的基础之上,将阈值的设定更加合理化。该方法的阈值是通过对该窗口像素的平均值E,像素之间的差平方P,像素之间的均方根值Q等各种局部特征,设定一个参数方程进行阈值的计算,例如:T=a*E+b*P+c*Q,其中a,b,c是自由参数。这样得出来的二值化图像就更能表现出二值化图像中的细节。
3 反色(inverse)
反色的实际含义是将R、G、B值反转。若颜色的量化级别是256,则新图的R、G、B值为255减去原图的R、G、B值。这里针对的是所有图,包括真彩图、带调色板的彩色图(又称为伪彩色图)、和灰度图。真彩图不带调色板,每个象素用3个字节,表示R、G、B三个分量。所以处理很简单,把反转后的R、G、B值写入新图即可,比如一个点的颜色为(0,0,0),反色后为(255,255,255)。带调色板的彩色图,其位图中的数据只是对应调色板中的一个索引值,我们只需要将调色板中的颜色反转,形成新调色板,而位图数据不用动,就能够实现反转。
二、源代码
function varargout = poker(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @poker_OpeningFcn, ...
'gui_OutputFcn', @poker_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin & isstr(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
% --------------------------------------------------------------------
function poker_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
global IMAGE;global POKER;global GRAY;global BW;global BWSTR;
IMAGE=0;
POKER=0;
GRAY=0;
BW=0;
BWSTR=0;%全局变量初始化为0
% --------------------------------------------------------------------
function varargout = poker_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
% --------------------------------------------------------------------
function file_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function new_Callback(hObject, eventdata, handles)
global IMAGE;
global POKER;
global GRAY;
global BW;
global BWSTR;
name=0;
[name,path]=uigetfile({'*.bmp';'*.jpg';'*,tif'},'打开图像');
if name==0;
return;%没有打开图像
end
IMAGE=imread(strcat(path,name));%成功打开图像
POKER=0;GRAY=0;BW=0;BWSTR=0;%其他图像复位
subplot(1,1,1),imshow(IMAGE),title('扑克纸牌图像');
% --------------------------------------------------------------------
function operate_Callback(hObject, eventdata, handles)
% --------------------------------------------------------------------
function rectify_Callback(hObject, eventdata, handles)
global IMAGE;
global POKER;
if IMAGE==0;%未打开图像
msgbox('请先打开一幅扑克图像','错误','error');
else
tic;%计算校正与定位用时
POKER=rectify(IMAGE);
if toc>5%设置超时时间为3秒
msgbox('图像校正定位超时','错误','error');
return;
end
time=num2str(toc);
str=strcat('校正与定位耗时',time,'秒');
subplot(1,1,1),imshow(POKER),title('扑克纸牌');
msgbox(str,'消息');
end
% --------------------------------------------------------------------
function gray_Callback(hObject, eventdata, handles)
global IMAGE;
global POKER;
global GRAY;
if IMAGE==0%未打开图像
msgbox('请先打开一幅扑克图像','错误','error');
elseif POKER==0%未进行图像校正
msgbox('请先对图像进行校正定位','错误','error');
else
GRAY=rgb2gray(POKER);
subplot(1,1,1),imshow(GRAY),title('图像灰度化');
end
% --------------------------------------------------------------------
function binary_Callback(hObject, eventdata, handles)
global IMAGE;
global POKER;
global GRAY;
global BW;
if IMAGE==0%未打开图像
msgbox('请先打开一幅扑克图像','错误','error');
elseif POKER==0%未进行图像校正
msgbox('请先对图像进行校正定位','错误','error');
elseif GRAY==0%未进行图像灰度化
msgbox('请先对图像进行灰度化','错误','error');
else
bw=im2bw(GRAY,ostu(GRAY));
BW=logical(abs(double(bw)-1));
subplot(1,1,1),imshow(BW),title('图像二值化');
end
% --------------------------------------------------------------------
function getsymstr_Callback(hObject, eventdata, handles)
global IMAGE;
global POKER;
global GRAY;
global BW;
global BWSTR;
if IMAGE==0%未打开图像
msgbox('请先打开一幅扑克图像','错误','error');
elseif POKER==0%未进行图像校正
msgbox('请先对图像进行校正定位','错误','error');
elseif GRAY==0%未进行图像灰度化
msgbox('请先对图像进行灰度化','错误','error');
elseif BW==0%未进行图像二值化
msgbox('请先对图像进行二值化','错误','error');
else
[m,n]=size(GRAY);
pokerstr=GRAY(2:m/2,n/20:n/5.5);%字符粗略定位
bw=im2bw(pokerstr,ostu(pokerstr));
bw1=bwmorph(bw,'clean');%清除孤立点
bw2=logical(abs(double(bw)-1));%二值图像反色
bw3=reduce(bw2);%清除连续不跳变边缘影响,自定义函数reduce
[m,n]=size(bw3);
temp=sum(bw3);shadow(2:n+1)=temp;shadow(1)=0;shadow(n+2)=0;
for i=2:n+1
if shadow(i)~=0&shadow(i-1)==0&shadow(i+1)==0%出现孤立线条
for j=1:m
bw3(j,i-1)=0;%删除孤立线条列
end
end
end
[m,n]=find(bw3);
BWSTR=bw3(min(m):max(m),min(n):max(n));
subplot(1,1,1),imshow(BWSTR),title('纸牌特征字符');
end
% --------------------------------------------------------------------
function recognition_Callback(hObject, eventdata, handles)
global IMAGE;
global POKER;
global GRAY;
global BW;
global BWSTR
%纸牌字符模板,34*22投影
str1=[6 6 6 6 8 8 10 10 10 10 8 8 8 8 10 10 8 8 8 8 12 12 16 16 12 12 8 8 8 8 16 16 16 16];%A
str2=[10 10 16 16 12 12 12 12 12 12 6 6 4 4 8 8 8 8 6 6 6 6 6 6 6 6 8 8 10 10 22 22 22 22];%2
str3=[22 22 14 14 10 10 8 8 8 8 8 12 12 14 14 6 6 4 4 4 4 4 4 4 4 8 8 8 12 12 18 18 12 12];%3
str4=[2 2 4 4 6 6 8 8 10 10 12 12 10 10 10 10 8 8 10 10 12 12 20 20 22 22 6 6 6 6 6 6 8 8];%4
str5=[18 18 16 16 4 4 4 4 4 16 16 16 16 6 6 4 4 4 4 4 4 4 4 4 4 10 12 12 16 16 12 12 2 2];%5
str6=[9 9 15 15 7 7 5 5 3 3 5 5 14 14 18 18 12 12 9 9 9 9 11 11 11 11 7 7 10 10 14 14 11 11];%6
str7=[15 15 22 22 14 14 9 9 5 5 5 5 5 5 4 4 4 4 6 6 4 4 4 4 6 6 4 4 4 4 4 4 4 4];%7
str8=[10 10 16 16 10 10 6 6 8 8 6 6 12 12 14 14 14 14 10 10 8 8 8 8 8 8 8 8 14 14 18 18 10 10];%8
str9=[14 14 16 16 8 8 8 8 12 12 12 10 10 12 12 12 12 18 18 16 16 4 4 4 4 6 6 6 12 12 14 14 8 8];%9
str10=[10 10 16 16 14 14 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 16 16 16 16 10 10];%10
str11=[13 13 11 11 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 9 9 9 9 14 14 13 13 4 4];%J
str12=[11 11 10 10 10 10 6 6 6 6 6 6 6 6 6 6 6 10 10 14 14 16 16 12 12 10 10 10 10 10 18 18 12 12];%Q
str13=[20 20 20 20 12 12 10 10 10 10 10 10 8 8 12 12 12 12 12 12 10 10 10 10 10 10 8 8 10 10 18 18 20 20];%K
STR=[str1;str2;str3;str4;str5;str6;str7;str8;str9;str10;str11;str12;str13];
%纸牌花形模板,24*20投影
style1=[4 4 6 6 8 8 12 12 16 16 16 16 20 20 20 20 20 20 14 14 6 6 6 6];%黑桃
style2=[12 12 20 20 20 20 20 20 18 18 16 16 14 14 12 12 8 8 6 6 4 4 2 2];%红桃
style3=[4 4 8 8 10 10 10 10 8 8 16 16 20 20 20 20 20 20 12 12 4 4 4 4];%梅花
style4=[2 2 4 4 6 6 12 12 16 16 20 20 20 20 16 16 12 12 6 6 6 6 2 2];%方片
STYLE=[style1;style2;style3;style4];
if IMAGE==0%未打开图像
msgbox('请先打开一幅扑克图像','错误','error');
elseif POKER==0%未进行图像校正
msgbox('请先对图像进行校正定位','错误','error');
elseif GRAY==0%未进行图像灰度化
msgbox('请先对图像进行灰度化','错误','error');
elseif BW==0%未进行图像二值化
msgbox('请先对图像进行二值化','错误','error');
elseif BWSTR==0%未提取特征
msgbox('请先提取图像字符','错误','error');
else
sym=imclose(BWSTR,strel('disk',3));%粗略估算特征面积大小
shadow=sum(sym);
if max(shadow)>=40%面积过大,识别为为JOKER
result=strcat('识别结果:','JOKER');
msgbox(result,'消息','warn');
else
sym=bwmorph(BWSTR,'clean');%清除孤立点
shadow=(sum(sym,2))';%侧面投影
len=length(shadow);
for i=2:len-1%搜索数字符号与花形符号的分界点
if shadow(i)~=0&shadow(i+1)==0%检测到靠近数字一边的边界
bonder1=i+1;
i=bonder1;
continue;
end
三、运行结果
四、备注
完整代码或者仿真咨询添加QQ1575304183
以上是关于图像识别基于形态学和模板匹配实现扑克牌识别matlab源码的主要内容,如果未能解决你的问题,请参考以下文章
纸牌识别基于matlab形态学扑克牌识别含Matlab源码 1352期
车牌识别基于matlab GUI模板匹配车牌识别含Matlab源码 958期