11 #include <pcl/features/crh.h>
12 #include <pcl/common/fft/kiss_fftr.h>
13 #include <pcl/common/transforms.h>
29 template<
typename Po
intT,
int nbins_>
38 operator() (std::pair<float, int>
const& a, std::pair<float, int>
const& b)
40 return a.first > b.first;
47 PointTPtr target_view_;
49 PointTPtr input_view_;
51 Eigen::Vector3f centroid_target_;
53 Eigen::Vector3f centroid_input_;
55 std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f> > transforms_;
63 float accept_threshold_;
70 computeTransformToZAxes (Eigen::Vector3f & centroid, Eigen::Affine3f & transform)
72 Eigen::Vector3f plane_normal;
73 plane_normal[0] = -centroid[0];
74 plane_normal[1] = -centroid[1];
75 plane_normal[2] = -centroid[2];
76 Eigen::Vector3f z_vector = Eigen::Vector3f::UnitZ ();
77 plane_normal.normalize ();
78 Eigen::Vector3f axis = plane_normal.cross (z_vector);
79 double rotation = -asin (axis.norm ());
81 transform = Eigen::Affine3f (Eigen::AngleAxisf (
static_cast<float>(rotation), axis));
91 computeRollTransform (Eigen::Vector3f & centroidInput, Eigen::Vector3f & centroidResult,
double roll_angle, Eigen::Affine3f & final_trans)
93 Eigen::Affine3f transformInputToZ;
94 computeTransformToZAxes (centroidInput, transformInputToZ);
96 transformInputToZ = transformInputToZ.inverse ();
97 Eigen::Affine3f transformRoll (Eigen::AngleAxisf (-
static_cast<float>(roll_angle *
M_PI / 180), Eigen::Vector3f::UnitZ ()));
98 Eigen::Affine3f transformDBResultToZ;
99 computeTransformToZAxes (centroidResult, transformDBResultToZ);
101 final_trans = transformInputToZ * transformRoll * transformDBResultToZ;
109 accept_threshold_ = 0.8f;
115 void getTransforms(std::vector<Eigen::Matrix4f, Eigen::aligned_allocator<Eigen::Matrix4f> > & transforms) {
116 transforms = transforms_;
126 target_view_ = target_view;
127 input_view_ = input_view;
137 centroid_target_ = c2;
138 centroid_input_ = c1;
151 std::vector<float> peaks;
152 computeRollAngle (input_ftt, target_ftt, peaks);
156 for (
const float &peak : peaks)
158 Eigen::Affine3f rollToRot;
159 computeRollTransform (centroid_input_, centroid_target_, peak, rollToRot);
161 Eigen::Matrix4f rollHomMatrix = Eigen::Matrix4f ();
162 rollHomMatrix.setIdentity (4, 4);
163 rollHomMatrix = rollToRot.matrix ();
165 Eigen::Matrix4f translation2;
166 translation2.setIdentity (4, 4);
167 Eigen::Vector3f centr = rollToRot * centroid_target_;
168 translation2 (0, 3) = centroid_input_[0] - centr[0];
169 translation2 (1, 3) = centroid_input_[1] - centr[1];
170 translation2 (2, 3) = centroid_input_[2] - centr[2];
172 Eigen::Matrix4f resultHom (translation2 * rollHomMatrix);
173 transforms_.push_back(resultHom.inverse());
185 std::vector<float> & peaks)
190 for (
int i = 2; i < (nbins_); i += 2)
191 input_ftt_negate[0].histogram[i] = -input_ftt_negate[0].histogram[i];
193 int nr_bins_after_padding = 180;
194 int peak_distance = 5;
195 int cutoff = nbins_ - 1;
198 for (
int i = 0; i < nr_bins_after_padding; i++)
199 multAB[i].r = multAB[i].i = 0.f;
202 multAB[k].
r = input_ftt_negate[0].histogram[0] * target_ftt[0].histogram[0];
206 for (
int i = 1; i < cutoff; i += 2, k++)
208 a = input_ftt_negate[0].histogram[i];
209 b = input_ftt_negate[0].histogram[i + 1];
210 c = target_ftt[0].histogram[i];
211 d = target_ftt[0].histogram[i + 1];
212 multAB[k].
r = a * c - b * d;
213 multAB[k].
i = b * c + a * d;
215 float tmp = std::sqrt (multAB[k].r * multAB[k].r + multAB[k].i * multAB[k].i);
221 multAB[nbins_ - 1].
r = input_ftt_negate[0].histogram[nbins_ - 1] * target_ftt[0].histogram[nbins_ - 1];
223 kiss_fft_cfg mycfg = kiss_fft_alloc (nr_bins_after_padding, 1,
nullptr,
nullptr);
225 kiss_fft (mycfg, multAB, invAB);
227 std::vector < std::pair<float, int> > scored_peaks (nr_bins_after_padding);
228 for (
int i = 0; i < nr_bins_after_padding; i++)
229 scored_peaks[i] = std::make_pair (invAB[i].r, i);
231 std::sort (scored_peaks.begin (), scored_peaks.end (), peaks_ordering ());
233 std::vector<int> peaks_indices;
234 std::vector<float> peaks_values;
237 float quantile = quantile_;
238 int max_inserted= max_peaks_;
242 for (
int i = 0; (i < static_cast<int> (quantile *
static_cast<float> (nr_bins_after_padding))) && !stop; i++)
244 if (scored_peaks[i].first >= scored_peaks[0].first * accept_threshold_)
248 for (
const int &peaks_index : peaks_indices)
250 if ((std::abs (peaks_index - scored_peaks[i].second) <= peak_distance) ||
251 (std::abs (peaks_index - (scored_peaks[i].second - nr_bins_after_padding)) <= peak_distance))
260 peaks_indices.push_back (scored_peaks[i].second);
261 peaks_values.push_back (scored_peaks[i].first);
262 peaks.push_back (
static_cast<float> (scored_peaks[i].second * (360 / nr_bins_after_padding)));
264 if(inserted >= max_inserted)
CRHAlignment uses two Camera Roll Histograms (CRH) to find the roll rotation that aligns both views.
void setInputAndTargetCentroids(Eigen::Vector3f &c1, Eigen::Vector3f &c2)
sets model and input centroids
void align(pcl::PointCloud< pcl::Histogram< nbins_ > > &input_ftt, pcl::PointCloud< pcl::Histogram< nbins_ > > &target_ftt)
Computes the transformation aligning model to input.
void computeRollAngle(pcl::PointCloud< pcl::Histogram< nbins_ > > &input_ftt, pcl::PointCloud< pcl::Histogram< nbins_ > > &target_ftt, std::vector< float > &peaks)
Computes the roll angle that aligns input to model.
CRHAlignment()
Constructor.
void setInputAndTargetView(PointTPtr &input_view, PointTPtr &target_view)
sets model and input views
void getTransforms(std::vector< Eigen::Matrix4f, Eigen::aligned_allocator< Eigen::Matrix4f > > &transforms)
returns the computed transformations
PointCloud represents the base class in PCL for storing collections of 3D points.
shared_ptr< PointCloud< PointT > > Ptr
Define standard C methods and C++ classes that are common to all methods.
A point structure representing an N-D histogram.