Matlab 基于位置将两列向量排序为3D矩阵

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

使用MATLAB中的imfindcircles函数跟踪两幅图像中的圆。我从一个变形的圆网格开始。我试图将imfindcircles中的两列向量排序为矩阵,以便相邻的圆是矩阵中的相邻元素。第一个图像显示圆符合网格,以下代码起作用:

[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;