0


【图像处理】从点云数据中提取边界(识别和追踪)(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 = 2Fd;
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代码、数据、文章讲解


本文转载自: https://blog.csdn.net/weixin_46039719/article/details/129251368
版权归原作者 荔枝科研社 所有, 如有侵权,请联系我们删除。

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

还没有评论