2013-05-10 41 views
12

Mam siatkę na obrazie binarnym (można obracać). Jak mogę poznać przybliżoną formułę dla tej siatki za pomocą MATLAB?Wykrywanie siatki w programie Matlab

Przykład obrazu:

http://www.pami.sjtu.edu.cn/people/wyg/images/print5.jpg

Czasami czarne kropki brakuje, więc trzeba wzór lub „sposób” w celu oszacowania ewentualnego środka tych czarnych punktów.

Próbowałem za pomocą regionprops, to pomoże mi dostać się centrum tych istnieją czarne kropki, ale nie wiem, czy czarne kropki brakujący

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

Spróbuj loo king ad treść częstotliwości: 'fft2' siatka jest bardzo regularna, powinieneś być w stanie wykryć szczyty w dziedzinie częstotliwości. – Shai

+5

Jeśli edytujesz wszystkie informacje z powyższych komentarzy na swoje pytanie, powinieneś móc je ponownie otworzyć. –

+5

Wow, to przyciągnęło wiele spadków w krótkim czasie. Rozumiem, dlaczego był zamknięty, ale czy naprawdę zasłużył - 20 spadł ... – Amro

Odpowiedz

38

oto sposób korzystania fft w 1D nad X i Y projekcja:

po pierwsze, będę rozmycie obrazu nieco wygładzić wysoki hałas freq przez splatanie z Gaussa:

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'); 

potem wezmę FF t występu każdej osi:

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

Widzimy więc zarówno oś uzyskując pik w 0.07422 które przekładają się na okres 1/0,07422 pikseli lub ~ 13,5 pikseli.

Lepszym sposobem, aby uzyskać także informacje o kąt jest przejść 2D, czyli:

ml= log(abs(fftshift (fft2(m2)))+1); 
imagesc(ml) 
colormap(bone) 

enter image description here

a następnie zastosować narzędzia, takie jak prostą geometrię lub regionprops jeśli chcesz, możesz dostać kąt i rozmiar kwadratów. Rozmiar kwadratu to 1/rozmiar dużego obróconego kwadratu w tle (trochę rozmyte, ponieważ zamazałem obraz, więc bez tego postaram się to zrobić), a kąt to atan(y/x). Odległość między kwadratami wynosi 1/odległość między mocnymi pikami w środkowej części a centrum obrazu.

więc jeśli próg ml obraz prawidłowo powiedzieć

imagesc(ml>11) 

można uzyskać dostęp do szczytów ośrodkiem że ...

jeszcze inne podejście będzie operacja morfologiczne na obrazie binarnym, na przykład Przekierowuję niewyraźny obraz i zmniejszam obiekty do punktów. Usuwa pikseli tak, że obiekty bez otworów kurczyć do punktu:

BW=m2>100; 
BW2 = bwmorph(BW,'shrink',Inf); 
figure, imshow(BW2) 

enter image description here

Wtedy praktycznie mają jeden piksel na siatkę stronie kraty! więc można karmić go rozwiązanie Amro użyciu Hough przekształcać ani analizować go z FFT, lub dopasować blok, itp ...

26

Można zastosować Hough transform wykryć linie siatki.Kiedy już mamy tych można wywnioskować lokalizacje siatki i kąta obrotu:

%# 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 

(używam imoverlay funkcję z Exchange File)

Rezultat:

grid_lines_overlayed

Oto macierz akumulatorów z pikami odpowiadającymi wykrytym liniom podświetlonym:

accumulator_peaks


Teraz można odzyskać kąta obrotu, obliczając średnie nachylenie wykrytych linii, przesączono tym, w jednym z dwóch kierunków (lub poziomą):

%# 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) 

tutaj obraz jest obrócony do tyłu, tak, że siatka jest wyrównane z osiami XY:

aligned_img

Powiązane problemy