clc
clear
close all
%结果数据是CC
% rootFolder = fullfile('D:\Data\2016.5.18棋盘格');
rootFolder = fullfile('D:\程序\总');
imgSets = imageSet(rootFolder);
count=imgSets.Count(1,1);
row=7;%棋盘格的行数
col=10;%棋盘格的列数
rho=12;%ρ为图像中角点弥散斑直径。
bianchang=160;%棋盘格的边长
theta=0.2;%角度步进
jd=cell(1,count);
for img=1:count
I=read(imgSets,img);%读取第i幅图
I=rgb2gray(I);
%做标准差为3的高斯滤波,然后以0.08为低门槛,0.2为高门槛,进行canny边缘检测
%考虑到棋盘格信息对比度明显,选择较高的灰度梯度门槛值进行边缘检测
%可以考虑使用OTSU算法对棋盘格图像进行预处理
[BW,thresh]=edge(I,'canny',[0.2*0.4,0.2],3);%BW为二值化的边缘图像
% figure;imshow(I,[]);
% figure;imshow(BW,[]);
%%
%hough变换检测竖线
[H,T,R]=hough(BW,'RhoResolution',rho,'Theta',-10:theta:10);
P=houghpeaks(H,col+3,'threshold',ceil(0.2*max(H(:))));%预留4个裕量
lines=houghlines(BW,T,R,P,'FillGap',bianchang*1.5,'MinLength',bianchang*3);
% h2=figure;
% imshow(I,'InitialMagnification',30);
% title('霍夫变换直线检测');
% grid on;
% axis on;
% hold on;
shu=[];
ps=[];
for k=1:length(lines)
xy=[lines(k).point1;lines(k).point2];
dis=(xy(1,1)+xy(2,1))/2;
shu=[shu,dis];
sign=0;
if length(shu)>1
for i=1:length(shu)-1
if abs(dis-shu(i))<rho*2.5
shu(end)=[];%删除重复直线
sign=1;
break
end
end
end
if sign
continue
end
t=lines(k).theta;
r=lines(k).rho;
%写成x=p1*y+p2的形式避免斜率为无穷
p=[-tan(t*pi/180),r/cos(t*pi/180)];
ps=[ps;p];
% y=1:max(size(I));
% x=polyval(p,y);
% plot(x,y,'LineWidth',2,'Color','green');
end
%删除可能存在的棋盘格边缘线
%限制条件:棋盘格必须位于图像正中,偏差不能超过一个棋盘格
%这里是偷懒了、、凑合用
switch length(shu)
case col+1
for u=1:2
[m1,index1]=max(shu);
m1=size(I,2)-m1;
[m2,index2]=min(shu);
if m1<m2
ps(index1,:)=[];
shu(index1)=[];
else
ps(index2,:)=[];
shu(index2)=[];
end
end
case col
[m1,index1]=max(shu);
m1=size(I,2)-m1;
[m2,index2]=min(shu);
if m1<m2
ps(index1,:)=[];
shu(index1)=[];
else
ps(index2,:)=[];
shu(index2)=[];
end
end
if length(shu)<col-1
disp(strcat('第',num2str(img),'张棋盘格竖线漏检'));
end
%%
%hough变换检测横线
[H,T,R]=hough(BW,'RhoResolution',rho,'Theta',[-90:theta:-80,80:theta:90-theta]);
P=houghpeaks(H,row+3,'threshold',ceil(0.2*max(H(:))));
lines=houghlines(BW,T,R,P,'FillGap',bianchang*1.5,'MinLength',bianchang*3);
heng=[];
ph=[];
for k=1:length(lines)
xy=[lines(k).point1;lines(k).point2];
dis=(xy(1,2)+xy(2,2))/2;
heng=[heng,dis];
sign=0;
if length(heng)>1
for i=1:length(heng)-1
if abs(dis-heng(i))<rho*2.5
heng(end)=[];
sign=1;
break
end
end
end
if sign
continue
end
t=lines(k).theta;
r=lines(k).rho;
p=[-cot(t*pi/180),r/sin(t*pi/180)];
ph=[ph;p];
% x=1:max(size(I));
% y=polyval(p,x);
% plot(x,y,'LineWidth',2,'Color','blue');
end
%删除可能存在的棋盘格边缘线
switch length(heng)
case row+1
for u=1:2
[m1,index1]=max(heng);
m1=size(I,1)-m1;
[m2,index2]=min(heng);
if m1<m2
ph(index1,:)=[];
heng(index1)=[];
else
ph(index2,:)=[];
heng(index2)=[];
end
end
case row
[m1,index1]=max(heng);
m1=size(I,1)-m1;
[m2,index2]=min(heng);
if m1<m2
ph(index1,:)=[];
heng(index1)=[];
else
ph(index2,:)=[];
heng(index2)=[];
end
end
if length(heng)<row-1
disp(strcat('第',num2str(img),'张棋盘格横线漏检'));
end
%%
%求纵横线交点
corner0=zeros(2,(row-1)*(col-1));
for i=1:row-1
for j=1:col-1
n=(i-1)*(col-1)+j;
corner0(1,n)=(ps(j,1)*ph(i,2)+ps(j,2))/(1-ps(j,1)*ph(i,1));
corner0(2,n)=(ph(i,1)*ps(j,2)+ph(i,2))/(1-ph(i,1)*ps(j,1));
end
end
% figure;
% imshow(I,'InitialMagnification',30);
% title('角点粗略检测');
% grid on;
% axis on;
% hold on;
% plot(corner0(1,:),corner0(2,:),'rx');
%%
%求精确角点
if rho>10
Image=imresize(I,1/2);
C=corner(Image,'FilterCoefficients',fspecial('gaussian',[5 1],3));
% figure,imshow(Image,'InitialMagnification',60);
% hold on
% plot(C(:,1), C(:,2), 'rx');
C=C.*2;
else
Image=I;
C=corner(Image,'FilterCoefficients',fspecial('gaussian',[5 1],3));
% figure,imshow(Image,'InitialMagnification',30);
% hold on
% plot(C(:,1), C(:,2), 'rx');
end
C0=corner0';
CC=zeros(size(C0));
% finds the nearest neighbor in C for each point in C0
[nv,d]=knnsearch(C,C0,'k',2);
for i=1:size(corner0,2)
a=C(nv(i,:),:);
CC(i,:)=mean(a(d(i,:)<rho+5,:),1);
end
figure;
imshow(I,'InitialMagnification',30);
title('角点精确检测');
grid on;
axis on;
hold on;
plot(CC(:,1),CC(:,2),'rx');
jd{1,img}=CC;
end