matlab中的网格检测

use*_*870 13 matlab image-processing

我在二进制图像中有一个网格(可以旋转).如何使用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
Run Code Online (Sandbox Code Playgroud)

bla*_*bla 39

这是fft在x和y投影中使用1D 的方式:

首先,我将模糊图像以通过与高斯卷积来平滑高频噪声:

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');
Run Code Online (Sandbox Code Playgroud)

然后我将采用每个轴投影的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))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

因此我们可以看到两个轴在0.07422处产生峰值,这转换为1/0.07422像素或~13.5像素的周期.

获得角度信息的更好方法是去2D,即:

ml= log( abs( fftshift (fft2(m2)))+1);
imagesc(ml) 
colormap(bone)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

然后根据需要应用简单几何或regionprops等工具,可以得到正方形的角度和大小.方块的大小是1 /背景上大旋转方块的大小(位模糊,因为我模糊了图像所以尝试不用那样做),角度是atan(y/x).正方形之间的距离是1 /中心部分中的强峰与图像中心之间的距离.

所以,如果你ml适当的阈值图像说

 imagesc(ml>11)
Run Code Online (Sandbox Code Playgroud)

你可以访问中心的山峰......

另一种方法是对二值图像进行形态学操作,例如我对模糊图像进行阈值处理并将对象缩小到点.它会删除像素,以便没有孔的对象缩小到某个点:

BW=m2>100;
BW2 = bwmorph(BW,'shrink',Inf);
figure, imshow(BW2)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

然后你几乎每格点网格有一个像素!所以你可以 使用霍夫变换将其提供给Amro的解决方案,或者用fft分析它,或者适合一个块等等......


Amr*_*mro 26

您可以应用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
Run Code Online (Sandbox Code Playgroud)

(我正在使用imoverlay文件交换中的功能)

结果:

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)
Run Code Online (Sandbox Code Playgroud)

这是向后旋转的图像,以便网格与xy轴对齐:

aligned_img