Split repetitive image to find pattern
이전 댓글 표시
Hello
I have an image, which has been made by repeating the same (unknown) pattern. Usually there are 4 to 12 repetitions. This image is processed, as rotated, and cropped (taken a portion of it). A few examples of images (to be renamed as A for the code to run) are added here. My aim is to find this pattern, that is to split the image into complete equal tiles.
My code uses autocorrelation to find the repetition distance, but it seems it is not always working. It should find the right pattern, and also tell me if there are no complete tiles.
Rotation angle is fine. Code sometimes works, sometimes not. I can add more examples if needed.
If you have a better way to find the solution, please let me know
I hope it is clear what I ask
Thank you very much
%% autocorrelation
% ---------------------------------------------------------------------- %
[rows, cols] = size(A);
B = abs(fftshift(ifft2(fft2(A).*conj(fft2(A)))))./(rows*cols);
%B = medfilt2(B);
%% threshold the matrix and find centroids
% ---------------------------------------------------------------------- %
C = B;
checkstart = max(C(:));
checkstart = round(checkstart,2);
for check = checkstart:-0.01:0
for i = 1:rows
for j = 1:cols
if B(i,j)<=check
C(i,j) = 0;
else
C(i,j) = 1;
end
end
end
L = bwlabel(C);
s = regionprops(L,'centroid');
if numel(s)>=3 && numel(s)<=10
break
end
end
%% find distance and angle from the middle centroid
% ---------------------------------------------------------------------- %
midpoint = round(numel(s)/2);
middle = s(midpoint);
for p=1:numel(s)
if p ~= midpoint
N = s(p);
deltax = middle.Centroid(1)-N.Centroid(1);
deltay = middle.Centroid(2)-N.Centroid(2);
distance1(p) = sqrt((deltax.^2)+(deltay.^2));
distance(p) = round(distance1(p));
angle(p) = atand(deltay/deltax);
end
end
mindistance = min(distance(distance>0));
for p=1:numel(distance)
if distance(p) == mindistance
minangle = angle(p);
end
end
dif(1) = minangle-90;
dif(2) = minangle;
dif(3) = minangle+90;
adif = abs(dif);
adifmin = min(adif);
for q=1:numel(dif)
if abs(dif(q))==adifmin
anglechange = dif(q);
end
end
if anglechange>=45
anglechange = anglechange-90;
elseif anglechange<=-45
anglechange = anglechange+90;
end
D = imrotate(A,anglechange);
%% create a grid
% ---------------------------------------------------------------------- %
[row, col] = size(D);
x = floor((col-1)/(mindistance));
y = floor((row-1)/(mindistance));
for xn=0:x
xpos(xn+1) = 1+xn*(mindistance);
end
for yn=0:y
ypos(yn+1) = 1+yn*(mindistance);
end
%% separate tiles
% ---------------------------------------------------------------------- %
w = 1;
for inc = 1:numel(xpos)-1
for jnc = 1:numel(ypos)-1
singletile{w} = D(ypos(jnc):ypos(jnc+1),xpos(inc):xpos(inc+1));
w=w+1;
end
end
채택된 답변
추가 답변 (2개)
Image Analyst
2023년 5월 17일
0 개 추천
Screenshots would help. Does your template (pattern you're searching the larger image for) change size or rotation when it's in the different locations? Have you tried normxcorr2 (demo attached)?

Image Analyst
2023년 5월 18일
If it's just a perfect replication of some tile, why can't you just scan across until a column or row is the same
[rows, columns] = size(m);
% First scan for a matching column
firstColumn= m(:, 1);
for col = 1 : columns
if isequal(firstColumn, m(:, col))
% This column is the same as the first so log it's size
tileWidth = col - 1;
break;
end
end
% Next scan for a matching row
firstRow = m(1, :);
for row = 1 : rows
if isequal(firstRow, m(row, :))
% This row is the same as the first so log it's size
tileHeight = row - 1;
break;
end
end
댓글 수: 1
카테고리
도움말 센터 및 File Exchange에서 Images에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

