📄 poker.m
字号:
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
if shadow(i)<=1&shadow(i+1)>1%检测到靠近花形一边的边界
bonder2=i;
break;
end
end
bonder=(bonder1+bonder2)/2;%取两个边界的中间作为符号分界线
SYM1=sym(1:bonder,:);%数字符号
[m,n]=find(SYM1);
SYM1=SYM1(min(m):max(m),min(n):max(n));
SYM1=imresize(SYM1,[34 22]);%模板归一化
SYM2=sym(bonder:len,:);%花形符号
[m,n]=find(SYM2);
SYM2=SYM2(min(m):max(m),min(n):max(n));
SYM2=imresize(SYM2,[24,20]);%模板归一化
shadow1=(sum(SYM1,2))';shadow2=(sum(SYM2,2))';
%字符匹配
errormean=50;sn1=0;
for i=1:13%搜索最佳匹配的模板
temp=STR(i,:);
error=abs(shadow1-temp);
error=mean(error,2);%求绝对均差
if error<errormean;
sn1=i;errormean=error;
end
end
if errormean>=3;%误差过大
sn1=0;
end
%花形匹配
errormean=50;sn2=0;
for i=1:4%搜索最佳匹配的模板
temp=STYLE(i,:);
error=abs(shadow2-temp);
error=mean(error,2);%求绝对均差
if error<errormean;
sn2=i;errormean=error;
end
end
if errormean>=3;%误差过大
sn2=0;
end
%特征映射
switch sn1
case 0
result1='-不能识别出字符'
case 1
result1='A';
case 10
result1='10';
case 11
result1='J';
case 12
result1='Q';
case 13
result1='K';
otherwise
result1=num2str(sn1);
end
switch sn2
case 1
result2='黑桃';
case 2
result2='红桃';
case 3
result2='梅花';
case 4
result2='方片';
otherwise
result2='不能识别出花形';
end
result=strcat('识别结果:',result2,result1);
msgbox(result,'消息','warn');
end
end
% --------------------------------------------------------------------
function about_Callback(hObject, eventdata, handles)
msgbox('欢迎交流:luotiancheng7299@hotmail.com','关于','help');
% --------------------------------------------------------------------
function exit_Callback(hObject, eventdata, handles)
global IMAGE;global POKER;global GRAY;global BW;global BWSTR;
clear IMAGE;clear POKER;clear GRAY;clear BW;clear BWSTR;%清除全局变量
close poker;
% --------------------------------------------------------------------
function figure1_DeleteFcn(hObject, eventdata, handles)
global IMAGE;global POKER;global GRAY;global BW;global BWSTR;
clear IMAGE;clear POKER;clear GRAY;clear BW;clear BWSTR;%清楚全局变量
% -----------------------以下为自定义函数-----------------------------
function str=reduce(bwstr);
%去除边缘
[m,n]=size(bwstr);
temp=ones(m,n);
num=1;
for j=1:n
count=0;
for i=1:m
if bwstr(i,j)==0;
count=0;continue;
else
count=count+1;%连续不跳变点数增加
if count>=m/3;%连续不跳变长度约为1.5个字符宽
break;
end
end
end
if count>=m/3
line(num)=j;
num=num+1;%记录扫描到的最后一行边框
end
end
for i=1:num-1%扫描到的最后一行边框以上的行置为背景
for j=1:m
temp(j,line(i))=0;
end
end
str=logical(double(bwstr).*temp);
%--------------------------------------------------------------------------
function level=ostu(IMAGE)
%最大类间方差ostu算法,求最佳阈值
[m,n,s]=size(IMAGE);
if s==1
image=IMAGE;
end
if s==3
image=RGB2gray(IMAGE);
end
ranks=256;
counts=imhist(image,ranks);
p=counts/sum(counts);omega=cumsum(p);
mu=cumsum(p.*(0:ranks-1)');mu_t = mu(end);
sigma2=0;%otsu类间方差
T=0;%threshold
h=0;
Hmax=0;
w0=0;w1=0;
u0=0;u1=0;
HStore=zeros(1,256);
for i=1:ranks
if (omega(i)==0)|((1-omega(i))==0)
continue;
end;
w0=omega(i);w1=1-w0;
u0=mu(i)/w0;u1=(mu_t-mu(i))/w1;
sigma2=w0*(u0-mu_t).^2+w1*(u1-mu_t).^2;
h=sigma2;HStore(i)=h;
end
Hmax = max(HStore);
isfinite_maxval = isfinite(Hmax);
if isfinite_maxval
idx = mean(find(HStore == Hmax));
level = (idx - 1) / (ranks - 1);
else
level = 0.0;
end
%--------------------------------------------------------------------------
function poker=rectify(rgbimage)
%扑克目标校正且定位函数
grey=rgb2gray(rgbimage);%灰度化图像
ed1=edge(grey,'sobel','both');%灰度化图象边缘化
bw1=imclose(ed1,strel('disk',20));%形态学闭操作填充区域,选择圆形结构体
%以上形态学操作为了模糊纸牌内部的线条结构
%从而减小A,J,Q,K,JOKER纸牌等内部复杂边缘对定位的影响
ed2=edge(bw1,'sobel','both');%对纸牌的物理边缘进行检测
bw2=bwmorph(ed2,'dilate');%形态学结构性膨胀,加强边缘效果
hough=radon(bw2,-90:90);%-90到90度的hough变换
[m,n]=size(hough);
rotate=0;%倾斜角值
sline=0;%最长直线长度
for i=1:m
for j=1:n
if hough(i,j)>sline;
rotate=j-1;sline=hough(i,j);
end
end
end
ed3=bwmorph(ed2,'clean',10);
bw3=imrotate(ed3,-rotate);%预测校正
[m,n]=find(bw3);%预测校正后的目标位置
rgb=imrotate(rgbimage,-rotate,'bilinear');%倾斜校正
poker=rgb(min(m):max(m),min(n):max(n),:);%定位
[m,n]=size(poker);
if n>m
poker=imrotate(poker,90,'bilinear');
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -