【图像处理】从点云数据中提取边界(识别和追踪)(Matlab代码实现)

 👨‍🎓个人主页:研学社的博客 

💥💥💞💞欢迎来到本博客❤️❤️💥💥

🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。

⛳️座右铭:行百里者,半于九十。

📋📋📋本文目录如下:🎁🎁🎁

目录


💥1 概述

从建筑的点集中生成直线建筑轮廓通常分为三个步骤。首先确定构成建筑轮廓的边界。然后从边缘开始跟踪一系列点来定义建筑边界。最后,从点的序列中生成线条,并进行调整以形成规则的建筑轮廓。现有的解决方案在以下一种或多种情况下存在缺陷:沿凹形状识别细节,单独识别形状内的“洞”,适当的边界跟踪,以及沿正则化建筑轮廓保存详细信息。本文针对这三个步骤提出了新的解决方案。通过使用输入数据中的最大点对点距离,识别步骤的解决方案正确地检测任何类型形状的边界边缘,并单独识别形状内部的孔(如果有的话)。所提出的跟踪算法将边界边划分为段,准确获取每个段的点序列,并在必要时将它们合并,以生成每个形状的单一边界。正则化步骤提出了一种改进的角线提取算法,并根据自动确定的建筑物主方向对提取的线进行调整。为了评价其性能,还提出了一种将提取的建筑轮廓线与参考轮廓线进行角对应的评价系统。实验结果表明,即使在低密度输入数据中,所提出的解决方案也能保持建筑边界的细节,并提供较高的基于像素的完整性和几何精度。


1) 从输入点集中分别提取(识别和跟踪)外部边界和内部边界,

2) 处理任何类型的输入点集,

3) 从大型和/或密集点集的每个子集中单独提取边界。可以分割原始输入点集(用户定义如何分割),然后可以从组合的子集边界中提取(内部和外部)边界。这大大降低了大型和/或密集点集的计算成本。

这些算法还能够在单个输入数据集中为多个对象提取多个边界。在这种情况下,两个对象之间的距离应至少是输入点云中最大点对点距离的 2 倍。

详细文章见第4部分。

📚2 运行结果

部分代码:

function [bndry bndryin] = delaunay_boundary02_fig(X,Fd,Plns)

[bndry E Ne] = find_delaunay_boundary03(X,Fd);
%Fd = Fd-0.2;

aThresh = 22.5/2; %standard 45 degree
dFd = 2*Fd;
msd = dFd*dFd;
msd1 = Fd*Fd;

(Ner(j,k) > 1 || Ner(k,j) > 1)) ||…
                                    (chk2(1,1) == 0 && chk2(2,1) == 0 && (Ner(j,k) > 0 || Ner(k,j) > 0)))%if (j,k) is from the same plane j,k should not be the consecutive points along plane boundary
                                if j < k
                                    Ner(j,k) = Ner(j,k)-1;
                                    Q = [Q; [j k chk2(2,1)]];                                
                                else
                                    Ner(k,j) = Ner(k,j)-1;
                                    Q = [Q; [k j chk2(2,1)]];
                                end
                                %plot([X(j,1) X(k,1)], [X(j,2) X(k,2)],’-b’); hold on; 
                                if Ner(j,k) == 0 && Ner(k,j) == 0
                                    here = 1;
her vertics with edge (i,j)
                    for v = 1:size(vs,2)
                        here = 1;
                        k = vs(1,v);                          

                        %for edge (i,k)
                        %check if (i,k) is already in Q
                        chk2 = checkEdgeInGaps03(X,i,k,Plns); %check if the edge (i,k) is within a gap in between two planes
                        %if chk2 == 1
                        fik = 0;
                        if size(Q,1)>0
                            if sum(Q(:,1) == i & Q(:,2) == k) == 1 || sum(Q(:,1) == k & Q(:,2) == i) == 1
                                %it is alreday inlcuded into a previous
                                %iteration, so do not add it anymore
                                %Er(i,k) = 0;
                                %Er(k,i) = 0;
                                %Ner(i,k) = 0;
                                %Ner(k,i) = 0;
                                %plot([X(i,1) X(k,1)], [X(i,2) X(k,2)],’-m’); hold on;
                                fik = 1;
                            end
                        end
                        if fik == 0 && (Ner(i,k) == 2 || Ner(k,i) == 2) %&& (chk2(1,1) == 1 ||…
                                    %(chk2(1,1) == 0 && chk2(2,1) == 1 && (Ner(i,k) > 1 || Ner(k,i) > 1)) ||…

                                [mn id] = min(dks);
                                k = k(1,id);

        end

        else
            Q = [];
            Qactive = [];
        end
        B = [];
        while size(Q,1)>0
            found = 0;
            for qc = 1:size(Q,1)
                q = Q(qc,1);%struct number
                if Qactive(qc,1) == 1%if this sturct is not marked inactive
                    found = 1;
                    break;
                end
            end
            if found == 0
                Q = [];
                Qactive = [];
                break;
            end
            e = S{q}.f1;%starting edge
            pv = e(1,1);%previous and current vertices
            cv = e(1,2);
            plot([X(pv,1) X(cv,1)], [X(pv,2) X(cv,2)],’-g’, ‘linewidth’, 2); hold on;
            PVs = pv;%previous vertics, which are left column of S{q}.f1
            %explore the current struct
            while(1)
                vs = find(Er(cv,:) == 1); %all vertices that are connected to cv
                %find all vertices, other than pv, which are along boundary (remove non
                %boundary vertices
                bv = [];
                if cv == 1628 || cv == 156
                    here = 1;
                end
                for m = 1:size(vs,2)
                    k = vs(1,m);

                            if fv > 0
                                break;
                            end
                        end
                        if fv > 0% a new edge is found
                            count = count+1;
                            S{count} = s;
                            El = [El;[i j count 1]];
                            chkV(i,j) = 0;
                            chkV(j,i) = 0;
                            is = i;
                            js = j;
                            Q = [Q;count];%queue for structs to explore
                            Qactive = [Qactive; 1];
                        end
                    end
                    break;
                elseif size(bv,1) == 1
                    %only 1 option, so go forward tracking boundary
                    k = bv(1,1);

                    chkV(cv,k) = 0;
                    chkV(k,cv) = 0;

                    S{q}.f1 = [S{q}.f1; [cv k]];%update edge list for S{q}
                    S{q}.f2 = [S{q}.f2; k];%update vertices list for S{q}
                    El = [El; [cv k q size(S{q}.f1,1)]];
                    pv = cv;
                    cv = k;
                    plot([X(pv,1) X(cv,1)], [X(pv,2) X(cv,2)],’-m’, ‘linewidth’, 2); hold on;

                    if cv == 2935
                        here = 1;
                    end

                    PVs = [PVs;pv];            
                    if sum(PVs == cv)==1 %current vertext has already been visited in an earlier iteration, possibly a loop, so break
                        %self-loop! Update B
                        loopid = find(PVs == cv);
                        B = [B; [q size(S{q}.f1,1) q loopid]];%record the boundary
                        S{q}.f3 = [S{q}.f3; q];%update child list (a previuos paranet becomes a child, so a loop)
                        break;
                    end
                    %{
                    Vi(end,1) = k;
                    Vc = [Vc; pv];
                    if k == fv % aboundary is found
                        Vi = [];
                        Vc = [Vc; fv];
                        count = count + 1;
                        Vb{count,1} = Vc;
                        Vc = [];
                    end
                    %}            
                else%more than one option, generate new structs to explore latter
                    for l = 1:size(bv,1)
                        k = bv(l,1);

                        chkV(cv,k) = 0;
                        chkV(k,cv) = 0;

                        count = count+1;
                        %create a new struct and set q as a parent of new, and new
                        %as a child of q
                        S{count} = struct(‘f0’, q, ‘f1’, [cv k], ‘f2’, [cv;k], ‘f3’, []);
                        El = [El; [cv k count 1]];
                        S{q}.f3 = [S{q}.f3; count];
                        Q = [Q; count]; 
                        Qactive = [Qactive; 1];
                    end
                    break;
                end
            end

            if size(Q,1) > qc
                Q = Q(qc+1:end,:);
                Qactive = Qactive(qc+1:end,:);
                if sum(Qactive,1) == 0
                    Q = [];
                    Qactive = [];
                end
            end

            if size(Q,1) <= qc || size(Q,1) == 0
                Q = [];
                Qactive = [];

                %look for another boundary edge, if any
                    fv = 0;
                    bm = (Er & chkV) & (Ner == 1);
                    hasB = sum(sum(bm));
                    if hasB > 0
                        for i = is:nP
                            for j = js:nP
                                if i < j && bm(i,j)
                                    s = struct(‘f0’, [], ‘f1’, [i j], ‘f2’, [i;j], ‘f3’, []);%f0: parent struct, f1: edges, f2: vertices list, f3: children structs
                                    fv = i;%first vertex
                                    cv = j;%current vertex
                                    pv = i;%previous vertex

                                    %show
                                    %plot(X(fv,1), X(fv,2), ‘og’); hold on;
                                    %plot(X(pv,1), X(pv,2), ‘sy’); hold on;
            while(cur_num ~= first_num)%if they are different
                %then backtrach the edges and nodes
                cur_num = S{last_num}.f0; %take parents
                if size(cur_num,1) == 0 || sum(sids1 == cur_num) == 1
                    %the first sturcture was visited in previous iteration and it does not have a parent (cur_num is empty),
                    % or cur_num is alreday a visited strcuture, so break the loop
                    found = 0;
                    break;
                end
                if cur_num == first_num%loop found, so break the loop
                    joints = [joints; size(bids1,1)];
                    bids1 = [[S{first_num}.f1(first_num_edges:end,:) S{first_num}.f2(first_num_edges:end-1,:)]; bids1];
                    sids1 = [sids1;first_num];
                else
                    joints = [joints; size(bids1,1)];
                    bids1 = [[S{cur_num}.f1 S{cur_num}.f2(1:end-1,:)]; bids1];
                    sids1 = [sids1;cur_num];
                    last_num = cur_num;
                end
            end

            %check joints if they confirm a loop
            if found == 1
                fJoint = 1;
                for j = 1:size(joints,1)
                    jid = joints(j,1);
                    if bids1(jid,2) ~= bids1(jid+1,1)
                        fJoint = 0;
                        break;
                    end
                end
                if cur_num == first_num && fJoint == 1 && bids1(1,1) == bids1(end,2)
                    bcount = bcount + 1;
                    bids{bcount} = bids1;
                    sids{bcount} = sids1;

                    plot(X(bids1(:,1),1),X(bids1(:,1),2),’-c’, ‘linewidth’, 2); hold on;
                end
            end
        end
        end%if bigWholeFound == 1 
    end
    bndryin{bn} = bids;
end

end

🎉3 参考文献

部分理论来源于网络,如有侵权请联系删除。

[1]M. Awrangjeb, “Using point cloud data to identify,trace, and regularize the outlines of buildings” International Journal of Remote Sensing, Volume 37, Issue 3, February 2016, pages 551-579;

🌈4 Matlab代码、数据、文章讲解

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年11月29日
下一篇 2023年11月29日

相关推荐