40 #ifndef PCL_FEATURES_IMPL_INTENSITY_GRADIENT_H_
41 #define PCL_FEATURES_IMPL_INTENSITY_GRADIENT_H_
46 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename IntensitySelectorT>
void
49 const Eigen::Vector3f &point,
float mean_intensity,
const Eigen::Vector3f &normal, Eigen::Vector3f &gradient)
51 if (indices.size () < 3)
53 gradient[0] = gradient[1] = gradient[2] = std::numeric_limits<float>::quiet_NaN ();
57 Eigen::Matrix3f A = Eigen::Matrix3f::Zero ();
58 Eigen::Vector3f b = Eigen::Vector3f::Zero ();
60 for (
size_t i_point = 0; i_point < indices.size (); ++i_point)
62 PointInT p = cloud.points[indices[i_point]];
72 intensity_.demean (p, mean_intensity);
74 A (0, 0) += p.x * p.x;
75 A (0, 1) += p.x * p.y;
76 A (0, 2) += p.x * p.z;
78 A (1, 1) += p.y * p.y;
79 A (1, 2) += p.y * p.z;
81 A (2, 2) += p.z * p.z;
83 b[0] += p.x * intensity_ (p);
84 b[1] += p.y * intensity_ (p);
85 b[2] += p.z * intensity_ (p);
93 Eigen::Vector3f x = A.colPivHouseholderQr ().solve (b);
138 gradient = (Eigen::Matrix3f::Identity () - normal*normal.transpose ()) * x;
142 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename IntensitySelectorT>
void
147 std::vector<int> nn_indices (k_);
148 std::vector<float> nn_dists (k_);
149 output.is_dense =
true;
152 if (surface_->is_dense)
154 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
155 #pragma omp parallel for shared (output) private (nn_indices, nn_dists) num_threads(threads_)
158 for (
int idx = 0; idx < static_cast<int> (indices_->size ()); ++idx)
160 PointOutT &p_out = output.points[idx];
162 if (!this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists))
164 p_out.gradient[0] = p_out.gradient[1] = p_out.gradient[2] = std::numeric_limits<float>::quiet_NaN ();
165 output.is_dense =
false;
169 Eigen::Vector3f centroid;
170 float mean_intensity = 0;
173 for (
size_t i = 0; i < nn_indices.size (); ++i)
175 centroid += surface_->points[nn_indices[i]].getVector3fMap ();
176 mean_intensity += intensity_ (surface_->points[nn_indices[i]]);
178 centroid /=
static_cast<float> (nn_indices.size ());
179 mean_intensity /=
static_cast<float> (nn_indices.size ());
181 Eigen::Vector3f normal = Eigen::Vector3f::Map (normals_->points[(*indices_) [idx]].normal);
182 Eigen::Vector3f gradient;
183 computePointIntensityGradient (*surface_, nn_indices, centroid, mean_intensity, normal, gradient);
185 p_out.gradient[0] = gradient[0];
186 p_out.gradient[1] = gradient[1];
187 p_out.gradient[2] = gradient[2];
192 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
193 #pragma omp parallel for shared (output) private (nn_indices, nn_dists) num_threads(threads_)
196 for (
int idx = 0; idx < static_cast<int> (indices_->size ()); ++idx)
198 PointOutT &p_out = output.points[idx];
199 if (!
isFinite ((*surface_) [(*indices_)[idx]]) ||
200 !this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists))
202 p_out.gradient[0] = p_out.gradient[1] = p_out.gradient[2] = std::numeric_limits<float>::quiet_NaN ();
203 output.is_dense =
false;
206 Eigen::Vector3f centroid;
207 float mean_intensity = 0;
211 for (
size_t i = 0; i < nn_indices.size (); ++i)
214 if (!
isFinite ((*surface_) [nn_indices[i]]))
217 centroid += surface_->points [nn_indices[i]].getVector3fMap ();
218 mean_intensity += intensity_ (surface_->points [nn_indices[i]]);
221 centroid /=
static_cast<float> (cp);
222 mean_intensity /=
static_cast<float> (cp);
223 Eigen::Vector3f normal = Eigen::Vector3f::Map (normals_->points[(*indices_) [idx]].normal);
224 Eigen::Vector3f gradient;
225 computePointIntensityGradient (*surface_, nn_indices, centroid, mean_intensity, normal, gradient);
227 p_out.gradient[0] = gradient[0];
228 p_out.gradient[1] = gradient[1];
229 p_out.gradient[2] = gradient[2];
235 template <
typename Po
intInT,
typename Po
intNT>
void
239 output.
points.resize (indices_->size (), 3);
243 std::vector<int> nn_indices (k_);
244 std::vector<float> nn_dists (k_);
248 for (
size_t idx = 0; idx < indices_->size (); ++idx)
250 if (this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists) == 0)
252 output.
points.row (idx).setConstant (std::numeric_limits<float>::quiet_NaN ());
257 Eigen::Vector4f centroid;
260 float mean_intensity = 0;
261 unsigned valid_neighbor_count = 0;
262 for (
size_t nIdx = 0; nIdx < nn_indices.size (); ++nIdx)
264 const PointInT& p = (*surface_)[nn_indices[nIdx]];
268 mean_intensity += p.intensity;
269 ++valid_neighbor_count;
272 mean_intensity /=
static_cast<float> (valid_neighbor_count);
274 Eigen::Vector3f normal = Eigen::Vector3f::Map (normals_->points[idx].normal);
275 Eigen::Vector3f gradient;
276 this->computePointIntensityGradient (*surface_, nn_indices, centroid.head<3> (), mean_intensity, normal, gradient);
278 output.
points (idx, 0) = gradient[0];
279 output.
points (idx, 1) = gradient[1];
280 output.
points (idx, 2) = gradient[2];
285 #define PCL_INSTANTIATE_IntensityGradientEstimation(InT,NT,OutT) template class PCL_EXPORTS pcl::IntensityGradientEstimation<InT,NT,OutT>;
287 #endif // PCL_FEATURES_IMPL_INTENSITY_GRADIENT_H_