PointCloudLibrary / PointCloudLibrary/pcl
[visualization] PCLVisualizer::addCorrespondences/updateCorrespondences does not show all correspondences
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 11.1k
- Forks
- 4.7k
- Avg merge
- 4d 10h
- Merged PRs (30d)
- 6
Description
Describe the bug
I use Registration::registerVisualizationCallback() to show correspondences. The code employs PCLVisualizer::addCorrespondences(). This does not lead to all correspondences getting shown. If instead I iterate over all correspondences manually and addLine() for each, all are shown as expected. Somewhere inside PCLVisualizer, items get lost.
Expected behavior
All correspondences passed to addCorrespondences() function should be shown.
Current Behavior
Not all correspondences passed to addCorrespondences() function are shown.
To Reproduce
mwe.cpp
#include <pcl/io/pcd_io.h>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
using namespace std;
using namespace pcl;
using namespace pcl::visualization;
using PointT = PointXYZ;
using CloudT = PointCloud<PointT>;
using namespace Eigen;
struct RegistrationVisualizer {
pcl::visualization::PCLVisualizer::Ptr optimization_viewer;
RegistrationVisualizer();
void visualize_registration(pcl::Registration<PointT, PointT> ®);
};
int main(int argc, char *argv[]) {
Matrix4f transformation;
transformation << 1, 0, 0, 6.7, 0, 1, 0, 12.3, 0, 0, 1, 0.7, 0, 0, 0, 1;
CloudT::Ptr source{new CloudT};
CloudT::Ptr target{new CloudT};
io::loadPCDFile("../scene_filtered.pcd", *target);
io::loadPCDFile("../template.pcd", *source);
IterativeClosestPoint<PointT, PointT> icp;
icp.setInputSource(source);
icp.setInputTarget(target);
icp.setMaxCorrespondenceDistance(0.1);
RegistrationVisualizer regvis;
regvis.visualize_registration(icp);
icp.align(*source, transformation);
return 0;
}
RegistrationVisualizer::RegistrationVisualizer() {
optimization_viewer = pcl::make_shared<pcl::visualization::PCLVisualizer>();
optimization_viewer->setWindowName("Correspondences");
}
void RegistrationVisualizer::visualize_registration(
pcl::Registration<PointT, PointT> ®) {
using namespace pcl;
using namespace pcl::visualization;
std::function<
pcl::Registration<PointT, PointT>::UpdateVisualizerCallbackSignature>
callback([this](const CloudT &c1, const pcl::Indices &idxs1,
const CloudT &c2, const pcl::Indices &idxs2) {
if (!idxs1.size() || !idxs2.size()) {
return;
}
// turn idxs into one correspondence vector
Correspondences correspondences;
for (size_t i = 0; i < idxs1.size(); ++i) {
correspondences.push_back(Correspondence(idxs1[i], idxs2[i], 1));
}
// viewer needs ptrs, not values (expensiveish)
const CloudT::Ptr c1_correspondences = c1.makeShared();
const CloudT::Ptr c2_correspondences = c2.makeShared();
if (!this->optimization_viewer->updatePointCloud<PointT>(
c1_correspondences, "c1")) {
this->optimization_viewer->addPointCloud<PointT>(c1_correspondences,
"c1");
this->optimization_viewer->setPointCloudRenderingProperties(
PCL_VISUALIZER_COLOR, 0, 1, 1, "c1");
this->optimization_viewer->setPointCloudRenderingProperties(
PCL_VISUALIZER_POINT_SIZE, 3, "c1");
}
if (!this->optimization_viewer->updateText("Source", 10, 10)) {
this->optimization_viewer->addText("Source", 10, 10, 20, 0, 1, 1);
}
if (!this->optimization_viewer->updatePointCloud<PointT>(
c2_correspondences, "c2")) {
this->optimization_viewer->addPointCloud<PointT>(c2_correspondences,
"c2");
this->optimization_viewer->setPointCloudRenderingProperties(
PCL_VISUALIZER_COLOR, 1, 1, 0, "c2");
this->optimization_viewer->setPointCloudRenderingProperties(
PCL_VISUALIZER_POINT_SIZE, 3, "c2");
}
if (!this->optimization_viewer->updateText("Target", 10, 40)) {
this->optimization_viewer->addText("Target", 10, 40, 20, 1, 1, 0);
}
// works as expected
/* int c = 0; */
/* for (const auto& corr : correspondences) { */
/* const auto p1 = c1_correspondences->points[corr.index_query]; */
/* const auto p2 = c2_correspondences->points[corr.index_match]; */
/* const string name = "line" + to_string(c); */
/* this->optimization_viewer->removeShape(name); */
/* this->optimization_viewer->addLine(p1, p2, 1, 0, 0, name); */
/* c++; */
/* } */
// many lines missing
if (!this->optimization_viewer->updateCorrespondences<PointT>(
c1_correspondences, c2_correspondences, correspondences)) {
this->optimization_viewer->addCorrespondences<PointT>(
c1_correspondences, c2_correspondences, correspondences,
"correspondences");
}
this->optimization_viewer->setShapeRenderingProperties(
PCL_VISUALIZER_LINE_WIDTH, 5, "correspondences");
this->optimization_viewer->spin();
});
reg.registerVisualizationCallback(callback);
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.19.8)
set(CMAKE_CXX_STANDARD 20)
find_package(PCL REQUIRED)
add_executable(mwe mwe.cpp)
target_link_libraries(mwe ${PCL_LIBRARIES})
target_include_directories(mwe PRIVATE ${PCL_INCLUDE_DIRS})
pcds:
First screenshot is using updateCorrespondences(). Notice how on the right there are no correspondences.
Second screenshot I add them by hand with addLine(). Many correspondences on the right.
Your Environment (please complete the following information):
- OS: macos 12.6.5
- Compiler: Apple clang version 14.0.0 (clang-1400.0.29.202) (arm)
- PCL Version 1.13 (4d8f60706c5d97c4a5b3b3da65f107cc7716ce1e)
I'm at a loss here. I don't know VTK, but the code in addCorrespondences() does not look wrong. I could verify that in https://github.com/PointCloudLibrary/pcl/blob/master/visualization/include/pcl/visualization/impl/pcl_visualizer.hpp#L1259, the full number of found correspondences is iterated, but somehow not everything shows up.
This led me on a merry chase as I had first assumed the correspondence estimation to somehow fail, but it seems to be just the visualization.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the mwe.cpp reproducer and the addCorrespondences()/updateCorrespondences() implementation in visualization/include/pcl/visualization/impl/pcl_visualizer.hpp, including the referenced area around line 1259. Compare its rendering behavior with the working addLine() loop and investigate why not every iterated correspondence becomes visible; done means all correspondences are shown through the correspondence APIs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- computer-graphics, computer-vision
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100