1 #pragma warning(push, 0)
4 #include <pcl/common/common.h>
5 #include <pcl/filters/extract_indices.h>
6 #include <pcl/io/pcd_io.h>
7 #include <pcl/visualization/pcl_visualizer.h>
26 "\tcloud_viewer [options] <infile>\n"
27 "Options (defaults in brackets):\n"
28 "\t-gnuplot print result as a gnuplot command\n"
29 "\t-r <radius> radius for point smoothing [7.0]\n"
30 "\t (when negative, it is set to dNN)\n"
31 "\t-k <n> number of nearest neighbours used for creating triplets\n"
33 "\t-n <n> number of the best triplets to use [3]\n"
34 "\t-a <alpha> maximum angle between the lines in a triplet [0.015]\n"
35 "\t-s <scale> scalingfactor for clustering [1.0]\n"
36 "\t-t <dist> best cluster distance [5.0]\n"
37 "\t-m <n> minimum number of triplets for a cluster [5]\n"
38 "\t-o <outfile> write results to <outfile>\n"
39 "\t-x11 show interactive window with clustering\n"
40 "\t-v <n> be verbose and save debug trace to file. n is the\n"
43 "\t1.0 from 2018-03-27";
84 return (
x == p.
x &&
y == p.
y &&
z == p.
z);
89 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud,
90 std::vector<hc::triplet>
const &triplets) {
93 for (
size_t tripletIndex = 0; tripletIndex < triplets.size();
95 hc::triplet const &tripletEl = triplets[tripletIndex];
96 double const r = (double)((tripletIndex * 23) % 19) / 18.0;
97 double const g = (double)((tripletIndex * 23) % 7) / 6.0;
98 double const b = (double)((tripletIndex * 23) % 3) / 2.0;
101 pcl::PointXYZI
const &pointA = (*cloud)[tripletEl.
pointIndexA];
102 pcl::PointXYZI
const &pointB = (*cloud)[tripletEl.
pointIndexB];
104 std::ostringstream oss;
105 oss <<
"line" << lineId;
106 viewer.addLine<pcl::PointXYZI>(pointA, pointB, r, g, b, oss.str());
111 pcl::PointXYZI
const &pointA = (*cloud)[tripletEl.
pointIndexB];
112 pcl::PointXYZI
const &pointB = (*cloud)[tripletEl.
pointIndexC];
114 std::ostringstream oss;
115 oss <<
"line" << lineId;
116 viewer.addLine<pcl::PointXYZI>(pointA, pointB, r, g, b, oss.str());
125 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud,
128 std::vector<pcl::PointIndicesPtr> clusters =
cluster.getClusters();
130 for (
size_t clusterIndex = 0; clusterIndex < clusters.size();
132 pcl::PointIndicesPtr
const &pointIndices = clusters[clusterIndex];
133 pcl::PointCloud<pcl::PointXYZI>::Ptr clusterCloud(
134 new pcl::PointCloud<pcl::PointXYZI>());
135 pcl::ExtractIndices<pcl::PointXYZI> extract;
136 extract.setInputCloud(cloud);
137 extract.setIndices(pointIndices);
138 extract.setNegative(
false);
139 extract.filter(*clusterCloud);
141 std::vector<mst::state> mstResult =
144 if (mstResult.size() < 1)
continue;
146 double const r = (double)((clusterIndex * 23) % 19) / 18.0;
147 double const g = (double)((clusterIndex * 23) % 7) / 6.0;
148 double const b = (double)((clusterIndex * 23) % 3) / 2.0;
150 mst::state const &lastMstResult = mstResult[mstResult.size() - 1];
151 std::vector<mst::edge>
const &edges = lastMstResult.
edges;
152 for (
size_t i = 0; i < edges.size(); ++i) {
154 pcl::PointXYZI
const &pointA = (*clusterCloud)[edge.
voxelIndexA];
155 pcl::PointXYZI
const &pointB = (*clusterCloud)[edge.
voxelIndexB];
157 std::ostringstream oss;
158 oss <<
"line" << lineId;
159 viewer.addLine<pcl::PointXYZI>(pointA, pointB, r, g, b, oss.str());
197 std::vector<hc::triplet> triplets,
float scale,
float cdist,
198 size_t cleanup_min_triplets,
int opt_verbose = 0) {
201 hc::compute_hc(cloud, triplets, scale_triplet_metric, cdist, opt_verbose);
205 return hc::toCluster(triplets, cleaned_up_cluster_group, cloud->size());
209 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_rgb) {
211 pcl::copyPointCloud(*cloud, *cloud_rgb);
214 for (pcl::PointCloud<pcl::PointXYZRGB>::iterator it = cloud_rgb->begin();
215 it != cloud_rgb->end(); ++it) {
216 it->r = (uint8_t)(256 * (index % 8) / 8);
224 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_rgb,
225 float minIntensity = 0.0
f,
float maxIntensity = 4000.0
f) {
227 pcl::copyPointCloud(*cloud, *cloud_rgb);
229 float size = maxIntensity - minIntensity;
231 for (
size_t i = 0; i < cloud->size(); ++i) {
232 pcl::PointXYZRGB &point = (*cloud_rgb)[i];
234 point.r = (uint8_t)(256 * (((*cloud)[i].intensity - minIntensity) / size));
235 point.g = point.r / 2;
241 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_rgb,
243 std::vector<rgb_t>
const cluster_rgb) {
245 pcl::copyPointCloud(*cloud, *cloud_rgb);
248 for (
size_t i = 0; i < cloud->size(); ++i) {
249 pcl::PointXYZRGB &point = (*cloud_rgb)[i];
256 std::vector<pcl::PointIndicesPtr> clusters =
cluster.getClusters();
257 for (
size_t i = 0; i < clusters.size(); ++i) {
258 pcl::PointIndicesPtr
const &pointIndices = clusters[i];
259 rgb_t rgb = cluster_rgb[i];
260 std::vector<int> indices = pointIndices->indices;
261 for (
size_t i = 0; i < indices.size(); ++i) {
262 int index = indices[i];
263 pcl::PointXYZRGB &point = (*cloud_rgb)[index];
273 pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud,
Cluster const cluster) {
274 std::vector<rgb_t> cluster_rgb;
275 std::vector<pcl::PointIndicesPtr> clusters =
cluster.getClusters();
276 for (
size_t clusterIndex = 0; clusterIndex < clusters.size();
278 pcl::PointIndicesPtr
const &pointIndices = clusters[clusterIndex];
279 double const r = (double)((clusterIndex * 23) % 19) / 18.0;
280 double const g = (double)((clusterIndex * 23) % 7) / 6.0;
281 double const b = (double)((clusterIndex * 23) % 3) / 2.0;
283 rgb.
r = (uint8_t)(r * 255);
284 rgb.
g = (uint8_t)(g * 255);
285 rgb.
b = (uint8_t)(b * 255);
287 cluster_rgb.push_back(rgb);
304 std::ostringstream oss, header;
305 pcl::PointXYZ min, max;
306 header <<
"set mouse\n";
307 pcl::getMinMax3D(*cloud, min, max);
308 header <<
"set xrange [" << min.x <<
":" << max.x <<
"]\n";
309 header <<
"set yrange [" << min.y <<
":" << max.y <<
"]\n";
310 header <<
"set zrange [" << min.z <<
":" << max.z <<
"]\nsplot ";
312 std::vector<pcl::PointXYZ, Eigen::aligned_allocator<pcl::PointXYZ> > points =
314 std::vector<pcl::PointIndicesPtr> clusters =
cluster.getClusters();
315 for (
size_t clusterIndex = 0; clusterIndex < clusters.size();
317 pcl::PointIndicesPtr
const &pointIndices = clusters[clusterIndex];
319 rgb_t rgb = cluster_rgb[clusterIndex];
320 unsigned long rgb_hex = (rgb.
r << 16) | (rgb.
g << 8) | rgb.
b;
322 header <<
" '-' with points lc '#" << std::hex << rgb_hex
323 <<
"' title 'track " << clusterIndex <<
"',";
324 for (
size_t i = 0; i < pointIndices->indices.size(); ++i) {
325 int index = pointIndices->indices[i];
326 pcl::PointXYZ point = cloud->points[index];
329 for (std::vector<pcl::PointXYZ,
330 Eigen::aligned_allocator<pcl::PointXYZ> >::iterator it =
332 it != points.begin(); --it) {
333 if (it->x == point.x && it->y == point.y && it->z == point.z) {
338 oss << point.x <<
" " << point.y <<
" " << point.z << std::endl;
340 oss <<
"e" << std::endl;
344 header <<
"'-' with points lc 'red' title 'noise'\n";
345 for (std::vector<pcl::PointXYZ,
346 Eigen::aligned_allocator<pcl::PointXYZ> >::iterator it =
348 it != points.end(); ++it) {
349 oss << it->x <<
" " << it->y <<
" " << it->z << std::endl;
353 oss <<
"pause mouse keypress\n";
354 std::cout << header.str() << oss.str();
367 std::ostringstream oss;
368 oss <<
"set mouse\nrgb(r,g,b) = 65536 * int(r) + 256 * int(g) + int(b)\n";
369 oss <<
"splot '-' using 1:2:3:(rgb($4,$5,$6)) with points lc rgb variable\n";
370 for (pcl::PointCloud<pcl::PointXYZRGB>::iterator it = cloud->begin();
371 it != cloud->end(); ++it) {
372 oss << it->x <<
" " << it->y <<
" " << it->z <<
" ";
373 oss << (int)it->r <<
" " << (
int)it->g <<
" " << (int)it->b <<
"\n";
376 oss <<
"pause mouse keypress\n";
377 std::cout << oss.str();
388 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud,
389 const char *fname =
"debug_smoothed.gnuplot") {
391 std::ofstream of(fname);
392 pcl::PointXYZI min, max;
394 std::cerr <<
"Could Not save under '" << fname << std::endl;
398 pcl::getMinMax3D(*cloud, min, max);
400 of <<
"set xrange [" << min.x <<
":" << max.x <<
"]\n";
401 of <<
"set yrange [" << min.y <<
":" << max.y <<
"]\n";
402 of <<
"set zrange [" << min.z <<
":" << max.z <<
"]\n";
404 of <<
"splot '-' with points lc 'black' title 'original', '-' with points lc "
405 "'red' title 'smoothed'\n";
406 for (
size_t i = 0; i < cloud->points.size(); ++i) {
407 pcl::PointXYZI point = cloud->points[i];
408 of << point.x <<
" " << point.y <<
" " << point.z << std::endl;
412 for (
size_t i = 0; i < cloud_smooth->points.size(); ++i) {
413 pcl::PointXYZI point = cloud_smooth->points[i];
414 of << point.x <<
" " << point.y <<
" " << point.z << std::endl;
416 of <<
"e\npause mouse keypress\n";
435 std::vector<Point> points;
437 for (
size_t i = 0; i < cloud->points.size(); ++i) {
438 pcl::PointXYZ point = cloud->points[i];
439 points.push_back(
Point(point));
442 std::vector<pcl::PointIndicesPtr> clusters =
cluster.getClusters();
443 for (
size_t clusterIndex = 0; clusterIndex < clusters.size();
445 pcl::PointIndicesPtr
const &pointIndices = clusters[clusterIndex];
446 for (
size_t i = 0; i < pointIndices->indices.size(); ++i) {
447 int index = pointIndices->indices[i];
448 points[index].clIds.push_back(clusterIndex);
452 std::cout <<
"# Comment: a trackID of -1 represents noise\n# x, y, z, trackID\n";
454 for (std::vector<Point>::iterator it = points.begin(); it != points.end();
456 std::cout << it->x <<
"," << it->y <<
"," << it->z <<
",";
457 if (it->clIds.empty()) {
461 for (
size_t i = 0; i < it->clIds.size(); ++i) {
465 std::cout << it->clIds[i];
467 std::cout << std::endl;
480 const char *fname =
"debug_smoothed.csv") {
482 std::ofstream of(fname);
484 std::cerr <<
"Could Not save under '" << fname << std::endl;
487 of <<
"# x,y,z" << std::endl;
488 for (
size_t i = 0; i < cloud->points.size(); ++i) {
489 pcl::PointXYZI point = cloud->points[i];
490 of << point.x <<
"," << point.y <<
"," << point.z << std::endl;
495 int main(
int argc,
char **argv) {
497 double time1 = 0.0, tstart;
500 char *infile_name = NULL, *outfile_name = NULL;
502 bool gnuplot =
false, x11 =
false;
523 opt_params = bestParams;
526 for (
int i = 1; i < argc; i++) {
527 if (0 == strcmp(argv[i],
"-v")) {
530 opt_verbose = atoi(argv[i]);
532 std::cerr <<
usage << std::endl;
535 }
else if (0 == strcmp(argv[i],
"-gnuplot")) {
537 }
else if (0 == strcmp(argv[i],
"-s")) {
542 std::cerr <<
usage << std::endl;
545 }
else if (0 == strcmp(argv[i],
"-r")) {
550 std::cerr <<
usage << std::endl;
553 }
else if (0 == strcmp(argv[i],
"-k")) {
558 std::cerr <<
usage << std::endl;
561 }
else if (0 == strcmp(argv[i],
"-n")) {
566 std::cerr <<
usage << std::endl;
569 }
else if (0 == strcmp(argv[i],
"-a")) {
574 std::cerr <<
usage << std::endl;
577 }
else if (0 == strcmp(argv[i],
"-t")) {
582 std::cerr <<
usage << std::endl;
585 }
else if (0 == strcmp(argv[i],
"-m")) {
590 std::cerr <<
usage << std::endl;
593 }
else if (0 == strcmp(argv[i],
"-o")) {
595 std::cerr <<
"Not enough parameters\n" <<
usage << std::endl;
597 }
else if (argv[i + 1][0] ==
'-') {
598 std::cerr <<
"Please enter outfile name\n" <<
usage << std::endl;
601 outfile_name = argv[++i];
602 }
else if (0 == strcmp(argv[i],
"-x11")) {
604 }
else if (argv[i][0] ==
'-') {
605 std::cerr <<
usage << std::endl;
608 infile_name = argv[i];
614 std::cerr <<
"Error: no infile given!\n" <<
usage << std::endl;
617 if (0 != access(infile_name, R_OK)) {
618 std::cerr <<
"Error: cannot read infile '" << infile_name <<
"'!\n" <<
usage << std::endl;
626 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_xyzti(
627 new pcl::PointCloud<pcl::PointXYZI>());
628 pcl::io::loadPCDFile(std::string(infile_name), *cloud_xyzti);
629 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(
630 new pcl::PointCloud<pcl::PointXYZ>());
631 pcl::copyPointCloud(*cloud_xyzti, *cloud_xyz);
632 if (cloud_xyz->size() == 0) {
633 std::cerr <<
"Error: empty cloud in file '" << infile_name <<
"'\n";
637 time1 = clock() - tstart;
638 std::cerr <<
"file loading time: " << time1 / CLOCKS_PER_SEC <<
"s"
645 if (opt_verbose > 0) {
646 std::cout <<
"Computed smoothen radius: " << fq << std::endl;
674 pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_xyzti_smooth(
675 new pcl::PointCloud<pcl::PointXYZI>());
681 if (opt_verbose > 0) {
686 time1 = clock() - tstart;
687 std::cerr <<
"smoothen time: " << time1 / CLOCKS_PER_SEC <<
"s" << std::endl;
692 std::vector<hc::triplet> triplets;
701 time1 = clock() - tstart;
702 std::cerr <<
"gen triplet time: " << time1 / CLOCKS_PER_SEC <<
"s"
718 time1 = clock() - tstart;
719 std::cerr <<
"clustering time: " << time1 / CLOCKS_PER_SEC <<
"s"
728 }
else if (outfile_name) {
730 std::streambuf *backup = std::cout.rdbuf();
731 std::ofstream of(outfile_name);
732 std::cout.rdbuf(of.rdbuf());
734 std::cout.rdbuf(backup);
737 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_xyzrgb(
738 new pcl::PointCloud<pcl::PointXYZRGB>());
741 pcl::visualization::PCLVisualizer viewer(
"PCL Viewer");
742 viewer.setPosition(0, 0);
743 viewer.setSize(800, 600);
744 viewer.setShowFPS(
true);
745 viewer.setBackgroundColor(1.0, 1.0, 1.0);
746 viewer.setCameraPosition(0.0, 0.0, 2000.0, 0.0, 1.0, 0.0);
748 if (opt_verbose > 2) {
753 viewer.addPointCloud(cloud_xyzrgb,
"cloud");
754 viewer.setPointCloudRenderingProperties(
755 pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5,
"cloud");
756 if (opt_verbose > 2) {
757 viewer.setPointCloudRenderingProperties(
758 pcl::visualization::PCL_VISUALIZER_OPACITY, 0.75,
"cloud");