我有以下黑色随机方格的源图像:
问题:
如何检测其中有多少个方块?以及如何获得每个方格的宽度,高度和起始位置(x,y)的信息?
如何将组合方块分离为单个方格(可单独变为2格/ 3格/更多/自动),如下所示:
我已经根据这个问题进行了一些简单的模拟,这里是我在matlab中的代码,现在这段代码完全可以检测方块,但是当我将图像源更改为带方形的样本文件时,它有一些错误
%% First Initialisation
tic; % Start timer.
clc; % Clear command window.
clear;
close all; % Close all figure windows except those created by imtool.
imtool close all;
clearvars; % Get rid of variables from prior run of this m-file.
workspace; % Make sure the workspace panel is showing.
%Source
%RGB = imread('Result.png');
RGB = [
0 0 0 0 255 255 255 0 0;
0 0 0 0 255 255 255 0 0;
0 0 0 0 255 255 255 255 255;
255 255 255 255 0 0 0 0 0;
255 255 255 255 0 0 0 0 0;
0 0 0 0 255 255 255 0 0;
0 0 0 0 255 255 255 0 0;
255 255 255 255 0 0 0 0 0;
255 255 255 255 0 0 0 0 0;
];
figure;
imshow(RGB);
caption = sprintf('Source Image');
title(caption, 'FontSize', 13);
%%Make It White
white=Make_Image_White(RGB);
figure;
imshow(white);
caption = sprintf('White Image');
title(caption, 'FontSize', 13);
RGB=white;
%save x,y location
[yy xx] = find( RGB == 0 );
%%Prepare Struct Variabel to Save vertical Black Line
RectLine=struct('Line',[],'PosX',[],'PosY',[],'Width',[],'Height',[]);
%start counting vertical black line
startNew=0;
line=0;
limit=0;
for repeat = 1 : size(find(RGB==0),1)
if startNew==0
line=line+1;
fprintf('Start The-%d Line....\n',line);
startNew=1;
Height=0;
if limit==1
PosY=yy(repeat-1);
PosX=xx(repeat-1);
fprintf(' =-=-=-=-=-=-=-=-=-=-=-=-Continue \n'); % Message sent to command window.
fprintf(' New Box Detection ==> %d \n', line); % Message sent to command window.
fprintf(' Position (x,y) => (%d,%d) \n', PosX, PosY); % Message sent to command window.
fprintf(' Counting X-%d : (x,y) -> [ %d , %d ] \n', repeat-1, xx(repeat-1), yy(repeat-1)); % Message sent to command window.
% fprintf('xx(repeat)==tempX && tempY+1==yy(repeat)\n\r');
% fprintf('%d==%d && %d==%d\n\r',xx(repeat-1),xx(repeat-1),tempY-1,yy(repeat-1));
fprintf(' 1.* add height+1 ==> Counting X-%d : (x,y) -> [ %d , %d ] \n', repeat-1, xx(repeat-1), yy(repeat-1)); % Message sent to command window.
tempX=xx(repeat);
Height=Height+1;
tempY=yy(repeat-1);
startNew=startNew+1;
else
PosY=yy(repeat);
PosX=xx(repeat);
tempX=0;
tempY=0;
end
Width=1;
startY=PosY;
startX=PosX;
if limit==0
fprintf(' =-=-=-=-=-=-=-=-=-=-=-=- Real\n'); % Message sent to command window.
fprintf(' New Line Detection ==> %d \n', line); % Message sent to command window.
fprintf(' Position (x,y) => [ %d , %d ] \n', PosX, PosY); % Message sent to command window.
fprintf(' Counting X-%d : (x,y) -> [ %d , %d ] \n', repeat, xx(repeat), yy(repeat)); % Message sent to command window.
end
end
if (RGB(yy(repeat),xx(repeat),1)==0)
% fprintf(' =-=Tes Titik [%d,%d] \n',xx(repeat),yy(repeat)); % Message sent to command window.
if tempX==0
% fprintf('%d==%d && %d==%d\n',xx(repeat),tempX,tempY+1,yy(repeat));
fprintf(' %d.a add height+1 ==> Counting X-%d : (x,y) -> [ %d , %d ] \n', startNew, repeat,xx(repeat), yy(repeat)); % Message sent to command window.
tempX=xx(repeat);
Height=Height+1;
tempY=tempY+1;
startNew=startNew+1;
elseif xx(repeat)==tempX && tempY+1==yy(repeat)
% fprintf('xx(repeat)==tempX && tempY+1==yy(repeat)\n\r');
% fprintf('%d==%d && %d==%d\n\r',xx(repeat),tempX,tempY+1,yy(repeat));
fprintf(' %d.b add height+1 ==> Counting X-%d : (x,y) -> [ %d , %d ] \n', startNew, repeat,xx(repeat), yy(repeat)); % Message sent to command window.
Height=Height+1;
tempX=xx(repeat);
tempY=tempY+1;
startNew=startNew+1;
if repeat == size(find(RGB==0),1)
RectLine(line).Line=line;
RectLine(line).PosX=PosX;
RectLine(line).PosY=PosY;
RectLine(line).Width=Width;
RectLine(line).Height=Height;
end
else
% fprintf('xx(repeat)==tempX && tempY+1==yy(repeat)\n');
% fprintf('%d==%d && %d==%d\n',xx(repeat),tempX,tempY+1,yy(repeat));
limit=1;
startNew=0;
RectLine(line).Line=line;
RectLine(line).PosX=PosX;
RectLine(line).PosY=PosY;
RectLine(line).Width=Width;
RectLine(line).Height=Height;
tempX=xx(repeat);
end
end;
end
fprintf('\n\nStart Combine Line become Box\n');
RectBox=struct('Box',[],'PosX',[],'PosY',[],'Width',[],'Height',[]);
startBox=1;
for line = size(RectLine,1) : size(RectLine,2)
fprintf(' ************************** Line %d\n',line);
Width=0;
fprintf(' Start Point (%d,%d) Height = %d ** Width=%d\n',RectLine(line).PosX,RectLine(line).PosY,RectLine(line).Height,Width);
if startBox>1
exist=0;
for cek = size(RectBox,1) : size(RectBox,2)
if (RectLine(line).PosX >= RectBox(cek).PosX) && (RectLine(line).PosX <= RectBox(cek).PosX+RectBox(cek).Width-1) ...
&& (RectLine(line).PosY >= RectBox(cek).PosY) && (RectLine(line).PosY <= RectBox(cek).PosY+RectBox(cek).Height-1)
if (RectLine(line).Height == RectBox(cek).Height)
exist=1;
elseif (RectLine(line).Height > RectBox(cek).Height)
RectLine(size(RectBox,2)+1).Line=size(RectBox,2)+1;
RectLine(size(RectBox,2)+1).PosX=RectLine(line).PosX;
RectLine(size(RectBox,2)+1).PosY=RectLine(line).PosY;
RectLine(size(RectBox,2)+1).Width=1;
RectLine(size(RectBox,2)+1).Height=RectLine(line).Height - RectBox(cek).Height;
end
end
if exist==1
fprintf(' ** Line Start From (%d,%d) -> Already Exist On Box %d\n',RectLine(line).PosX,RectLine(line).PosY,cek);
break;
end
end
if exist==0
for x=RectLine(line).PosX : size(RGB,2)
fprintf(' Cek Find Start Position looping at %d -> (%d,%d)\n',x,RectLine(line).PosX,RectLine(line).PosY);
fprintf(' find(RGB(%d:%d,%d:%d))\n',RectLine(line).PosY,RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX,x);
if find(RGB(RectLine(line).PosY:RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX:x))
fprintf(' --> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
elseif x==size(RGB,2)
Width=Width+1;
fprintf(' b--> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
else
up0=0;
down0=0;
% fprintf('Y RGB=%d,%d \n',RectLine(line).PosY-1,x);
if RectLine(line).PosY>1
if (RGB(RectLine(line).PosY-1,x)>0)
up0=1;
else
end
else
up0=1;
end
% fprintf('X RGB=%d,%d \n',RectLine(line).PosY+RectLine(line).Height,x);
if (RectLine(line).PosY+RectLine(line).Height) <= size(RGB,1)
if (RGB(RectLine(line).PosY+RectLine(line).Height,x)>0)
down0=1;
end
else
down0=1;
end
% fprintf('posy=%d,x=%d,height=%d-->tot=%d\n',RectLine(line).PosY, x, RectLine(line).Height, RectLine(line).PosY + RectLine(line).Height);
% fprintf('Status Up=%d ---- Down=%d\n',up0,down0);
if (up0==1) && (down0==1)
Width=Width+1;
fprintf(' Position (%d,%d) -> Width+1 => %d\n',x,RectLine(line).PosY,Width);
else
fprintf('c --> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
end
end
end
end
else
for x=RectLine(line).PosX : size(RGB,2)
fprintf(' Cek Find Start Position looping at %d -> (%d,%d)\n',x,RectLine(line).PosX,RectLine(line).PosY);
fprintf(' find(RGB(%d:%d,%d:%d))\n',RectLine(line).PosY,RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX,x);
if find(RGB(RectLine(line).PosY:RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX:x))
fprintf(' --> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
elseif x==size(RGB,2)
Width=Width+1;
fprintf(' b--> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
else
Width=Width+1;
fprintf(' Position (%d,%d) -> Width+1 => %d\n',x,RectLine(line).PosY,Width);
end
end
end
end
RectBox
%Source
%RGB = imread('Result.png');
RGB = [
0 0 0 0 255 255 255 0 0;
0 0 0 0 255 255 255 0 0;
0 0 0 0 255 255 255 255 255;
255 255 255 255 0 0 0 0 0;
255 255 255 255 0 0 0 0 0;
0 0 0 0 255 255 255 0 0;
0 0 0 0 255 255 255 0 0;
255 255 255 255 0 0 0 0 0;
255 255 255 255 0 0 0 0 0;
];
figure;
imshow(RGB);
caption = sprintf('Source Image');
title(caption, 'FontSize', 13);
%%Make It White
white=Make_Image_White(RGB);
figure;
imshow(white);
caption = sprintf('White Image');
title(caption, 'FontSize', 13);
RGB=white;
%save x,y location
[yy xx] = find( RGB == 0 );
%%Prepare Struct Variabel to Save vertical Black Line
RectLine=struct('Line',[],'PosX',[],'PosY',[],'Width',[],'Height',[]);
%start counting vertical black line
startNew=0;
line=0;
limit=0;
for repeat = 1 : size(find(RGB==0),1)
if startNew==0
line=line+1;
fprintf('Start The-%d Line....\n',line);
startNew=1;
Height=0;
if limit==1
PosY=yy(repeat-1);
PosX=xx(repeat-1);
fprintf(' =-=-=-=-=-=-=-=-=-=-=-=-Continue \n'); % Message sent to command window.
fprintf(' New Box Detection ==> %d \n', line); % Message sent to command window.
fprintf(' Position (x,y) => (%d,%d) \n', PosX, PosY); % Message sent to command window.
fprintf(' Counting X-%d : (x,y) -> [ %d , %d ] \n', repeat-1, xx(repeat-1), yy(repeat-1)); % Message sent to command window.
% fprintf('xx(repeat)==tempX && tempY+1==yy(repeat)\n\r');
% fprintf('%d==%d && %d==%d\n\r',xx(repeat-1),xx(repeat-1),tempY-1,yy(repeat-1));
fprintf(' 1.* add height+1 ==> Counting X-%d : (x,y) -> [ %d , %d ] \n', repeat-1, xx(repeat-1), yy(repeat-1)); % Message sent to command window.
tempX=xx(repeat);
Height=Height+1;
tempY=yy(repeat-1);
startNew=startNew+1;
else
PosY=yy(repeat);
PosX=xx(repeat);
tempX=0;
tempY=0;
end
Width=1;
startY=PosY;
startX=PosX;
if limit==0
fprintf(' =-=-=-=-=-=-=-=-=-=-=-=- Real\n'); % Message sent to command window.
fprintf(' New Line Detection ==> %d \n', line); % Message sent to command window.
fprintf(' Position (x,y) => [ %d , %d ] \n', PosX, PosY); % Message sent to command window.
fprintf(' Counting X-%d : (x,y) -> [ %d , %d ] \n', repeat, xx(repeat), yy(repeat)); % Message sent to command window.
end
end
if (RGB(yy(repeat),xx(repeat),1)==0)
% fprintf(' =-=Tes Titik [%d,%d] \n',xx(repeat),yy(repeat)); % Message sent to command window.
if tempX==0
% fprintf('%d==%d && %d==%d\n',xx(repeat),tempX,tempY+1,yy(repeat));
fprintf(' %d.a add height+1 ==> Counting X-%d : (x,y) -> [ %d , %d ] \n', startNew, repeat,xx(repeat), yy(repeat)); % Message sent to command window.
tempX=xx(repeat);
Height=Height+1;
tempY=tempY+1;
startNew=startNew+1;
elseif xx(repeat)==tempX && tempY+1==yy(repeat)
% fprintf('xx(repeat)==tempX && tempY+1==yy(repeat)\n\r');
% fprintf('%d==%d && %d==%d\n\r',xx(repeat),tempX,tempY+1,yy(repeat));
fprintf(' %d.b add height+1 ==> Counting X-%d : (x,y) -> [ %d , %d ] \n', startNew, repeat,xx(repeat), yy(repeat)); % Message sent to command window.
Height=Height+1;
tempX=xx(repeat);
tempY=tempY+1;
startNew=startNew+1;
if repeat == size(find(RGB==0),1)
RectLine(line).Line=line;
RectLine(line).PosX=PosX;
RectLine(line).PosY=PosY;
RectLine(line).Width=Width;
RectLine(line).Height=Height;
end
else
% fprintf('xx(repeat)==tempX && tempY+1==yy(repeat)\n');
% fprintf('%d==%d && %d==%d\n',xx(repeat),tempX,tempY+1,yy(repeat));
limit=1;
startNew=0;
RectLine(line).Line=line;
RectLine(line).PosX=PosX;
RectLine(line).PosY=PosY;
RectLine(line).Width=Width;
RectLine(line).Height=Height;
tempX=xx(repeat);
end
end;
end
fprintf('\n\nStart Combine Line become Box\n');
RectBox=struct('Box',[],'PosX',[],'PosY',[],'Width',[],'Height',[]);
startBox=1;
for line = size(RectLine,1) : size(RectLine,2)
fprintf(' ************************** Line %d\n',line);
Width=0;
fprintf(' Start Point (%d,%d) Height = %d ** Width=%d\n',RectLine(line).PosX,RectLine(line).PosY,RectLine(line).Height,Width);
if startBox>1
exist=0;
for cek = size(RectBox,1) : size(RectBox,2)
if (RectLine(line).PosX >= RectBox(cek).PosX) && (RectLine(line).PosX <= RectBox(cek).PosX+RectBox(cek).Width-1) ...
&& (RectLine(line).PosY >= RectBox(cek).PosY) && (RectLine(line).PosY <= RectBox(cek).PosY+RectBox(cek).Height-1)
if (RectLine(line).Height == RectBox(cek).Height)
exist=1;
elseif (RectLine(line).Height > RectBox(cek).Height)
RectLine(size(RectBox,2)+1).Line=size(RectBox,2)+1;
RectLine(size(RectBox,2)+1).PosX=RectLine(line).PosX;
RectLine(size(RectBox,2)+1).PosY=RectLine(line).PosY;
RectLine(size(RectBox,2)+1).Width=1;
RectLine(size(RectBox,2)+1).Height=RectLine(line).Height - RectBox(cek).Height;
end
end
if exist==1
fprintf(' ** Line Start From (%d,%d) -> Already Exist On Box %d\n',RectLine(line).PosX,RectLine(line).PosY,cek);
break;
end
end
if exist==0
for x=RectLine(line).PosX : size(RGB,2)
fprintf(' Cek Find Start Position looping at %d -> (%d,%d)\n',x,RectLine(line).PosX,RectLine(line).PosY);
fprintf(' find(RGB(%d:%d,%d:%d))\n',RectLine(line).PosY,RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX,x);
if find(RGB(RectLine(line).PosY:RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX:x))
fprintf(' --> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
elseif x==size(RGB,2)
Width=Width+1;
fprintf(' b--> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
else
up0=0;
down0=0;
% fprintf('Y RGB=%d,%d \n',RectLine(line).PosY-1,x);
if RectLine(line).PosY>1
if (RGB(RectLine(line).PosY-1,x)>0)
up0=1;
else
end
else
up0=1;
end
% fprintf('X RGB=%d,%d \n',RectLine(line).PosY+RectLine(line).Height,x);
if (RectLine(line).PosY+RectLine(line).Height) <= size(RGB,1)
if (RGB(RectLine(line).PosY+RectLine(line).Height,x)>0)
down0=1;
end
else
down0=1;
end
% fprintf('posy=%d,x=%d,height=%d-->tot=%d\n',RectLine(line).PosY, x, RectLine(line).Height, RectLine(line).PosY + RectLine(line).Height);
% fprintf('Status Up=%d ---- Down=%d\n',up0,down0);
if (up0==1) && (down0==1)
Width=Width+1;
fprintf(' Position (%d,%d) -> Width+1 => %d\n',x,RectLine(line).PosY,Width);
else
fprintf('c --> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
end
end
end
end
else
for x=RectLine(line).PosX : size(RGB,2)
fprintf(' Cek Find Start Position looping at %d -> (%d,%d)\n',x,RectLine(line).PosX,RectLine(line).PosY);
fprintf(' find(RGB(%d:%d,%d:%d))\n',RectLine(line).PosY,RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX,x);
if find(RGB(RectLine(line).PosY:RectLine(line).PosY+RectLine(line).Height-1,RectLine(line).PosX:x))
fprintf(' --> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
elseif x==size(RGB,2)
Width=Width+1;
fprintf(' b--> Save %d - Box\n',startBox);
fprintf(' Start Position (%d,%d)\n',RectLine(line).PosX,RectLine(line).PosY);
fprintf(' Width=%d ** Height=%d\n',Width,RectLine(line).Height);
RectBox(startBox).Box=startBox;
RectBox(startBox).PosX=RectLine(line).PosX;
RectBox(startBox).PosY=RectLine(line).PosY;
RectBox(startBox).Width=Width;
RectBox(startBox).Height=RectLine(line).Height;
startBox=startBox+1;
break;
else
Width=Width+1;
fprintf(' Position (%d,%d) -> Width+1 => %d\n',x,RectLine(line).PosY,Width);
end
end
end
end
RectBox
答案 0 :(得分:1)
黑色方块是完全黑色的(RGB值[0,0,0])因此您可以使用非常低的值进行阈值处理,并且您将拥有仅保留正方形的遮罩(存在更好的方法,但您可以从此开始一个)
然后你可以运行一些边缘检测器来保持边缘。
如果然后逐列和逐行添加像素,则峰值将对应于属于正方形边缘的列和行。
由于您知道方块具有相同的大小,因此您可以推断丢失的列和行,以防其中一些没有黑色正方形为您提供峰值。
另一种方法是运行霍夫变换,只保留完全水平和垂直的线条,这些线条对应于正方形的边缘。
答案 1 :(得分:1)
回答问题的第一部分:
I = imread('866PX.jpg');
%Split your image into smaller elements
I2 = mat2cell(I,repmat(40,10,1),repmat(42,10,1),3);
%if an element has more than half of its pixels = 0 then this element is a black square.
for ii = 1:10
for jj = 1:10
ind(ii,jj) = sum(I2{ii,jj}(:)>0)>(numel(I2{1,1})/2);
end
end
imshow(ind)
%number of black square
nbr = sum(~ind(:))
<强>结果:强>
答案 2 :(得分:0)
我没有使用Matlab,但是这里有一些使用ImageMagick实现的想法(仅在命令行),你可以希望它适应。
如果您对图像进行阈值处理并检测边缘,请执行以下操作:
convert chess.png -threshold 10 -edge 1 result.png
如果你现在使用1x3矩形结构元素侵蚀,你将删除水平线并得到这个:
convert chess.png -threshold 10 -edge 1 -morphology erode rectangle:1x3 result.png
现在,您可以按行扫描图像并查找白色像素,这些像素将告诉您块的边缘在哪里。
然后你可以用另一种方式在图像上应用相同的技术:
convert chess.png -threshold 10 -edge 1 -morphology erode rectangle:3x1 result.png
然后,您可以从垂直或水平检测到的白色像素之间的最小间隙推断出您的方形尺寸。
然后,您可以将&#34; Blob Analysis&#34; 或&#34; Connected Component Analysis&#34; 应用于阈值图像以查找黑色方块:
convert chess.png -threshold 10 -negate \
-define connected-components:verbose=true \
-connected-components 4 output.png
示例输出
Objects (id: bounding-box centroid area mean-color):
0: 420x399+0+0 144.3,166.8 78660 srgb(0,0,0)
3: 240x285+180+114 287.5,256.0 34200 srgb(255,255,255)
6: 120x171+300+171 374.5,256.0 13680 srgb(0,0,0)
5: 120x114+0+171 69.5,237.0 10260 srgb(255,255,255)
2: 120x114+300+57 369.5,104.0 10260 srgb(255,255,255)
1: 120x57+120+0 179.5,28.0 6840 srgb(255,255,255)
4: 60x57+300+114 329.5,142.0 3420 srgb(0,0,0)
7: 60x57+60+342 89.5,370.0 3420 srgb(255,255,255)
8: 60x57+180+342 209.5,370.0 3420 srgb(255,255,255)
9: 60x57+240+342 269.5,370.0 3420 srgb(0,0,0)
每条线告诉我们一个blob的高度和宽度及其左上角。我将这些blob以红色绘制到原始图像上:
实际上,您还可以通过查看斑点尺寸的GCD来推断原始图像中正方形的大小 - 它们都是60左右的倍数。
所以,现在你也可以做你问题的第二部分。看看120x57的斑点,必须是2平方乘1平方。
答案 3 :(得分:0)
代码不在matlab中,但它可以很容易地转换成代码,因为我只使用绘图例程以外的最基本的操作。
关键的想法只是首先检测最小矩形大小。黑色的实际上不是正方形,它们是矩形。您可以通过水平和垂直扫描并找到黑色区域的连续区域来完成此操作。每个方向的最小像素长度形成最小矩形大小。
import cv2
import numpy as np
im=cv2.imread('QfOab0P.png')
cv2.imshow('im',im)
# the following deal with jpeg artifacts and squares will contain clean squares at the end
squares = np.zeros((im.shape[0],im.shape[1]),np.uint8)
for y in xrange(im.shape[0]):
for x in xrange(im.shape[1]):
if (sum(im[y,x,:])<40):
squares[y,x]=255
squares=cv2.erode(squares,np.ones((5,5),np.uint8))
squares=cv2.dilate(squares,np.ones((5,5),np.uint8))
# we need to detect minimum size of the square
szx = {}
szy={}
# scan vertically
for x in xrange(im.shape[1]):
sz = 0
for y in xrange(im.shape[0]):
if squares[y,x]==255:
sz += 1
elif sz>0:
if sz not in szy:
szy[sz]=0
szy[sz]+=1
sz = 0
if sz > 0:
if sz not in szy:
szy[sz]=0
szy[sz]+=1
sz = 0
# scan horizontally
for y in xrange(im.shape[0]):
sz = 0
for x in xrange(im.shape[1]):
if squares[y,x]==255:
sz += 1
elif sz>0:
if sz not in szx:
szx[sz]=0
szx[sz]+=1
sz = 0
if sz > 0:
if sz not in szx:
szx[sz]=0
szx[sz]+=1
sz = 0
szx = {k:v for k,v in szx.iteritems() if v>10} # dicard spurious small values caused by imperfect thresholding
szy = {k:v for k,v in szy.iteritems() if v>10}
sqsz = [min(szx.keys()),min(szy.keys())]
# now we may need to refine the values so that we can differentiate between 56 vs 57 in this example
sqsz[0] = int(round(float(im.shape[1])/int(im.shape[1]/float(sqsz[0]))))
sqsz[1] = int(round(float(im.shape[0])/int(im.shape[0]/float(sqsz[1]))))
print sqsz
if im.shape[0]%sqsz[1]!=0 or im.shape[1]%sqsz[0]!=0:
print 'square size detection failed'
# since you know the minimum square size, you can do whatever you wish
# here's an example where the black squares are numbered
# of course you can get fancy and move the blocks around if you want to
sq_cnt =0
for yi in xrange(im.shape[0]/sqsz[1]):
for xi in xrange(im.shape[1]/sqsz[0]):
x = xi*sqsz[0]
y = yi*sqsz[1]
patch = im[y:y+sqsz[1],x:x+sqsz[0],:]
if patch.sum()<100000:#this should be ideally equal to zero but due to jpeg,black is not always black
#this is a black square
cv2.putText(im,str(sq_cnt),(x+sqsz[0]/2,y+sqsz[1]/2),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,255,255),2)
sq_cnt+=1
cv2.rectangle(im,(x,y),(x+sqsz[0],y+sqsz[1]),(255,255,0))
cv2.imshow('sq',squares)
cv2.imshow('with_squares',im)
cv2.imwrite('with_squares.jpg',im)
cv2.waitKey(0)
答案 4 :(得分:0)
%save x,y location
[yy xx] = find( RGB == 0 );
所以,当我将源更改为样本图像时,该样本图像具有3维,当我执行此命令时
%save x,y location
[yy xx] = find( RGB == 0 );
%change dimension 3 become 1
if size(RGB,3) > 1
RGB = rgb2gray(RGB);
end
%save x,y location
[yy xx dimension] = find( RGB == 0 );
在此之后,所有程序都运行良好。
顺便说一句,这个代码执行需要时间,因为它逐个检查所有像素,有没有人有任何解决方案来缩短时间吗?
感谢您的帮助