20 #include <QCoreApplication>
21 #include <QElapsedTimer>
22 #include <QProgressDialog>
32 #include <boost/geometry.hpp>
33 #include <boost/geometry/geometries/point_xy.hpp>
34 #include <boost/geometry/geometries/polygon.hpp>
36 typedef boost::geometry::model::d2::point_xy<double>
point_xy;
37 typedef boost::geometry::model::polygon<point_xy>
polygon;
38 typedef boost::geometry::model::multi_point<point_xy>
multi_point;
41 typedef std::vector<float>
Vec3d;
51 template <
class result_t = std::chrono::milliseconds,
52 class clock_t = std::chrono::steady_clock,
53 class duration_t = std::chrono::milliseconds>
54 static auto Since(std::chrono::time_point<clock_t, duration_t>
const& start) {
55 return std::chrono::duration_cast<result_t>(clock_t::now() - start);
59 const unsigned min_nn1,
60 const float regStrength1,
61 const float PR_DECIMATE_RES1,
62 QProgressDialog* progressDlg ) {
69 progressDlg->setRange(0, 100);
72 auto start = std::chrono::steady_clock::now();
74 const unsigned pointCount = pc->
size();
76 std::vector<Vec3d> pc_vec;
80 progressDlg->setValue(10);
81 QCoreApplication::processEvents();
84 std::vector<size_t> ia, ic;
85 std::vector<Vec3d> pc_dec, pc_sub;
91 progressDlg->setValue(30);
92 QCoreApplication::processEvents();
95 const unsigned K = (min_nn1 - 1);
97 std::vector<uint32_t> Eu;
98 std::vector<uint32_t> Ev;
99 std::vector<uint32_t> in_component;
100 std::vector<std::vector<uint32_t>> components;
103 in_component, components);
106 progressDlg->setValue(90);
107 QCoreApplication::processEvents();
112 if (outSFIndex < 0) {
114 if (outSFIndex < 0) {
122 std::vector<uint32_t> clusterIdx(pointCount);
123 for (
unsigned i = 0; i < pointCount; ++i) {
124 clusterIdx[i] = in_component[ic[i]];
125 outSF->
setValue(i, in_component[ic[i]]);
132 auto elapsed =
Since(start).count() / 1000;
133 CVLog::Print(QString(
"[TreeIso] Init segs took %1 seconds").arg(elapsed));
136 progressDlg->setValue(100);
137 QCoreApplication::processEvents();
144 const unsigned PR_MIN_NN2,
145 const float PR_REG_STRENGTH2,
146 const float PR_DECIMATE_RES2,
147 const float PR_MAX_GAP,
148 QProgressDialog* progressDlg ) {
155 progressDlg->setRange(0, 100);
158 auto start = std::chrono::steady_clock::now();
160 unsigned pointCount = pc->
size();
163 if (initSFIndex < 0) {
164 CVLog::Error(
"[TreeIso] Please run initial segmentation first!");
169 std::vector<uint32_t> in_component;
171 in_component.resize(pointCount);
172 }
catch (
const std::bad_alloc&) {
176 for (
unsigned i = 0; i < pointCount; ++i) {
177 in_component[i] = initSF->
getValue(i);
179 std::vector<std::vector<uint32_t>> clusterVGroup;
182 std::vector<Vec3d> pc_vec;
185 size_t n_clusters = clusterVGroup.size();
187 std::vector<Vec3d> clusterCentroids(n_clusters);
188 std::vector<std::vector<Vec3d>> currentClusterDecs(n_clusters);
189 std::vector<std::vector<size_t>> currentClusterDecsICs(n_clusters);
191 for (
size_t i = 0; i < n_clusters; ++i) {
192 std::vector<Vec3d> currentClusterPos;
193 get_subset(pc_vec, clusterVGroup[i], currentClusterPos);
195 if (currentClusterPos.size() > 1) {
196 std::vector<size_t> ia, ic;
197 std::vector<Vec3d> currentClusterPosDec;
199 currentClusterPosDec);
202 std::vector<Vec3d> currentClusterPosUnq;
203 get_subset(currentClusterPos, ia, currentClusterPosUnq);
204 currentClusterDecs[i] = currentClusterPosUnq;
206 mean_col(currentClusterPos, clusterCentroids[i]);
207 currentClusterDecsICs[i] = ic;
209 currentClusterDecs[i] = currentClusterPos;
210 clusterCentroids[i] = currentClusterPos[0];
211 currentClusterDecsICs[i] = std::vector<size_t>(1, 0);
216 progressDlg->setValue(10);
217 QCoreApplication::processEvents();
220 std::vector<std::vector<uint32_t>> minIdxsC;
221 std::vector<Vec3d> minIdxsD;
226 progressDlg->setValue(15);
227 QCoreApplication::processEvents();
230 size_t n_centroids = minIdxsC.size();
231 if (n_centroids == 0) {
235 size_t n_K = minIdxsC[0].size();
236 std::vector<Eigen::MatrixXf> currentClusterDecMats;
240 for (
size_t i = 0; i < n_centroids; ++i) {
241 std::vector<Vec3d> currentClusterDec = currentClusterDecs[i];
242 Eigen::MatrixXf currentClusterDecMat(currentClusterDec[0].
size(),
243 currentClusterDec.size());
244 for (
size_t k = 0; k < currentClusterDec.size(); k++) {
245 currentClusterDecMat.col(k) = Eigen::VectorXf::Map(
246 ¤tClusterDec[k][0], currentClusterDec[k].
size());
248 currentClusterDecMats.push_back(currentClusterDecMat);
252 progressDlg->setValue(20);
253 QCoreApplication::processEvents();
256 std::vector<Vec3d> nnDists;
257 nnDists.resize(n_centroids,
Vec3d(n_K));
258 for (
size_t i = 0; i < n_centroids; ++i) {
260 knn_kdtree(currentClusterDecMats[minIdxsC[i][0]]);
262 for (
size_t j = 1; j < n_K; ++j) {
263 if (minIdxsD[i][j] > 0) {
264 std::vector<std::vector<size_t>> min_c;
265 std::vector<Vec3d> min_D2;
267 knn_kdtree, currentClusterDecMats[minIdxsC[i][j]], 1);
268 nnDists[i][j] = min_D;
274 progressDlg->setValue(40);
275 QCoreApplication::processEvents();
278 std::vector<Vec3d> currentClusterDecsFlat;
279 std::vector<size_t> currentClusterDecsFlatIndex;
280 std::vector<size_t> currentClusterDecsICsFlatIndex;
281 std::vector<uint32_t> currentClusterDecsIDs;
283 for (
auto& vec : clusterVGroup) {
284 currentClusterDecsIDs.insert(currentClusterDecsIDs.end(),
285 std::make_move_iterator(vec.begin()),
286 std::make_move_iterator(vec.end()));
288 for (
auto& vec : currentClusterDecs) {
289 currentClusterDecsFlat.insert(currentClusterDecsFlat.end(),
290 std::make_move_iterator(vec.begin()),
291 std::make_move_iterator(vec.end()));
292 currentClusterDecsICsFlatIndex.insert(
293 currentClusterDecsICsFlatIndex.end(), vec.size());
296 for (
unsigned i = 0; i < currentClusterDecs.size(); i++) {
297 for (
unsigned j = 0; j < currentClusterDecs[i].size(); ++j) {
298 currentClusterDecsFlatIndex.push_back(i);
303 progressDlg->setValue(50);
304 QCoreApplication::processEvents();
307 size_t nNodes = currentClusterDecsFlat.size();
308 unsigned nKs = PR_MIN_NN2;
310 std::vector<std::vector<uint32_t>> minIdxs;
311 std::vector<Vec3d> Ds;
316 std::vector<uint32_t> Eu;
317 std::vector<uint32_t> Ev;
319 for (
size_t i = 0; i < minIdxs.size(); i++) {
320 size_t currentNode = currentClusterDecsFlatIndex[i];
321 Vec3d currentDists = nnDists[currentNode];
322 for (
size_t j = 1; j < minIdxs[0].size(); ++j) {
323 size_t nnNode = currentClusterDecsFlatIndex[minIdxs[i][j]];
324 const std::vector<uint32_t>& nnCand = minIdxsC[currentNode];
325 auto it = std::find(nnCand.begin(), nnCand.end(), nnNode);
326 if (it != nnCand.end()) {
327 float nnDist = currentDists[it - nnCand.begin()];
328 if (nnDist < PR_MAX_GAP) {
329 Eu.push_back(
static_cast<uint32_t
>(i));
330 Ev.push_back(minIdxs[i][j]);
331 edgeWeight.push_back(10 / ((nnDist + 0.1) / 0.01));
338 progressDlg->setValue(55);
339 QCoreApplication::processEvents();
342 std::vector<uint32_t> in_component2d;
344 edgeWeight, Eu, Ev, in_component2d);
347 progressDlg->setValue(80);
348 QCoreApplication::processEvents();
351 std::vector<uint32_t> currentClusterDecsICsReverse;
352 std::vector<Vec3d> currentClusterDecsReverse;
353 size_t ia_counter = 0;
354 for (
size_t i = 0; i < currentClusterDecs.size(); i++) {
355 size_t N = currentClusterDecsICs[i].size();
356 std::vector<uint32_t> v(in_component2d.begin() + ia_counter,
357 in_component2d.begin() + ia_counter +
358 currentClusterDecsICsFlatIndex[i]);
359 for (
size_t j = 0; j < N; j++) {
360 currentClusterDecsICsReverse.push_back(
361 v[currentClusterDecsICs[i][j]]);
363 ia_counter += currentClusterDecsICsFlatIndex[i];
366 std::vector<uint32_t> currentClusterDecsIDsSortedIdx;
367 std::vector<uint32_t> currentClusterDecsIDsSorted;
369 sort_indexes(currentClusterDecsIDs, currentClusterDecsIDsSortedIdx,
370 currentClusterDecsIDsSorted);
371 std::vector<uint32_t> currentClusterDecsICsReverseSorted;
372 currentClusterDecsICsReverseSorted.reserve(
373 currentClusterDecsICsReverse.size());
374 std::transform(currentClusterDecsIDsSortedIdx.begin(),
375 currentClusterDecsIDsSortedIdx.end(),
376 std::back_inserter(currentClusterDecsICsReverseSorted),
377 [&](uint32_t i) { return currentClusterDecsICsReverse[i]; });
381 if (outSFIndex < 0) {
383 if (outSFIndex < 0) {
391 std::vector<uint32_t> groupIdx(pointCount);
392 for (
unsigned i = 0; i < pointCount; ++i) {
393 groupIdx[i] = currentClusterDecsICsReverseSorted[i];
394 outSF->
setValue(i, currentClusterDecsICsReverseSorted[i]);
402 progressDlg->setValue(100);
403 QCoreApplication::processEvents();
406 auto elapsed =
Since(start).count() / 1000;
407 CVLog::Print(QString(
"[TreeIso] Intermediate segs took %1 seconds")
414 const unsigned PR_MIN_NN3,
415 const float PR_REL_HEIGHT_LENGTH_RATIO,
416 const float PR_VERTICAL_WEIGHT,
417 QProgressDialog* progressDlg ) {
424 progressDlg->setRange(0, 100);
427 auto start = std::chrono::steady_clock::now();
429 unsigned pointCount = pc->
size();
430 std::vector<Vec3d> pc_vec;
435 CVLog::Error(
"[TreeIso] Please run initial segmentation first!");
440 CVLog::Error(
"[TreeIso] Please run intermeditate segmentation first!");
446 std::vector<uint32_t> segs_init_ids;
447 segs_init_ids.resize(pointCount);
448 for (
unsigned i = 0; i < pointCount; ++i) {
449 segs_init_ids[i] = initSF->
getValue(i);
458 std::vector<uint32_t> segs_group_ids;
459 segs_group_ids.resize(pointCount);
461 for (
unsigned i = 0; i < pointCount; ++i) {
462 segs_group_ids[i] = groupSF->
getValue(i);
465 std::vector<std::vector<uint32_t>> initVGroup;
466 std::vector<uint32_t> initU;
467 std::vector<uint32_t> initUI;
470 size_t n_init_clusters = initVGroup.size();
471 std::vector<Vec3d> clusterCentroids(n_init_clusters);
473 for (
size_t i = 0; i < n_init_clusters; ++i) {
474 std::vector<Vec3d> clusterPts;
475 get_subset(pc_vec, initVGroup[i], clusterPts);
476 Vec3d clusterCentroid;
477 mean_col(clusterPts, clusterCentroid);
478 clusterCentroids[i] = clusterCentroid;
480 std::vector<uint32_t> segs_group_id;
481 get_subset(segs_group_ids, initVGroup[i], segs_group_id);
482 float seg_group_mode =
mode_col(segs_group_id);
483 for (
int j = 0; j < segs_group_id.size(); ++j) {
484 segs_group_ids[initVGroup[i][j]] = seg_group_mode;
488 std::vector<uint32_t> cluster_ids;
489 get_subset(segs_group_ids, initUI, cluster_ids);
491 std::vector<std::vector<uint32_t>> clusterVGroup;
492 std::vector<uint32_t> clusterU0;
495 if (clusterVGroup.size() > 1) {
496 auto start = std::chrono::steady_clock::now();
497 size_t n_clusters = clusterVGroup.size();
499 std::vector<unsigned> mergedRemainIds;
501 size_t n_to_merge_ids = 1;
502 int n_prev_merge_ids = -1;
505 std::vector<std::vector<uint32_t>> groupVGroup;
506 std::vector<uint32_t> groupU;
508 std::vector<std::vector<float>> centroid2DFeatures;
509 Eigen::MatrixXf groupCentroidsToMerge;
510 Eigen::MatrixXf groupCentroidsRemain;
512 while ((n_to_merge_ids != 0) &&
513 (
static_cast<int>(n_to_merge_ids) != n_prev_merge_ids)) {
515 n_prev_merge_ids =
static_cast<int>(n_to_merge_ids);
518 size_t nGroups = groupVGroup.size();
519 centroid2DFeatures.resize(nGroups, std::vector<float>(2));
521 std::vector<float> zFeatures;
522 zFeatures.resize(nGroups);
523 std::vector<float> lenFeatures;
524 lenFeatures.resize(nGroups);
526 std::vector<polygon> groupHulls;
527 for (
size_t i = 0; i < nGroups; ++i) {
528 std::vector<Vec3d> groupPts;
530 Vec3d groupCentroids;
532 centroid2DFeatures[i][0] = groupCentroids[0];
533 centroid2DFeatures[i][1] = groupCentroids[1];
535 std::vector<float> minPts;
537 zFeatures[i] = minPts[2];
538 std::vector<float> maxPts;
540 lenFeatures[i] = maxPts[2] - minPts[2];
544 for (
const auto& p : groupPts) {
545 conv_points.push_back(
point_xy(p[0], p[1]));
548 boost::geometry::convex_hull(conv_points, hull);
549 groupHulls.push_back(hull);
553 (PR_MIN_NN3 < n_clusters ? PR_MIN_NN3 : n_clusters);
554 std::vector<std::vector<uint32_t>> groupNNIdxC;
555 std::vector<Vec3d> groupNNCDs;
557 groupNNIdxC, groupNNCDs, 8);
560 float sigmaD = mds[1];
562 std::vector<size_t> toMergeIds;
563 std::vector<size_t> toMergeCandidateIds;
564 Vec3d toMergeCandidateMetrics;
565 for (
size_t i = 0; i < nGroups; ++i) {
566 const std::vector<uint32_t>& nnGroupId = groupNNIdxC[i];
567 Vec3d nnGroupZ(nnGroupId.size());
568 Vec3d nnGroupLen(nnGroupId.size());
569 for (
size_t j = 0; j < nnGroupId.size(); ++j) {
570 nnGroupZ[j] = zFeatures[nnGroupId[j]];
571 nnGroupLen[j] = lenFeatures[nnGroupId[j]];
573 float minZ =
min_col(nnGroupZ);
574 float minLen =
min_col(nnGroupLen);
576 float currentGroupRelHt =
577 (zFeatures[i] - minZ) / lenFeatures[i];
579 if (
abs(currentGroupRelHt) > PR_REL_HEIGHT_LENGTH_RATIO) {
581 float initialLenRatio =
583 if (initialLenRatio > 1.5) {
584 toMergeIds.push_back(i);
586 toMergeCandidateIds.push_back(i);
587 toMergeCandidateMetrics.push_back(initialLenRatio);
589 toMergeIds.push_back(i);
593 if ((iter == 1) && (toMergeCandidateMetrics.size() == 0)) {
596 if ((iter == 1) && (toMergeIds.size() == 0)) {
597 size_t cand_ind =
arg_max_col(toMergeCandidateMetrics);
598 toMergeIds.push_back(toMergeCandidateIds[cand_ind]);
601 std::vector<size_t> remainIds;
602 std::vector<size_t> allIds(nGroups);
603 std::iota(std::begin(allIds), std::end(allIds), 0);
604 std::set_difference(allIds.begin(), allIds.end(),
605 toMergeIds.begin(), toMergeIds.end(),
606 std::inserter(remainIds, remainIds.begin()));
608 get_subset(centroid2DFeatures, toMergeIds, groupCentroidsToMerge);
609 get_subset(centroid2DFeatures, remainIds, groupCentroidsRemain);
611 (PR_MIN_NN3 < remainIds.size() ? PR_MIN_NN3
615 knn_kdtree(groupCentroidsRemain);
617 std::vector<std::vector<size_t>> groupNNIdx;
618 std::vector<Vec3d> groupNNIdxDists;
621 groupNNIdx, groupNNIdxDists);
623 size_t nToMergeIds = toMergeIds.size();
624 size_t nRemainIds = remainIds.size();
625 for (
size_t i = 0; i < nToMergeIds; ++i) {
626 size_t toMergeId = toMergeIds[i];
628 Eigen::MatrixXf currentClusterCentroids;
629 get_subset(clusterCentroids, clusterVGroup[toMergeId],
630 currentClusterCentroids);
632 size_t nNNs = groupNNIdx.size();
634 std::vector<float> scores;
635 std::vector<size_t> filteredRemainIds;
636 std::vector<float> min3DSpacings;
638 for (
size_t j = 0; j < nNNs; ++j) {
639 size_t remainId = remainIds[groupNNIdx[j][i]];
641 float lineSegs2 = zFeatures[toMergeId] +
642 lenFeatures[toMergeId] -
644 float lineSegs1 = zFeatures[remainId] +
645 lenFeatures[remainId] -
646 zFeatures[toMergeId];
648 float verticalOverlapRatio =
649 (lineSegs2 > lineSegs1 ? lineSegs1 : lineSegs2) /
650 (lineSegs1 > lineSegs2 ? lineSegs1 : lineSegs2);
651 float horizontalOverlapRatio;
652 if ((boost::geometry::num_points(groupHulls[toMergeId]) >
654 (boost::geometry::num_points(groupHulls[remainId]) >
657 boost::geometry::intersection(groupHulls[toMergeId],
658 groupHulls[remainId],
660 float intersect_area =
661 boost::geometry::area(intersection);
663 boost::geometry::area(groupHulls[toMergeId]);
665 boost::geometry::area(groupHulls[remainId]);
666 horizontalOverlapRatio =
668 (area1 < area2 ? area1 : area2);
670 horizontalOverlapRatio = 0.0;
673 Eigen::MatrixXf nnClusterCentroids;
674 get_subset(clusterCentroids, clusterVGroup[remainId],
679 knn_kdtree2(nnClusterCentroids);
681 std::vector<std::vector<size_t>> min3D_idx;
682 std::vector<Vec3d> min3D_dists;
685 min3D_idx, min3D_dists);
686 float min3DSpacing =
min_col(min3D_dists[0]);
687 min3DSpacings.push_back(min3DSpacing);
689 Eigen::MatrixXf nnClusterCentroids2D =
690 nnClusterCentroids.block(0, 0, 2,
691 nnClusterCentroids.cols());
692 Eigen::MatrixXf currentClusterCentroids2D =
693 currentClusterCentroids.block(
694 0, 0, 2, currentClusterCentroids.cols());
695 Eigen::VectorXf nnClusterCentroids2Dmean =
696 nnClusterCentroids2D.rowwise().mean();
697 Eigen::VectorXf currentClusterCentroids2Dmean =
698 currentClusterCentroids2D.rowwise().mean();
700 sqrt((nnClusterCentroids2Dmean[0] -
701 currentClusterCentroids2Dmean[0]) *
702 (nnClusterCentroids2Dmean[0] -
703 currentClusterCentroids2Dmean[0]) +
704 (nnClusterCentroids2Dmean[1] -
705 currentClusterCentroids2Dmean[1]) *
706 (nnClusterCentroids2Dmean[1] -
707 currentClusterCentroids2Dmean[1]));
709 verticalOverlapRatio =
710 verticalOverlapRatio > 0 ? verticalOverlapRatio : 0;
713 -(1 - horizontalOverlapRatio) *
714 (1 - horizontalOverlapRatio) -
715 PR_VERTICAL_WEIGHT * (1 - verticalOverlapRatio) *
716 (1 - verticalOverlapRatio) -
717 ((min3DSpacing < min2DSpacing ? min3DSpacing
720 ((min3DSpacing < min2DSpacing
724 scores.push_back(score);
726 filteredRemainIds.push_back(remainId);
729 std::vector<size_t> scoreSortI;
730 std::vector<float> scoreSort;
732 sort_indexes<float, size_t>(scores, scoreSortI, scoreSort);
733 float score_highest = scoreSort[0];
734 if (score_highest == 0) {
737 std::vector<float> scoreSortRatio;
739 scoreSortRatio.reserve(scoreSort.size());
740 std::transform(scoreSort.begin(), scoreSort.end(),
741 std::back_inserter(scoreSortRatio),
742 [score_highest](
float value) {
743 return value / score_highest;
746 std::vector<std::size_t> scoreSortCandidateIdx;
747 for (std::size_t i = 0; i < scoreSortRatio.size(); ++i) {
748 if (scoreSortRatio[i] > 0.7) {
749 scoreSortCandidateIdx.push_back(i);
752 size_t nScoreSortCandidateIdx = scoreSortCandidateIdx.size();
753 unsigned mergeNNId = 0;
754 if (nScoreSortCandidateIdx == 1) {
757 [scoreSortI[scoreSortCandidateIdx[0]]]];
759 }
else if (nScoreSortCandidateIdx > 1) {
760 std::vector<float> min3DSpacingsFiltered;
761 std::vector<size_t> scoreSortIFiltered;
765 min3DSpacingsFiltered);
767 size_t filterMinSpacingIdx =
770 groupU[filteredRemainIds
771 [scoreSortI[filterMinSpacingIdx]]];
776 std::vector<uint32_t> currentVGroup =
777 groupVGroup[toMergeIds[i]];
778 for (
unsigned k = 0; k < currentVGroup.size(); ++k) {
779 segs_group_ids[currentVGroup[k]] = mergeNNId;
781 mergedRemainIds.push_back(mergeNNId);
782 mergedRemainIds.push_back(groupU[toMergeIds[i]]);
785 n_to_merge_ids = toMergeIds.size();
786 get_subset(segs_group_ids, initUI, cluster_ids);
788 n_clusters = clusterVGroup.size();
793 for (
unsigned j = 0; j < groupVGroup.size(); ++j) {
794 std::vector<uint32_t> currentVGroup = groupVGroup[j];
795 for (
unsigned k = 0; k < currentVGroup.size(); ++k) {
796 segs_group_ids[currentVGroup[k]] = j + 1;
802 if (outSFIndex < 0) {
804 if (outSFIndex < 0) {
812 std::vector<uint32_t> groupIdx(pointCount);
813 for (
unsigned i = 0; i < pointCount; ++i) {
814 outSF->
setValue(i, segs_group_ids[i]);
822 progressDlg->setValue(100);
823 QCoreApplication::processEvents();
826 auto elapsed =
Since(start).count() / 1000;
827 CVLog::Print(QString(
"[TreeIso] Final segs took: %1 seconds !!!")
836 const float regStrength1,
837 const float PR_DECIMATE_RES1,
839 QProgressDialog* progressDlg) {
846 if (selectedEntities.empty()) {
861 if (Init_seg_pcd(pointCloud, min_nn1, regStrength1, PR_DECIMATE_RES1,
872 const float PR_REG_STRENGTH2,
873 const float PR_DECIMATE_RES2,
874 const float PR_MAX_GAP,
876 QProgressDialog* progressDlg) {
884 if (selectedEntities.empty()) {
901 if (Intermediate_seg_pcd(pointCloud, PR_MIN_NN2, PR_REG_STRENGTH2,
902 PR_DECIMATE_RES2, PR_MAX_GAP, progressDlg)) {
912 const float PR_REL_HEIGHT_LENGTH_RATIO,
913 const float PR_VERTICAL_WEIGHT,
915 QProgressDialog* progressDlg) {
923 if (selectedEntities.empty()) {
938 if (Final_seg_pcd(pointCloud, PR_MIN_NN3, PR_REL_HEIGHT_LENGTH_RATIO,
939 PR_VERTICAL_WEIGHT, progressDlg)) {
950 unsigned n_thread ) {
951 kdtree.setBucketSize(16);
952 kdtree.setSorted(
true);
953 kdtree.setThreads(n_thread);
960 Eigen::MatrixXf& query_points,
962 std::vector<std::vector<size_t>>& res_idx,
963 std::vector<Vec3d>& res_dists) {
968 Eigen::MatrixXf distances;
970 kdtree.query(query_points, k, indices, distances);
971 res_idx.resize(indices.rows(), std::vector<size_t>(indices.cols()));
973 res_idx[i] = std::vector<size_t>(
974 indices.row(i).data(), indices.row(i).data() + indices.cols());
976 res_dists.resize(distances.rows(),
Vec3d(distances.cols()));
978 res_dists[i] =
Vec3d(distances.row(i).data(),
979 distances.row(i).data() + distances.cols());
986 Eigen::MatrixXf& query_points,
989 Eigen::MatrixXf distances;
991 kdtree.query(query_points, k, indices, distances);
992 return distances.minCoeff();
997 std::vector<std::vector<uint32_t>>& res_idx,
998 std::vector<Vec3d>& res_dists,
1000 if (dataset.empty()) {
1005 Eigen::MatrixXf mat(dataset[0].
size(), dataset.size());
1006 for (
size_t i = 0; i < dataset.size(); i++) {
1007 mat.col(i) = Eigen::VectorXf::Map(&dataset[i][0], dataset[i].
size());
1017 Eigen::MatrixXf distances;
1019 kdtree.
query(mat, k, indices, distances);
1021 res_idx.resize(indices.cols(), std::vector<uint32_t>(indices.rows()));
1023 res_idx[i] = std::vector<uint32_t>(
1024 indices.col(i).data(), indices.col(i).data() + indices.rows());
1026 res_dists.resize(distances.cols(),
Vec3d(distances.rows()));
1028 res_dists[i] =
Vec3d(distances.col(i).data(),
1029 distances.col(i).data() + distances.rows());
1033 template <
typename T>
1035 std::vector<std::vector<T>>& u_group,
1036 std::vector<T>& arr_unq,
1037 std::vector<T>& ui) {
1047 std::vector<T> arr_sorted_idx;
1048 std::vector<T> arr_sorted;
1051 const size_t n = arr.size();
1053 ui.push_back(arr_sorted_idx[0]);
1054 std::size_t counter = 0;
1057 ut.push_back(arr_sorted_idx[0]);
1062 for (std::size_t i = 1; i < n; ++i) {
1063 if (arr_sorted[i] != arr_sorted[i - 1]) {
1064 ui.push_back(arr_sorted_idx[i]);
1065 arr_unq.push_back(arr_sorted[i]);
1067 u_group.push_back(ut);
1069 ut.push_back(arr_sorted_idx[i]);
1072 ut.push_back(arr_sorted_idx[i]);
1075 u_group.push_back(ut);
1078 template <
typename T>
1080 std::vector<std::vector<T>>& u_group,
1081 std::vector<T>& arr_unq) {
1090 std::vector<T> arr_sorted_idx;
1091 std::vector<T> arr_sorted;
1094 const size_t n = arr.size();
1095 arr_unq.push_back(arr_sorted[0]);
1096 std::size_t counter = 0;
1099 ut.push_back(arr_sorted_idx[0]);
1104 for (std::size_t i = 1; i < n; ++i) {
1105 if (arr_sorted[i] != arr_sorted[i - 1]) {
1106 arr_unq.push_back(arr_sorted[i]);
1108 u_group.push_back(ut);
1110 ut.push_back(arr_sorted_idx[i]);
1113 ut.push_back(arr_sorted_idx[i]);
1116 u_group.push_back(ut);
1119 template <
typename T>
1120 void unique_group(std::vector<T>& arr, std::vector<std::vector<T>>& u_group) {
1128 std::vector<T> arr_sorted_idx;
1129 std::vector<T> arr_sorted;
1132 const size_t n = arr.size();
1133 std::size_t counter = 0;
1136 ut.push_back(arr_sorted_idx[0]);
1141 for (std::size_t i = 1; i < n; ++i) {
1142 if (arr_sorted[i] != arr_sorted[i - 1]) {
1143 u_group.push_back(ut);
1145 ut.push_back(arr_sorted_idx[i]);
1148 ut.push_back(arr_sorted_idx[i]);
1151 u_group.push_back(ut);
1154 template <
typename T1,
typename T2>
1156 std::vector<T2>& indices,
1157 std::vector<T1>& arr_sub) {
1159 for (
const auto& idx : indices) {
1160 arr_sub.push_back(arr[idx]);
1164 template <
typename T1,
typename T2>
1166 const std::vector<T2>& indices,
1167 Eigen::MatrixXf& arr_sub) {
1175 arr_sub.resize(arr[0].
size(), indices.size());
1177 for (
size_t i = 0; i < indices.size(); ++i) {
1178 for (
size_t j = 0; j < arr[0].size(); ++j) {
1179 arr_sub(j, i) = arr[indices[i]][j];
1184 template <
typename T1,
typename T2>
1186 const std::vector<T2>& indices,
1187 std::vector<std::vector<T1>>& arr_sub) {
1190 if (arr.empty() || indices.empty()) {
1194 arr_sub.resize(indices.size());
1195 for (
size_t i = 0; i < indices.size(); ++i) {
1196 arr_sub[i] = arr[indices[i]];
1200 template <
typename T1,
typename T2>
1202 std::vector<T2>& indices,
1203 std::vector<std::vector<T1>>& arr_sub) {
1205 arr_sub.resize(indices.size(), std::vector<T1>(3));
1206 for (
size_t i = 0; i < indices.size(); ++i) {
1208 arr_sub[i][0] = vec->
x;
1209 arr_sub[i][1] = vec->
y;
1210 arr_sub[i][2] = vec->
z;
1217 template <
typename T>
1219 std::vector<std::vector<T>>& y) {
1222 const unsigned pointCount = pc->
size();
1223 if (pointCount == 0) {
1227 y.resize(pointCount, std::vector<T>(3));
1229 for (
unsigned i = 0; i < pointCount; ++i) {
1231 y[i] = {
static_cast<float>(pv->
x),
static_cast<float>(pv->
y),
1232 static_cast<float>(pv->
z)};
1235 std::vector<T> y_mean;
1238 for (
unsigned i = 0; i < pointCount; ++i) {
1239 y[i][0] -= y_mean[0];
1240 y[i][1] -= y_mean[1];
1241 y[i][2] -= y_mean[2];
1246 const float regStrength,
1247 const std::vector<Vec3d>& pc,
1248 std::vector<float>& edgeWeight,
1249 std::vector<uint32_t>& Eu,
1250 std::vector<uint32_t>& Ev,
1251 std::vector<uint32_t>& in_component,
1252 std::vector<std::vector<uint32_t>>& components) {
1253 const uint32_t pointCount =
static_cast<uint32_t
>(pc.size());
1254 if (pointCount == 0) {
1258 std::vector<std::vector<uint32_t>> nn_idx;
1259 std::vector<Vec3d> nn_D;
1262 const uint32_t nNod = pointCount;
1263 const uint32_t nObs = 3;
1264 const uint32_t nEdg = pointCount * K;
1265 const uint32_t cutoff = 0;
1266 const float mode = 1.0f;
1267 const float speed = 0;
1268 const float weight_decay = 0;
1269 const float verbose = 0;
1271 if (edgeWeight.size() == 0) {
1272 edgeWeight.resize(nEdg);
1273 std::fill(edgeWeight.begin(), edgeWeight.end(), 1.0);
1277 std::vector<double> y_avg(nObs, 0.0);
1279 if (Eu.size() == 0) {
1282 for (
unsigned i = 0; i < pointCount; ++i) {
1283 y_avg[0] += pc[i][0];
1284 y_avg[1] += pc[i][1];
1285 y_avg[2] += pc[i][2];
1287 for (
unsigned j = 0; j < K; ++j) {
1289 Ev[i * K + j] = nn_idx[i][j + 1];
1293 for (
unsigned i = 0; i < pointCount; ++i) {
1294 y_avg[0] += pc[i][0];
1295 y_avg[1] += pc[i][1];
1296 y_avg[2] += pc[i][2];
1300 y_avg[0] /= pointCount;
1301 y_avg[1] /= pointCount;
1302 y_avg[2] /= pointCount;
1304 std::vector<std::vector<float>> y = pc;
1305 for (
unsigned i = 0; i < pointCount; ++i) {
1306 y[i][0] -=
static_cast<float>(y_avg[0]);
1307 y[i][1] -=
static_cast<float>(y_avg[1]);
1308 y[i][2] -=
static_cast<float>(y_avg[2]);
1311 std::vector<float> nodeWeight(pointCount, 1.0);
1312 std::vector<Vec3d> solution(pointCount, std::vector<float>(K));
1313 CP::cut_pursuit<float>(nNod, nEdg, nObs, y, Eu, Ev, edgeWeight, nodeWeight,
1314 solution, in_component, components, regStrength,
1315 cutoff, mode, speed, weight_decay, verbose);
1320 const float regStrength,
1321 const std::vector<Vec3d>& pc_vec,
1323 std::vector<uint32_t>& Eu,
1324 std::vector<uint32_t>& Ev,
1325 std::vector<uint32_t>& in_component) {
1327 const uint32_t pointCount =
static_cast<uint32_t
>(pc_vec.size());
1329 const uint32_t nNod = pointCount;
1330 const uint32_t nObs = 2;
1331 const uint32_t nEdgMax = pointCount * K;
1332 const uint32_t cutoff = 0;
1333 const float mode = 1;
1334 const float speed = 0;
1335 const float weight_decay = 0;
1336 const float verbose = 0;
1338 if (edgeWeight.size() == 0) {
1339 edgeWeight.resize(nEdgMax);
1340 std::fill(edgeWeight.begin(), edgeWeight.end(), 1.0);
1342 const uint32_t nEdg =
static_cast<uint32_t
>(edgeWeight.size());
1345 Vec3d y_avg(nObs, 0.0);
1347 if (Eu.size() == 0) {
1348 std::vector<std::vector<uint32_t>> nn_idx;
1349 std::vector<Vec3d> nn_D;
1353 for (uint32_t i = 0; i < pointCount; ++i) {
1354 y_avg[0] += pc_vec[i][0];
1355 y_avg[1] += pc_vec[i][1];
1356 for (
unsigned j = 0; j < K; ++j) {
1358 Ev[i * K + j] = nn_idx[i][j + 1];
1362 for (
unsigned i = 0; i < pointCount; ++i) {
1363 y_avg[0] += pc_vec[i][0];
1364 y_avg[1] += pc_vec[i][1];
1368 y_avg[0] /= pointCount;
1369 y_avg[1] /= pointCount;
1371 std::vector<Vec3d> y = pc_vec;
1372 for (
unsigned i = 0; i < pointCount; ++i) {
1373 y[i][0] -=
static_cast<float>(y_avg[0]);
1374 y[i][1] -=
static_cast<float>(y_avg[1]);
1377 std::vector<float> nodeWeight(pointCount, 1.0);
1378 std::vector<std::vector<uint32_t>> components;
1379 std::vector<std::vector<float>> solution(pointCount, std::vector<float>(K));
1380 CP::cut_pursuit<float>(nNod, nEdg, nObs, y, Eu, Ev, edgeWeight, nodeWeight,
1381 solution, in_component, components, regStrength,
1382 cutoff, mode, speed, weight_decay, verbose);
1385 template <
typename T>
1387 auto min_element_it = std::min_element(arr.begin(), arr.end());
1388 std::size_t min_index = std::distance(arr.begin(), min_element_it);
1392 template <
typename T>
1394 auto max_element_it = std::max_element(arr.begin(), arr.end());
1395 std::size_t max_index = std::distance(arr.begin(), max_element_it);
1399 template <
typename T>
1400 void min_col(std::vector<std::vector<T>>& arr, std::vector<T>& min_vals) {
1407 for (
size_t j = 1; j < arr.size(); j++) {
1408 const auto& row = arr[j];
1409 for (
size_t i = 0; i < row.size(); i++) {
1410 min_vals[i] =
std::min(min_vals[i], row[i]);
1415 template <
typename T>
1417 auto result_it = std::min_element(arr.begin(), arr.end());
1422 template <
typename T>
1425 return std::numeric_limits<T>::quite_NaN();
1429 for (
const T& value : arr) {
1433 return static_cast<T
>(sum /= arr.size());
1436 template <
typename T>
1438 size_t n = arr.size();
1440 return std::numeric_limits<T>::quiet_NaN();
1443 std::sort(arr.begin(), arr.end());
1446 return (arr[n / 2 - 1] + arr[n / 2]) / 2;
1452 template <
typename T>
1454 std::unordered_map<T, int> freq;
1455 for (
const auto& val : arr) freq[val]++;
1456 return std::max_element(freq.begin(), freq.end(),
1457 [](
const auto& a,
const auto& b) {
1458 return a.second < b.second;
1463 template <
typename T>
1464 void max_col(std::vector<std::vector<T>>& arr, std::vector<T>& max_vals) {
1471 for (
size_t j = 1; j < arr.size(); j++) {
1472 const auto& row = arr[j];
1473 for (
size_t i = 0; i < row.size(); i++) {
1474 max_vals[i] =
std::max(max_vals[i], row[i]);
1479 template <
typename T>
1480 void mean_col(std::vector<std::vector<T>>& arr, std::vector<T>& mean_vals) {
1486 std::vector<double> sums(arr[0].
size(), 0.0);
1488 for (
const std::vector<T>& element : arr) {
1489 for (
size_t i = 0; i < arr[0].size(); i++) {
1490 sums[i] += element[i];
1494 mean_vals = std::vector<T>(arr[0].
size());
1495 for (
size_t i = 0; i < arr[0].size(); i++) {
1496 mean_vals[i] =
static_cast<T
>(sums[i] / arr.size());
1500 template <
typename T>
1503 std::vector<std::vector<T>>& vec_dec) {
1511 size_t num_rows = arr.size();
1512 if (num_rows == 0) {
1516 size_t num_cols = arr[0].size();
1518 std::vector<T> arr_min;
1520 vec_dec.resize(num_rows, std::vector<T>(num_cols));
1522 for (
unsigned i = 0; i < num_rows; ++i) {
1523 for (
unsigned j = 0; j < num_cols; ++j) {
1524 vec_dec[i][j] =
std::floor((arr[i][j] - arr_min[j]) / res) + 1;
1530 template <
typename T>
1532 std::vector<size_t>& idx,
1533 std::vector<std::vector<T>>& v_sorted) {
1538 size_t m = v.size();
1542 size_t n = v[0].size();
1545 std::iota(idx.begin(), idx.end(), 0);
1548 v_sorted.resize(m, std::vector<T>(n));
1554 std::stable_sort(idx.begin(), idx.end(), [&v](
size_t i1,
size_t i2) {
1556 for (size_t k = 0; k < v[0].size(); ++k) {
1557 if (v[i1][k] == v[i2][k]) {
1560 return v[i1][k] < v[i2][k];
1566 for (
size_t i = 0; i < idx.size(); ++i) {
1567 v_sorted[i].resize(n);
1568 for (
size_t k = 0; k < n; ++k) {
1569 v_sorted[i][k] = v[idx[i]][k];
1575 template <
typename ValueType,
typename IndexType>
1577 std::vector<IndexType>& idx,
1578 std::vector<ValueType>& v_sorted) {
1582 size_t m = v.size();
1587 std::iota(idx.begin(), idx.end(), 0);
1591 std::stable_sort(idx.begin(), idx.end(), [&v](IndexType i1, IndexType i2) {
1592 return v[i1] < v[i2];
1595 for (
size_t i = 0; i < idx.size(); ++i) {
1596 v_sorted[i] = v[idx[i]];
1600 template <
typename T>
1602 std::vector<size_t>& ia,
1603 std::vector<size_t>& ic) {
1607 std::vector<std::vector<T>> arr_sorted;
1608 arr_sorted.resize(arr.size());
1609 std::vector<size_t> sort_idx;
1614 const size_t num_rows = arr_sorted.size();
1615 const size_t num_cols = arr_sorted[0].size();
1617 ic.resize(num_rows);
1618 ia.push_back(sort_idx[0]);
1619 std::size_t counter = 0;
1620 ic[sort_idx[0]] = counter;
1625 for (std::size_t i = 1; i < num_rows; ++i) {
1627 for (std::size_t k = 0; k < num_cols; ++k) {
1628 if (arr_sorted[i][k] != arr_sorted[i - 1][k]) {
1635 ia.push_back(sort_idx[i]);
1638 ic[sort_idx[i]] = counter;
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
boost::geometry::model::multi_polygon< polygon > multi_polygon
void knn_cpp_build(knncpp::KDTreeMinkowskiX< float, knncpp::EuclideanDistance< float >> &kdtree, unsigned n_thread)
static const char FinalSegsSFName[]
void unique_index_by_rows(std::vector< std::vector< T >> &arr, std::vector< size_t > &ia, std::vector< size_t > &ic)
void knn_cpp_query(knncpp::KDTreeMinkowskiX< float, knncpp::EuclideanDistance< float >> &kdtree, Eigen::MatrixXf &query_points, size_t k, std::vector< std::vector< size_t >> &res_idx, std::vector< Vec3d > &res_dists)
boost::geometry::model::d2::point_xy< double > point_xy
bool perform_cut_pursuit(const uint32_t K, const float regStrength, const std::vector< Vec3d > &pc, std::vector< float > &edgeWeight, std::vector< uint32_t > &Eu, std::vector< uint32_t > &Ev, std::vector< uint32_t > &in_component, std::vector< std::vector< uint32_t >> &components)
void perform_cut_pursuit2d(const uint32_t K, const float regStrength, const std::vector< Vec3d > &pc_vec, Vec3d &edgeWeight, std::vector< uint32_t > &Eu, std::vector< uint32_t > &Ev, std::vector< uint32_t > &in_component)
void max_col(std::vector< std::vector< T >> &arr, std::vector< T > &max_vals)
void sort_indexes_by_row(std::vector< std::vector< T >> &v, std::vector< size_t > &idx, std::vector< std::vector< T >> &v_sorted)
T mean_col(std::vector< T > &arr)
T mode_col(std::vector< T > &arr)
boost::geometry::model::polygon< point_xy > polygon
void sort_indexes(std::vector< ValueType > &v, std::vector< IndexType > &idx, std::vector< ValueType > &v_sorted)
static auto Since(std::chrono::time_point< clock_t, duration_t > const &start)
float knn_cpp_query_min_d(knncpp::KDTreeMinkowskiX< float, knncpp::EuclideanDistance< float >> &kdtree, Eigen::MatrixXf &query_points, size_t k)
T median_col(std::vector< T > &arr)
void min_col(std::vector< std::vector< T >> &arr, std::vector< T > &min_vals)
void toTranslatedVector(const ccPointCloud *pc, std::vector< std::vector< T >> &y)
size_t arg_max_col(std::vector< T > &arr)
boost::geometry::model::multi_point< point_xy > multi_point
void decimate_vec(std::vector< std::vector< T >> &arr, T res, std::vector< std::vector< T >> &vec_dec)
void knn_cpp_nearest_neighbors(const std::vector< Vec3d > &dataset, size_t k, std::vector< std::vector< uint32_t >> &res_idx, std::vector< Vec3d > &res_dists, unsigned n_thread)
std::vector< float > Vec3d
size_t arg_min_col(std::vector< T > &arr)
static const char IntermedSegsSFName[]
static const char InitSegsSFName[]
void unique_group(std::vector< T > &arr, std::vector< std::vector< T >> &u_group, std::vector< T > &arr_unq, std::vector< T > &ui)
void get_subset(std::vector< T1 > &arr, std::vector< T2 > &indices, std::vector< T1 > &arr_sub)
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
static bool Init_seg(const unsigned min_nn1, const float regStrength1, const float PR_DECIMATE_RES1, ecvMainAppInterface *app, QProgressDialog *progressDlg)
static bool Intermediate_seg_pcd(ccPointCloud *pc, const unsigned PR_MIN_NN2, const float PR_REG_STRENGTH2, const float PR_DECIMATE_RES2, const float PR_MAX_GAP, QProgressDialog *progressDlg=nullptr)
static bool Final_seg(const unsigned PR_MIN_NN3, const float PR_REL_HEIGHT_LENGTH_RATIO, const float PR_VERTICAL_WEIGHT, ecvMainAppInterface *app, QProgressDialog *progressDlg)
static bool Final_seg_pcd(ccPointCloud *pc, const unsigned PR_MIN_NN3, const float PR_REL_HEIGHT_LENGTH_RATIO, const float PR_VERTICAL_WEIGHT, QProgressDialog *progressDlg=nullptr)
static bool Init_seg_pcd(ccPointCloud *pc, const unsigned min_nn1, const float regStrength1, const float PR_DECIMATE_RES1, QProgressDialog *progressDlg=nullptr)
static bool Intermediate_seg(const unsigned PR_MIN_NN2, const float PR_REG_STRENGTH2, const float PR_DECIMATE_RES2, const float PR_MAX_GAP, ecvMainAppInterface *app, QProgressDialog *progressDlg)
virtual void showSF(bool state)
Sets active scalarfield visibility.
Hierarchical CLOUDVIEWER Object.
virtual void redrawDisplay(bool forceRedraw=true, bool only2D=false)
Redraws associated display.
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
bool isA(CV_CLASS_ENUM type) const
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
int addScalarField(const char *uniqueName) override
Creates a new scalar field and registers it.
int getScalarFieldIndexByName(const char *name) const
Returns the index of a scalar field represented by its name.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned size() const override
const CCVector3 * getPoint(unsigned index) const override
A simple scalar field (to be associated to a point cloud)
void fill(ScalarType fillValue=0)
Fills the array with a particular value.
virtual void computeMinAndMax()
Determines the min and max values.
ScalarType & getValue(std::size_t index)
void setValue(std::size_t index, ScalarType value)
Main application interface (for plugins)
virtual const ccHObject::Container & getSelectedEntities() const =0
Returns currently selected entities ("read only")
virtual void dispToConsole(QString message, ConsoleMessageLevel level=STD_CONSOLE_MESSAGE)=0
void query(const Eigen::MatrixBase< Derived > &queryPoints, const size_t knn, Matrixi &indices, Matrix &distances) const
void setThreads(const unsigned int threads)
void setBucketSize(const Index bucketSize)
void setSorted(const bool sorted)
__host__ __device__ int2 abs(int2 v)
MiniVec< float, N > floor(const MiniVec< float, N > &a)
Eigen::Matrix< Index, Eigen::Dynamic, Eigen::Dynamic > Matrixi