36 #include <visp3/vision/vpPose.h> 37 #include <visp3/core/vpPolygon.h> 38 #include <visp3/core/vpPixelMeterConversion.h> 39 #include <visp3/core/vpRobust.h> 42 vpHomogeneousMatrix compute3d3dTransformation(
const std::vector<vpPoint>& p,
const std::vector<vpPoint>& q) {
43 double N =
static_cast<double>(p.size());
47 for (
size_t i = 0; i < p.size(); i++) {
48 for (
unsigned int j = 0; j < 3; j++) {
49 p_bar[j] += p[i].oP[j];
50 q_bar[j] += q[i].oP[j];
54 for (
unsigned int j = 0; j < 3; j++) {
59 vpMatrix pc(static_cast<unsigned int>(p.size()), 3);
60 vpMatrix qc(static_cast<unsigned int>(q.size()), 3);
62 for (
unsigned int i = 0; i < static_cast<unsigned int>(p.size()); i++) {
63 for (
unsigned int j = 0; j < 3; j++) {
64 pc[i][j] = p[i].oP[j] - p_bar[j];
65 qc[i][j] = q[i].oP[j] - q_bar[j];
89 for (
unsigned int i = 0; i < 3; i++) {
90 for (
unsigned int j = 0; j < 3; j++) {
99 void estimatePlaneEquationSVD(
const std::vector<double> &point_cloud_face,
101 double &normalized_weights)
103 unsigned int max_iter = 10;
104 double prev_error = 1e3;
105 double error = 1e3 - 1;
106 unsigned int nPoints =
static_cast<unsigned int>(point_cloud_face.size() / 3);
116 plane_equation_estimated.
resize(4,
false);
117 for (
unsigned int iter = 0; iter < max_iter && std::fabs(error - prev_error) > 1e-6; iter++) {
123 double centroid_x = 0.0, centroid_y = 0.0, centroid_z = 0.0;
124 double total_w = 0.0;
126 for (
unsigned int i = 0; i < nPoints; i++) {
127 centroid_x += weights[i] * point_cloud_face[3 * i + 0];
128 centroid_y += weights[i] * point_cloud_face[3 * i + 1];
129 centroid_z += weights[i] * point_cloud_face[3 * i + 2];
130 total_w += weights[i];
133 centroid_x /= total_w;
134 centroid_y /= total_w;
135 centroid_z /= total_w;
138 for (
unsigned int i = 0; i < nPoints; i++) {
139 M[
static_cast<unsigned int>(i)][0] = weights[i] * (point_cloud_face[3 * i + 0] - centroid_x);
140 M[
static_cast<unsigned int>(i)][1] = weights[i] * (point_cloud_face[3 * i + 1] - centroid_y);
141 M[
static_cast<unsigned int>(i)][2] = weights[i] * (point_cloud_face[3 * i + 2] - centroid_z);
149 double smallestSv = W[0];
150 unsigned int indexSmallestSv = 0;
151 for (
unsigned int i = 1; i < W.
size(); i++) {
152 if (W[i] < smallestSv) {
158 normal = V.
getCol(indexSmallestSv);
161 double A = normal[0], B = normal[1], C = normal[2];
162 double D = -(A * centroid_x + B * centroid_y + C * centroid_z);
165 plane_equation_estimated[0] = A;
166 plane_equation_estimated[1] = B;
167 plane_equation_estimated[2] = C;
168 plane_equation_estimated[3] = D;
173 for (
unsigned int i = 0; i < nPoints; i++) {
174 residues[i] = std::fabs(A * point_cloud_face[3 * i] + B * point_cloud_face[3 * i + 1] +
175 C * point_cloud_face[3 * i + 2] + D) / sqrt(A * A + B * B + C * C);
176 error += weights[i] * residues[i];
185 centroid.
resize(3,
false);
186 double total_w = 0.0;
188 for (
unsigned int i = 0; i < nPoints; i++) {
189 centroid[0] += weights[i] * point_cloud_face[3 * i];
190 centroid[1] += weights[i] * point_cloud_face[3 * i + 1];
191 centroid[2] += weights[i] * point_cloud_face[3 * i + 2];
192 total_w += weights[i];
195 centroid[0] /= total_w;
196 centroid[1] /= total_w;
197 centroid[2] /= total_w;
200 double A = normal[0], B = normal[1], C = normal[2];
201 double D = -(A * centroid[0] + B * centroid[1] + C * centroid[2]);
204 plane_equation_estimated[0] = A;
205 plane_equation_estimated[1] = B;
206 plane_equation_estimated[2] = C;
207 plane_equation_estimated[3] = D;
209 normalized_weights = total_w / nPoints;
212 double computeZMethod1(
const vpColVector& plane_equation,
double x,
double y) {
213 return -plane_equation[3] / (plane_equation[0]*x + plane_equation[1]*y + plane_equation[2]);
219 for (
unsigned int i = 0; i < cMo.
getRows() && valid; i++) {
220 for (
unsigned int j = 0; j < cMo.
getCols() && valid; j++) {
255 if (corners.size() != point3d.size()) {
257 point3d.size(), corners.size()));
259 std::vector<vpPoint> pose_points;
260 if (confidence_index != NULL) {
261 *confidence_index = 0.0;
264 for (
size_t i = 0; i < point3d.size(); i ++) {
265 pose_points.push_back(point3d[i]);
270 unsigned int top =
static_cast<unsigned int>(std::max( 0, static_cast<int>(bb.
getTop()) ));
271 unsigned int bottom =
static_cast<unsigned int>(std::min( static_cast<int>(depthMap.
getHeight())-1, static_cast<int>(bb.
getBottom()) ));
272 unsigned int left =
static_cast<unsigned int>(std::max( 0, static_cast<int>(bb.
getLeft()) ));
273 unsigned int right =
static_cast<unsigned int>(std::min( static_cast<int>(depthMap.
getWidth())-1, static_cast<int>(bb.
getRight()) ));
275 std::vector<double> points_3d;
276 points_3d.reserve( (bottom-top)*(right-left) );
277 for (
unsigned int idx_i = top; idx_i < bottom; idx_i++) {
278 for (
unsigned int idx_j = left; idx_j < right; idx_j++) {
280 if (depthMap[idx_i][idx_j] > 0 && polygon.
isInside(imPt)) {
283 double Z = depthMap[idx_i][idx_j];
284 points_3d.push_back(x*Z);
285 points_3d.push_back(y*Z);
286 points_3d.push_back(Z);
291 unsigned int nb_points_3d =
static_cast<unsigned int>(points_3d.size() / 3);
293 if (nb_points_3d > 4) {
294 std::vector<vpPoint> p, q;
298 double normalized_weights = 0;
299 estimatePlaneEquationSVD(points_3d, plane_equation, centroid, normalized_weights);
301 for (
size_t j = 0; j < corners.size(); j++) {
305 double Z = computeZMethod1(plane_equation, x, y);
309 p.push_back(
vpPoint(x*Z, y*Z, Z));
311 pose_points[j].set_x(x);
312 pose_points[j].set_y(y);
315 for (
size_t i = 0; i < point3d.size(); i ++) {
316 q.push_back(point3d[i]);
319 cMo = compute3d3dTransformation(p, q);
321 if (validPose(cMo)) {
325 if (confidence_index != NULL) {
326 *confidence_index = std::min(1.0, normalized_weights * static_cast<double>(nb_points_3d) / polygon.
getArea());
void svd(vpColVector &w, vpMatrix &V)
Implementation of a matrix and operations on matrices.
bool computePose(vpPoseMethodType method, vpHomogeneousMatrix &cMo, bool(*func)(const vpHomogeneousMatrix &)=NULL)
double det(vpDetMethod method=LU_DECOMPOSITION) const
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Compute the weights according a residue vector and a PsiFunction.
Implementation of an homogeneous matrix and operations on such kind of matrices.
void addPoints(const std::vector< vpPoint > &lP)
error that can be emited by ViSP classes.
unsigned int getRows() const
static bool computePlanarObjectPoseFromRGBD(const vpImage< float > &depthMap, const std::vector< vpImagePoint > &corners, const vpCameraParameters &colorIntrinsics, const std::vector< vpPoint > &point3d, vpHomogeneousMatrix &cMo, double *confidence_index=NULL)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
unsigned int size() const
Return the number of elements of the 2D array.
vpRect getBoundingBox() const
Class that defines what is a point.
unsigned int getCols() const
Defines a generic 2D polygon.
bool isInside(const vpImagePoint &iP, const PointInPolygonMethod &method=PnPolyRayCasting) const
Class used for pose computation from N points (pose from point only). Some of the algorithms implemen...
Generic class defining intrinsic camera parameters.
void setThreshold(double noise_threshold)
vpColVector getCol(unsigned int j) const
static bool isNaN(double value)
void resize(unsigned int i, bool flagNullify=true)
unsigned int getHeight() const
Implementation of column vector and the associated operations.
Contains an M-Estimator and various influence function.
Defines a rectangle in the plane.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void resize(unsigned int n_data)
Resize containers for sort methods.
unsigned int getWidth() const