Matlab 基于位置将两列向量排序为3D矩阵
使用MATLAB中的imfindcircles函数跟踪两幅图像中的圆。我从一个变形的圆网格开始。我试图将imfindcircles中的两列向量排序为矩阵,以便相邻的圆是矩阵中的相邻元素。第一个图像显示圆符合网格,以下代码起作用:Matlab 基于位置将两列向量排序为3D矩阵,matlab,sorting,grid,Matlab,Sorting,Grid,使用MATLAB中的imfindcircles函数跟踪两幅图像中的圆。我从一个变形的圆网格开始。我试图将imfindcircles中的两列向量排序为矩阵,以便相邻的圆是矩阵中的相邻元素。第一个图像显示圆符合网格,以下代码起作用: [centXsort,IX] = sortrows(centres1,1); %sort by x centYsort =zeros(289,2); %preallocate for i = 1:17:289 [sortedY,IY] = sortrows(c
[centXsort,IX] = sortrows(centres1,1); %sort by x
centYsort =zeros(289,2); %preallocate
for i = 1:17:289
[sortedY,IY] = sortrows(centXsort(i:i+16,:),2); %sort by y within individual column
centYsort(i:i+16,:) = sortedY;
end
cent1mat = reshape(centYsort,17,17,2); %reshape into centre matrices
这不适用于第二个图像,因为一些圆在x或y方向上重叠,但相邻的圆从不重叠。这意味着在第二组矩阵中,相邻圆在排序后不是相邻元素
有没有办法将分散的点近似成一个矩阵?这个答案并不适用于每一种情况,但对于点变化不太大的情况来说似乎已经足够了
我的想法是从网格角开始,沿着矩阵的外对角线,尝试“抓取”最近的点,这些点似乎适合基于我们已经捕获的任何周围点的网格点
您需要提供:
行
)和列数(列
)P
排列在nx2
阵列中,重新缩放到[0,1]x[0,1]
上的单位平方。(我假设您可以通过目视检查原始数据的角点来完成此操作。)edge\u weight
告诉算法边界点应吸引到网格边界的程度。一些测试表明,3
-5
左右是很好的值该代码包括一个测试用例:
%// input parameters
rows = 11;
cols = 11;
edge_weight = 4;
%// function for getting squared errors between the points list P and a specific point pt
getErr =@(P,pt) sqrt( sum( bsxfun(@minus,P,pt(:)').^2, 2 ) ); %'
output_grid = zeros(rows,cols,2); %// output grid matrix
check_grid = zeros(rows,cols); %// matrix flagging the gridpoints we have covered
[ROW,COL] = meshgrid(... %// coordinate points of an "ideal grid"
linspace(0,1,rows),...
linspace(0,1,cols));
%// create a test case
G = [ROW(:),COL(:)]; %// the actual grid-points
noise_factor = 0.35; %// noise radius allowed
rn = noise_factor/rows;
cn = noise_factor/cols;
row_noise = -rn + 2*rn*rand(numel(ROW),1);
col_noise = -cn + 2*cn*rand(numel(ROW),1);
P = G + [row_noise,col_noise]; %// add noise to get points
%// MAIN LOOP
d = 0;
while ~isempty(P) %// while points remain...
d = d+1; %// increase diagonal depth (d=1 are the outer corners)
for ii = max(d-rows+1,1):min(d,rows)%// for every row number i...
i = ii;
j = d-i+1; %// on the dth diagonal, we have d=i+j-1
for c = 1:4 %// repeat for all 4 corners
if i<rows & j<cols & ~check_grid(i,j) %// check for out-of-bounds/repetitions
check_grid(i,j) = true; %// flag gridpoint
current_gridpoint = [ROW(i,j),COL(i,j)];
%// get error between all remaining points and the next gridpoint's neighbours
if i>1
errI = getErr(P,output_grid(i-1,j,:));
else
errI = edge_weight*getErr(P,current_gridpoint);
end
if check_grid(i+1,j)
errI = errI + edge_weight*getErr(P,current_gridpoint);
end
if j>1
errJ = getErr(P,output_grid(i,j-1,:));
else
errJ = edge_weight*getErr(P,current_gridpoint);
end
if check_grid(i,j+1)
errJ = errJ + edge_weight*getErr(P,current_gridpoint);
end
err = errI.^2 + errJ.^2;
%// find the point with minimal error, add it to the grid,
%// and delete it from the points list
[~,idx] = min(err);
output_grid(i,j,:) = permute( P(idx,:), [1 3 2] );
P(idx,:) = [];
end
%// rotate the grid 90 degrees and repeat for next corner
output_grid = cat(3, rot90(output_grid(:,:,1)), rot90(output_grid(:,:,2)));
check_grid = rot90(check_grid);
ROW = rot90(ROW);
COL = rot90(COL);
end
end
end
%//输入参数
行=11;
cols=11;
边缘重量=4;
%//用于获取点列表P和特定点pt之间的平方误差的函数
getErr=@(P,pt)sqrt(sum(bsxfun(@减号,P,pt(:)')).^2,2));%
输出网格=零(行、列、2);%//输出网格矩阵
检查网格=零(行、列);%//矩阵标记我们已覆盖的网格点
[ROW,COL]=网格(…%//理想网格的坐标点)
linspace(0,1,行),。。。
linspace(0,1,cols));
%//创建一个测试用例
G=[行(:),列(:)];%//实际网格点
噪声系数=0.35;%//允许的噪声半径
rn=噪声系数/行;
cn=噪声系数/cols;
行噪声=-rn+2*rn*rand(numel(行),1);
col_noise=-cn+2*cn*rand(numel(行),1);
P=G+[行噪声,列噪声];%//添加噪波以获取点数
%//主回路
d=0;
while~isempty(P)%//当点仍然存在时。。。
d=d+1;%//增加对角线深度(d=1为外角)
对于ii=max(d行+1,1):min(d行)%//对于每个行数i。。。
i=ii;
j=d-i+1;%//在dth对角线上,我们有d=i+j-1
对于c=1:4%//对所有4个角重复
如果我我已经开发了一个解决方案,它适用于我的案例,但可能不如某些案例所需的那么健壮。它需要在一个“正方形”网格中有已知数量的点,并粗略估计点之间的间距。我找到点的“字母形状”和沿边缘的所有点。边向量从最小值开始移动,然后环绕矩阵,相应的点从顶点列表中丢弃。对于大型点云可能不是最好的主意,但对我来说已经足够好了
R = 50; % search radius
xy = centres2;
x = centres2(:,1);
y = centres2(:,2);
for i = 1:8
T = delaunay(xy); % delaunay
[~,r] = circumcenter(triangulation(T,x,y)); % circumcenters
T = T(r < R,:); % points within radius
B = freeBoundary(triangulation(T,x,y)); % find edge vertices
A = B(:,1);
EdgeList = [x(A) y(A) x(A)+y(A)]; % find point closest to origin and rotate vector
[~,I] = min(EdgeList);
EdgeList = circshift(EdgeList,-I(3)+1);
n = sqrt(length(xy)); % define zeros matrix
matX = zeros(n); % wrap x vector around zeros matrix
matX(1,1:n) = EdgeList(1:n,1);
matX(2:n-1,n) = EdgeList(n+1:(2*n)-2,1);
matX(n,n:-1:1) = EdgeList((2*n)-1:(3*n)-2,1);
matX(n-1:-1:2,1) = EdgeList((3*n)-1:(4*n)-4,1);
matY = zeros(n); % wrap y vector around zeros matrix
matY(1,1:n) = EdgeList(1:n,2);
matY(2:n-1,n) = EdgeList(n+1:(2*n)-2,2);
matY(n,n:-1:1) = EdgeList((2*n)-1:(3*n)-2,2);
matY(n-1:-1:2,1) = EdgeList((3*n)-1:(4*n)-4,2);
centreMatX(i:n+i-1,i:n+i-1) = matX; % paste into main matrix
centreMatY(i:n+i-1,i:n+i-1) = matY;
xy(B(:,1),:) = 0; % discard values
xy = xy(all(xy,2),:);
x = xy(:,1);
y = xy(:,2);
end
centreMatX(centreMatX == 0) = x;
centreMatY(centreMatY == 0) = y;
R=50;%搜索半径
xy=中心2;
x=中心2(:,1);
y=中心2(:,2);
对于i=1:8
T=delaunay(xy);%德洛奈
[~,r]=外心(三角测量(T,x,y));%环心
T=T(r
图像中的圆圈是否总是大致形成一定大小的网格,以便矩阵中的每个条目都有坐标?如果你能链接到你正在处理的一些图片,那会很有帮助。@Igenchris我没有足够的声誉在主要主题中发布一张图片,但这是这种排序方法的前/后方法谢谢。我现在没有时间回答。如果我能想出点什么,我会稍后再发。事实上,这个问题似乎已经得到了回答。如果这些答案中的任何一个有效,我将把它标记为一个副本,这样人们就可以很容易地找到解决方案。@Igenchris我不确定我是否理解这里给出的解决方案,但我会继续思考。感谢您发布这篇文章,我使用的解决方案发布在下面,并且涉及到一种不太相似的方法。
R = 50; % search radius
xy = centres2;
x = centres2(:,1);
y = centres2(:,2);
for i = 1:8
T = delaunay(xy); % delaunay
[~,r] = circumcenter(triangulation(T,x,y)); % circumcenters
T = T(r < R,:); % points within radius
B = freeBoundary(triangulation(T,x,y)); % find edge vertices
A = B(:,1);
EdgeList = [x(A) y(A) x(A)+y(A)]; % find point closest to origin and rotate vector
[~,I] = min(EdgeList);
EdgeList = circshift(EdgeList,-I(3)+1);
n = sqrt(length(xy)); % define zeros matrix
matX = zeros(n); % wrap x vector around zeros matrix
matX(1,1:n) = EdgeList(1:n,1);
matX(2:n-1,n) = EdgeList(n+1:(2*n)-2,1);
matX(n,n:-1:1) = EdgeList((2*n)-1:(3*n)-2,1);
matX(n-1:-1:2,1) = EdgeList((3*n)-1:(4*n)-4,1);
matY = zeros(n); % wrap y vector around zeros matrix
matY(1,1:n) = EdgeList(1:n,2);
matY(2:n-1,n) = EdgeList(n+1:(2*n)-2,2);
matY(n,n:-1:1) = EdgeList((2*n)-1:(3*n)-2,2);
matY(n-1:-1:2,1) = EdgeList((3*n)-1:(4*n)-4,2);
centreMatX(i:n+i-1,i:n+i-1) = matX; % paste into main matrix
centreMatY(i:n+i-1,i:n+i-1) = matY;
xy(B(:,1),:) = 0; % discard values
xy = xy(all(xy,2),:);
x = xy(:,1);
y = xy(:,2);
end
centreMatX(centreMatX == 0) = x;
centreMatY(centreMatY == 0) = y;