【图像处理】从点云数据中提取边界(识别和追踪)(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代码、数据、文章讲解
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)