Определение сетки в Matlab
У меня есть сетка в двоичном изображении (может быть повернута). Как узнать приблизительную формулу для этой сетки с помощью MATLAB?
Пример изображения:
http://www.pami.sjtu.edu.cn/people/wyg/images/print5.jpg
Иногда эти черные точки отсутствуют, поэтому мне нужна формула или "способ оценить возможный центр этих черных точек".
Я попытался использовать regionprops
, он поможет мне получить центр этих существующих черных точек, но не знаю, есть ли черные точки без
clear all
im = imread('print5.jpg');
im = im2bw(im);
[sy,sx] = size(im);
im = imcomplement(im);
im(150:200,100:150) = 0; % let some dots missing!
im = imclearborder(im);
st = regionprops(im, 'Centroid');
imshow(im) hold on;
for j = 1:numel(st)
px = round(st(j).Centroid(1,1));
py = round(st(j).Centroid(1,2));
plot(px,py,'b+')
end
Ответы
Ответ 1
здесь, используя fft
в 1D над проекцией x и y:
Во-первых, я немного размычу изображение, чтобы сгладить высокий частотный шум, свернув гауссовым:
m=double(imread('print5.jpg'));
m=abs(m-max(m(:))); % optional line if you want to look on the black square as "signal"
H=fspecial('gaussian',7,1);
m2=conv2(m,H,'same');
тогда я возьму fft проекции каждой оси:
delta=1;
N=size(m,1);
df=1/(N*delta); % the frequency resolution (df=1/max_T)
f_vector= df*((1:N)-1-N/2); % frequency vector
freq_vec=f_vector;
fft_vecx=fftshift(fft(sum(m2)));
fft_vecy=fftshift(fft(sum(m2')));
plot(freq_vec,abs(fft_vecx),freq_vec,abs(fft_vecy))
![enter image description here]()
Таким образом, мы можем видеть, что обе оси дают пик при 0.07422, которые переводятся на период 1/0,07422 пикселя или ~ 13,5 пикселей.
Лучший способ получить информацию о углу - перейти в 2D, то есть:
ml= log( abs( fftshift (fft2(m2)))+1);
imagesc(ml)
colormap(bone)
![enter image description here]()
а затем примените инструменты, такие как простая геометрия или regionprops, если хотите, вы можете получить угол и размер квадратов. Размер квадрата равен 1/размер большого поворотного квадрата на фоне (бит нечеткий, потому что я размыл изображение, поэтому попробуйте сделать это без этого), а угол atan(y/x)
. Расстояние между квадратами составляет 1/расстояние между сильными пиками в центральной части до центра изображения.
поэтому, если вы пороговое ml
правильно скажете
imagesc(ml>11)
вы можете получить доступ к центральным пикам для этого...
еще один подход будет морфологической операцией на двоичном изображении, например, я порождает размытое изображение и сокращает объекты до точек. Он удаляет пиксели, чтобы объекты без отверстий сжимались до точки:
BW=m2>100;
BW2 = bwmorph(BW,'shrink',Inf);
figure, imshow(BW2)
![enter image description here]()
Тогда у вас практически есть один пиксель на сетку сетки решетки! поэтому вы можете подать его в Amro solution
используя преобразование Хафа, или анализируйте его с помощью fft, или установите блок и т.д.
Ответ 2
Вы можете применить преобразование Hough для определения линий сетки. Как только у нас есть такие возможности, вы можете определить местоположение сетки и угол поворота:
%# load image, and process it
img = imread('print5.jpg');
img = imfilter(img, fspecial('gaussian',7,1));
BW = imcomplement(im2bw(img));
BW = imclearborder(BW);
BW(150:200,100:150) = 0; %# simulate a missing chunk!
%# detect dots centers
st = regionprops(BW, 'Centroid');
c = vertcat(st.Centroid);
%# hough transform, detect peaks, then get lines segments
[H,T,R] = hough(BW);
P = houghpeaks(H, 25);
L = houghlines(BW, T, R, P);
%# show image with overlayed connected components, their centers + detected lines
I = imoverlay(img, BW, [0.9 0.1 0.1]);
imshow(I, 'InitialMag',200, 'Border','tight'), hold on
line(c(:,1), c(:,2), 'LineStyle','none', 'Marker','+', 'Color','b')
for k = 1:length(L)
xy = [L(k).point1; L(k).point2];
plot(xy(:,1), xy(:,2), 'g-', 'LineWidth',2);
end
hold off
(Я использую imoverlay
из Файлового Exchange)
Результат:
![grid_lines_overlayed]()
Вот аккумуляторная матрица с пиками, соответствующими выделенным линиям:
![accumulator_peaks]()
Теперь мы можем восстановить угол поворота, вычислив средний наклон обнаруженных линий, отфильтрованный на один из двух направлений (горизонтали или вертикали):
%# filter lines to extract almost vertical ones
%# Note that theta range is (-90:89), angle = theta + 90
LL = L( abs([L.theta]) < 30 );
%# compute the mean slope of those lines
slopes = vertcat(LL.point2) - vertcat(LL.point1);
slopes = atan2(slopes(:,2),slopes(:,1));
r = mean(slopes);
%# transform image by applying the inverse of the rotation
tform = maketform('affine', [cos(r) sin(r) 0; -sin(r) cos(r) 0; 0 0 1]);
img_align = imtransform(img, fliptform(tform));
imshow(img_align)
Здесь изображение повернуто назад так, что сетка выровнена с осями xy:
![aligned_img]()