models.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2014, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 //
00028 // *****************************************************************************
00029 
00030 #include <swri_opencv_util/models.h>
00031 
00032 #include <opencv2/imgproc/imgproc.hpp>
00033 
00034 namespace swri_opencv_util
00035 {
00036 
00037   int32_t Correspondence2d::GetInlierCount(const M& model, double max_error)
00038   {
00039     CalculateNorms(model, norms__);
00040 
00041     cv::compare(norms__, cv::Scalar(max_error * max_error), thresholded__, cv::CMP_LT);
00042 
00043     return cv::countNonZero(thresholded__);
00044   }
00045 
00046   void Correspondence2d::GetInliers(const M& model, double max_error, std::vector<uint32_t>& indices)
00047   {
00048     CalculateNorms(model, norms__);
00049 
00050     indices.clear();
00051     indices.reserve(norms__.rows);
00052     double threshold = max_error * max_error;
00053     for (int i = 0; i < norms__.rows; i++)
00054     {
00055       if (norms__.at<float>(i) < threshold)
00056       {
00057         indices.push_back(i);
00058       }
00059     }
00060   }
00061 
00062   void Correspondence2d::CalculateNorms(const M& model, cv::Mat& norms)
00063   {
00064     cv::Mat src = data_(cv::Rect(0, 0, 2, data_.rows)).reshape(2);
00065     cv::transform(src, predicted__, model);
00066     cv::Mat measured = data_(cv::Rect(2, 0, 2, data_.rows));
00067     cv::subtract(predicted__.reshape(1), measured, delta__);
00068     cv::multiply(delta__, delta__, delta_squared__);
00069     cv::add(
00070       delta_squared__(cv::Rect(0, 0, 1, delta__.rows)),
00071       delta_squared__(cv::Rect(1, 0, 1, delta__.rows)),
00072       norms);
00073   }
00074 
00075   bool Homography::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00076   {
00077     if (indices.size() != MIN_SIZE)
00078     {
00079       return false;
00080     }
00081 
00082     cv::Mat src(MIN_SIZE, 1, CV_32FC2);
00083     cv::Mat dst(MIN_SIZE, 1, CV_32FC2);
00084 
00085     for (int32_t i = 0; i < MIN_SIZE; i++)
00086     {
00087       const float* sample = data_.ptr<float>(indices[i]);
00088       src.at<cv::Vec2f>(i, 0) = cv::Vec2f(sample[0], sample[1]);
00089       dst.at<cv::Vec2f>(i, 0) = cv::Vec2f(sample[2], sample[3]);
00090     }
00091 
00092     model = cv::getPerspectiveTransform(src, dst);
00093 
00094     // Test input points for if they all match the generated model.
00095     cv::Mat predicted;
00096     cv::perspectiveTransform(src, predicted, model);
00097     cv::Mat delta, delta_squared, norms;
00098     cv::subtract(predicted.reshape(1), dst.reshape(1), delta);
00099     cv::multiply(delta, delta, delta_squared);
00100     cv::add(
00101       delta_squared(cv::Rect(0, 0, 1, delta.rows)),
00102       delta_squared(cv::Rect(1, 0, 1, delta.rows)),
00103       norms);
00104 
00105     double min, max;
00106     cv::minMaxLoc(norms, &min, &max);
00107 
00108     return max < max_error * max_error;
00109   }
00110 
00111   void Homography::CalculateNorms(const M& model, cv::Mat& norms)
00112   {
00113     cv::Mat src = data_(cv::Rect(0, 0, 2, data_.rows)).reshape(2);
00114     cv::perspectiveTransform(src, predicted__, model);
00115     cv::Mat measured = data_(cv::Rect(2, 0, 2, data_.rows));
00116     cv::subtract(predicted__.reshape(1), measured, delta__);
00117     cv::multiply(delta__, delta__, delta_squared__);
00118     cv::add(
00119       delta_squared__(cv::Rect(0, 0, 1, delta__.rows)),
00120       delta_squared__(cv::Rect(1, 0, 1, delta__.rows)),
00121       norms);
00122   }
00123 
00124   bool AffineTransform2d::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00125   {
00126     if (indices.size() != MIN_SIZE)
00127     {
00128       return false;
00129     }
00130 
00131     cv::Mat src(MIN_SIZE, 1, CV_32FC2);
00132     cv::Mat dst(MIN_SIZE, 1, CV_32FC2);
00133 
00134     for (int32_t i = 0; i < MIN_SIZE; i++)
00135     {
00136       const float* sample = data_.ptr<float>(indices[i]);
00137       src.at<cv::Vec2f>(i, 0) = cv::Vec2f(sample[0], sample[1]);
00138       dst.at<cv::Vec2f>(i, 0) = cv::Vec2f(sample[2], sample[3]);
00139     }
00140 
00141     model = cv::getAffineTransform(src, dst);
00142 
00143     // Test input points for if they all match the generated model.
00144     cv::Mat predicted;
00145     cv::transform(src, predicted, model);
00146     cv::Mat delta, delta_squared, norms;
00147     cv::subtract(predicted.reshape(1), dst.reshape(1), delta);
00148     cv::multiply(delta, delta, delta_squared);
00149     cv::add(
00150       delta_squared(cv::Rect(0, 0, 1, delta.rows)),
00151       delta_squared(cv::Rect(1, 0, 1, delta.rows)),
00152       norms);
00153 
00154     double min, max;
00155     cv::minMaxLoc(norms, &min, &max);
00156 
00157     return max < max_error * max_error;
00158   }
00159 
00160   bool RigidTransform2d::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00161   {
00162     if (indices.size() != MIN_SIZE)
00163     {
00164       return false;
00165     }
00166 
00167     cv::Point2f src[MIN_SIZE];
00168     cv::Point2f dst[MIN_SIZE];
00169 
00170     for (int32_t i = 0; i < MIN_SIZE; i++)
00171     {
00172       const float* sample = data_.ptr<float>(indices[i]);
00173       src[i].x = sample[0];
00174       src[i].y = sample[1];
00175       dst[i].x = sample[2];
00176       dst[i].y = sample[3];
00177     }
00178 
00179     double len_src = cv::norm(src[1] - src[0]);
00180     double len_dst = cv::norm(dst[1] - dst[0]);
00181     if (std::fabs(len_src - len_dst) >= max_error)
00182     {
00183       return false;
00184     }
00185 
00186     // Construct a x-axis for both sets.
00187     cv::Point2f src_x = (src[1] - src[0]) * (1.0 / len_src);
00188     cv::Point2f dst_x = (dst[1] - dst[0]) * (1.0 / len_dst);
00189 
00190     // Construct a y-axis for both sets.
00191     cv::Point2f src_y(src_x.y, -src_x.x);
00192     src_y *= 1.0 / cv::norm(src_y);
00193 
00194     cv::Point2f dst_y(dst_x.y, -dst_x.x);
00195     dst_y *= 1.0 / cv::norm(dst_y);
00196 
00197     // Build rotation matrices for both sets.
00198     cv::Mat src_r(2, 2, CV_32F);
00199     src_r.at<float>(0, 0) = src_x.x;
00200     src_r.at<float>(1, 0) = src_x.y;
00201     src_r.at<float>(0, 1) = src_y.x;
00202     src_r.at<float>(1, 1) = src_y.y;
00203 
00204     cv::Mat dst_r(2, 2, CV_32F);
00205     dst_r.at<float>(0, 0) = dst_x.x;
00206     dst_r.at<float>(1, 0) = dst_x.y;
00207     dst_r.at<float>(0, 1) = dst_y.x;
00208     dst_r.at<float>(1, 1) = dst_y.y;
00209 
00210     // Solve for the rotation between src and dst
00211     //    R R_src = R_dst
00212     //    R = R_dst R_src^T
00213     cv::Mat rotation = dst_r * src_r.t();
00214 
00215     // Calculate the translation between src (rotated) and dst.
00216     cv::Mat src0_rotated(2, 1, CV_32F);
00217     src0_rotated.at<float>(0, 0) = src[0].x;
00218     src0_rotated.at<float>(1, 0) = src[0].y;
00219     src0_rotated = rotation * src0_rotated;
00220     float t_x = dst[0].x - src0_rotated.at<float>(0, 0);
00221     float t_y = dst[0].y - src0_rotated.at<float>(1, 0);
00222 
00223     model.create(2, 3, CV_32F);
00224     model.at<float>(0, 0) = rotation.at<float>(0, 0);
00225     model.at<float>(0, 1) = rotation.at<float>(0, 1);
00226     model.at<float>(1, 0) = rotation.at<float>(1, 0);
00227     model.at<float>(1, 1) = rotation.at<float>(1, 1);
00228     model.at<float>(0, 2) = t_x;
00229     model.at<float>(1, 2) = t_y;
00230 
00231     return true;
00232   }
00233 
00234   bool Translation2d::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00235   {
00236     if (indices.size() != MIN_SIZE)
00237     {
00238       return false;
00239     }
00240 
00241     cv::Point2f src;
00242     cv::Point2f dst;
00243 
00244     const float* sample = data_.ptr<float>(indices[0]);
00245     src.x = sample[0];
00246     src.y = sample[1];
00247     dst.x = sample[2];
00248     dst.y = sample[3];
00249 
00250     // Calculate the translation between src (rotated) and dst.
00251     float t_x = dst.x - src.x;
00252     float t_y = dst.y - src.y;
00253 
00254     model.create(2, 3, CV_32F);
00255     model.at<float>(0, 0) = 1.0f;
00256     model.at<float>(0, 1) = 0.0f;
00257     model.at<float>(1, 0) = 0.0f;
00258     model.at<float>(1, 1) = 1.0f;
00259     model.at<float>(0, 2) = t_x;
00260     model.at<float>(1, 2) = t_y;
00261 
00262     return true;
00263   }
00264 
00265   bool Valid2dPointCorrespondences(
00266     const cv::Mat& points1,
00267     const cv::Mat& points2)
00268   {
00269     if (points1.type() != points2.type())
00270     {
00271       return false;
00272     }
00273 
00274     if (points1.type() != CV_32FC2)
00275     {
00276       return false;
00277     }
00278 
00279     if (points1.cols != points2.cols  || points1.rows  != points2.rows)
00280     {
00281       return false;
00282     }
00283 
00284     if (points1.cols != 1 && points1.rows != 1)
00285     {
00286       return false;
00287     }
00288 
00289     return true;
00290   }
00291 
00292   bool ZipCorrespondences(
00293     const cv::Mat& points1,
00294     const cv::Mat& points2,
00295     cv::Mat& correspondeces)
00296   {
00297     if (!Valid2dPointCorrespondences(points1, points2))
00298     {
00299       return false;
00300     }
00301 
00302     size_t num_points = points1.cols;
00303     bool row_order = false;
00304     if (points1.rows > 1)
00305     {
00306       row_order = true;
00307       num_points = points1.rows;
00308     }
00309 
00310     // Put data into the correct format.
00311     if (row_order)
00312     {
00313       cv::hconcat(points1.reshape(1), points2.reshape(1), correspondeces);
00314     }
00315     else
00316     {
00317       cv::hconcat(
00318         points1.reshape(0, num_points).reshape(1),
00319         points2.reshape(0, num_points).reshape(1),
00320         correspondeces);
00321     }
00322 
00323     return true;
00324   }
00325 
00326 
00327   bool PerpendicularPlaneWithPointFit::GetModel(const std::vector<int32_t>& indices, M& model, 
00328                                                 double max_error) const
00329   {
00330     if (indices.size() != MIN_SIZE)
00331     {
00332       return false;
00333     }
00334 
00335     // Check if points are collinear.
00336 
00337     cv::Mat points = data_.reshape(3);
00338 
00339     cv::Vec3f p1 = points.at<cv::Vec3f>(indices[0], 0);
00340     cv::Vec3f p2 = points.at<cv::Vec3f>(indices[1], 0);
00341     cv::Vec3f p3 = point_;
00342 
00343     cv::Point3f v12 = p2 - p1;
00344     cv::Point3f v13 = p3 - p1;
00345     float d12 = cv::norm(v12);
00346     float d13 = cv::norm(v13);
00347     float d = std::fabs(d12 * d13);
00348     if (d == 0)
00349     {
00350       return false;
00351     }
00352 
00353     float angle = std::acos(v12.dot(v13) / d);
00354     if (angle < min_angle_ || angle + min_angle_ > M_PI)
00355     {
00356       return false;
00357     }
00358 
00359     // Calculate model.
00360 
00361     cv::Vec3f normal = v12.cross(v13);
00362     normal = normal / cv::norm(normal);
00363 
00364     if (std::acos(normal.dot(perp_axis_)) > max_axis_angle_)
00365     {
00366       return false;
00367     }
00368 
00369     model.x = p1[0];
00370     model.y = p1[1];
00371     model.z = p1[2];
00372     model.i = normal[0];
00373     model.j = normal[1];
00374     model.k = normal[2];
00375 
00376     return true;
00377   }
00378 
00379   bool PlaneFit::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00380   {
00381     if (indices.size() != MIN_SIZE)
00382     {
00383       return false;
00384     }
00385 
00386     // Check if points are collinear.
00387 
00388     cv::Mat points = data_.reshape(3);
00389 
00390     cv::Vec3f p1 = points.at<cv::Vec3f>(indices[0], 0);
00391     cv::Vec3f p2 = points.at<cv::Vec3f>(indices[1], 0);
00392     cv::Vec3f p3 = points.at<cv::Vec3f>(indices[2], 0);
00393 
00394     cv::Point3f v12 = p2 - p1;
00395     cv::Point3f v13 = p3 - p1;
00396     float d12 = cv::norm(v12);
00397     float d13 = cv::norm(v13);
00398     float d = std::fabs(d12 * d13);
00399     if (d == 0)
00400     {
00401       return false;
00402     }
00403 
00404     float angle = std::acos(v12.dot(v13) / d);
00405     if (angle < min_angle_ || angle + min_angle_ > M_PI)
00406     {
00407       return false;
00408     }
00409 
00410     // Calculate model.
00411 
00412     cv::Vec3f normal = v12.cross(v13);
00413     normal = normal / cv::norm(normal);
00414 
00415     model.x = p1[0];
00416     model.y = p1[1];
00417     model.z = p1[2];
00418     model.i = normal[0];
00419     model.j = normal[1];
00420     model.k = normal[2];
00421 
00422     return true;
00423   }
00424 
00425   void PlaneFit::CalculateNorms(const M& model, cv::Mat& norms)
00426   {
00427     // Subtract the origin point of the plane from each data point
00428     cv::Mat single_column = data_.reshape(3);
00429     cv::subtract(single_column, cv::Scalar(model.x, model.y, model.z), delta__);
00430 
00431     // Calculate the dot product of each adjusted data point with the normal
00432     // of the plane.
00433     cv::Mat split_columns = delta__.reshape(1);
00434     cv::Mat x = split_columns(cv::Rect(0, 0, 1, split_columns.rows));
00435     cv::Mat y = split_columns(cv::Rect(1, 0, 1, split_columns.rows));
00436     cv::Mat z = split_columns(cv::Rect(2, 0, 1, split_columns.rows));
00437     x = x * model.i;
00438     y = y * model.j;
00439     z = z * model.k;
00440     cv::add(x, y, norms);
00441     cv::add(norms, z, norms);
00442     norms = cv::abs(norms);
00443   }
00444 
00445   bool LineFit3d::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00446   {
00447     if (indices.size() != MIN_SIZE)
00448     {
00449       return false;
00450     }
00451 
00452     cv::Mat points = data_.reshape(3);
00453 
00454     cv::Point3f p1(points.at<cv::Vec3f>(indices[0], 0));
00455     cv::Point3f p2(points.at<cv::Vec3f>(indices[1], 0));
00456 
00457     cv::Point3f v12 = p2 - p1;
00458     v12 = cv::Vec3f(v12) / cv::norm(v12);
00459 
00460     model.x = p1.x;
00461     model.y = p1.y;
00462     model.z = p1.z;
00463     model.i = v12.x;
00464     model.j = v12.y;
00465     model.k = v12.z;
00466 
00467     return true;
00468   }
00469 
00470   void LineFit3d::CalculateNorms(const M& model, cv::Mat& norms)
00471   {
00472     // d = ||(x0 - p) - ((x0 - p) . n)n||
00473 
00474     cv::Scalar x0(model.x, model.y, model.z);
00475     cv::Scalar n(model.i, model.j, model.k);
00476     cv::Mat p = data_.reshape(3);
00477 
00478     if (temp1__.size != p.size)
00479     {
00480       temp1__ = cv::Mat(p.rows, p.cols, p.type());
00481     }
00482     temp1__.setTo(n);
00483     cv::Mat n_columns = temp1__.reshape(1);
00484     cv::Mat n_x = n_columns(cv::Rect(0, 0, 1, n_columns.rows));
00485     cv::Mat n_y = n_columns(cv::Rect(1, 0, 1, n_columns.rows));
00486     cv::Mat n_z = n_columns(cv::Rect(2, 0, 1, n_columns.rows));
00487 
00488     // (x0 - p)
00489     cv::subtract(p, x0, x0_p__);    
00490 
00491     // (x0 - p) . n
00492     cv::multiply(x0_p__, temp1__, temp2__);
00493     cv::reduce(temp2__.reshape(1), x0_p_dot_n__, 1, CV_REDUCE_SUM);
00494 
00495     // ((x0 - p) . n)n
00496     cv::multiply(n_x, x0_p_dot_n__, n_x);
00497     cv::multiply(n_y, x0_p_dot_n__, n_y);
00498     cv::multiply(n_z, x0_p_dot_n__, n_z);
00499 
00500     // (x0 - p) - ((x0 - p) . n)n
00501     cv::subtract(x0_p__, temp1__, temp1__);
00502 
00503     // d = ||(x0 - p) - ((x0 - p) . n)n||
00504     cv::multiply(n_x, n_x, n_x);
00505     cv::multiply(n_y, n_y, n_y);
00506     cv::multiply(n_z, n_z, n_z);
00507     cv::reduce(temp1__.reshape(1), norms, 1, CV_REDUCE_SUM);
00508     cv::sqrt(norms, norms);
00509   }
00510 
00511   bool OrthoLineFit3d::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00512   {
00513     if (indices.size() != MIN_SIZE)
00514     {
00515       return false;
00516     }
00517 
00518     cv::Mat points = data_.reshape(3);
00519 
00520     cv::Point3f p1(points.at<cv::Vec3f>(indices[0], 0));
00521     cv::Point3f p2(points.at<cv::Vec3f>(indices[1], 0));
00522 
00523     cv::Point3f v12 = p2 - p1;
00524     v12 = cv::Vec3f(v12) / cv::norm(v12);
00525 
00526     // Check if orthogonal
00527     cv::Point3f ortho(ortho_.i, ortho_.j, ortho_.k);
00528     ortho = cv::Vec3f(ortho) / cv::norm(ortho);
00529 
00530     float angle = std::acos(v12.dot(ortho));
00531     float error = std::fabs(M_PI * 0.5 - angle);
00532     if (error > angle_tolerance_)
00533     {
00534       return false;
00535     }
00536 
00537     model.x = p1.x;
00538     model.y = p1.y;
00539     model.z = p1.z;
00540     model.i = v12.x;
00541     model.j = v12.y;
00542     model.k = v12.z;
00543 
00544     return true;
00545   }
00546 
00547   bool CrossFit3d::GetModel(const std::vector<int32_t>& indices, M& model, double max_error) const
00548   {
00549     if (indices.size() != MIN_SIZE)
00550     {
00551       return false;
00552     }
00553 
00554     // Check if points are collinear.
00555 
00556     cv::Mat points = data_.reshape(3);
00557 
00558     cv::Point3f p1(points.at<cv::Vec3f>(indices[0], 0));
00559     cv::Point3f p2(points.at<cv::Vec3f>(indices[1], 0));
00560     cv::Point3f p3(points.at<cv::Vec3f>(indices[2], 0));
00561 
00562     cv::Point3f v12 = p2 - p1;
00563     cv::Point3f v13 = p3 - p1;
00564     float d12 = cv::norm(v12);
00565     float d13 = cv::norm(v13);
00566     float d = std::fabs(d12 * d13);
00567     if (d == 0)
00568     {
00569       return false;
00570     }
00571 
00572     float angle = std::acos(v12.dot(v13) / d);
00573     if (angle < min_angle_ || angle + min_angle_ > M_PI)
00574     {
00575       return false;
00576     }
00577 
00578     // Calculate model.
00579 
00580     // Orthogonally project 3rd point onto first line to
00581     // get line through 3rd point orthogonal to the first
00582     // line.
00583     cv::Point3f p4 = p1 + (v13.dot(v12) / v12.dot(v12)) * v12;
00584     cv::Point3f v34 = p4 - p3;
00585 
00586     // Get unit vector of the lines.
00587     v12 = cv::Vec3f(v12) / cv::norm(v12);
00588     v34 = cv::Vec3f(v34) / cv::norm(v34);
00589 
00590     model.x = p4.x;
00591     model.y = p4.y;
00592     model.z = p4.z;
00593     model.i1 = v12.x;
00594     model.j1 = v12.y;
00595     model.k1 = v12.z;
00596     model.i2 = v34.x;
00597     model.j2 = v34.y;
00598     model.k2 = v34.z;
00599 
00600     return true;
00601   }
00602 
00603   void CrossFit3d::CalculateNorms(const M& model, cv::Mat& norms)
00604   {
00606     // Line 1
00608 
00609     // d = ||(x0 - p) - ((x0 - p) . n)n||
00610 
00611     cv::Scalar x0(model.x, model.y, model.z);
00612     cv::Scalar n(model.i1, model.j1, model.k1);
00613     cv::Mat p = data_.reshape(3);
00614 
00615     if (temp1__.size != p.size)
00616     {
00617       temp1__ = cv::Mat(p.rows, p.cols, p.type());
00618     }
00619     temp1__.setTo(n);
00620     cv::Mat n_columns = temp1__.reshape(1);
00621     cv::Mat n_x = n_columns(cv::Rect(0, 0, 1, n_columns.rows));
00622     cv::Mat n_y = n_columns(cv::Rect(1, 0, 1, n_columns.rows));
00623     cv::Mat n_z = n_columns(cv::Rect(2, 0, 1, n_columns.rows));
00624 
00625     // (x0 - p)
00626     cv::subtract(p, x0, x0_p__);    
00627 
00628     // (x0 - p) . n
00629     cv::multiply(x0_p__, temp1__, temp2__);
00630     cv::reduce(temp2__.reshape(1), x0_p_dot_n__, 1, CV_REDUCE_SUM);
00631 
00632     // ((x0 - p) . n)n
00633     cv::multiply(n_x, x0_p_dot_n__, n_x);
00634     cv::multiply(n_y, x0_p_dot_n__, n_y);
00635     cv::multiply(n_z, x0_p_dot_n__, n_z);
00636 
00637     // (x0 - p) - ((x0 - p) . n)n
00638     cv::subtract(x0_p__, temp1__, temp1__);
00639 
00640     // d = ||(x0 - p) - ((x0 - p) . n)n||
00641     cv::multiply(n_x, n_x, n_x);
00642     cv::multiply(n_y, n_y, n_y);
00643     cv::multiply(n_z, n_z, n_z);
00644     cv::reduce(temp1__.reshape(1), temp3__, 1, CV_REDUCE_SUM);
00645     cv::sqrt(temp3__, temp3__);
00646 
00647 
00649     // Line 2
00651 
00652     // d = ||(x0 - p) - ((x0 - p) . n)n||
00653 
00654     n = cv::Scalar(model.i2, model.j2, model.k2);
00655     temp1__.setTo(n);
00656 
00657     // (x0 - p)
00658     cv::subtract(p, x0, x0_p__);    
00659 
00660     // (x0 - p) . n
00661     cv::multiply(x0_p__, temp1__, temp2__);
00662     cv::reduce(temp2__.reshape(1), x0_p_dot_n__, 1, CV_REDUCE_SUM);
00663 
00664     // ((x0 - p) . n)n
00665     cv::multiply(n_x, x0_p_dot_n__, n_x);
00666     cv::multiply(n_y, x0_p_dot_n__, n_y);
00667     cv::multiply(n_z, x0_p_dot_n__, n_z);
00668 
00669     // (x0 - p) - ((x0 - p) . n)n
00670     cv::subtract(x0_p__, temp1__, temp1__);
00671 
00672     // d = ||(x0 - p) - ((x0 - p) . n)n||
00673     cv::multiply(n_x, n_x, n_x);
00674     cv::multiply(n_y, n_y, n_y);
00675     cv::multiply(n_z, n_z, n_z);
00676     cv::reduce(temp1__.reshape(1), norms, 1, CV_REDUCE_SUM);
00677     cv::sqrt(norms, norms);
00678 
00679     // Use the minimum distance to either line.
00680     norms = cv::min(norms, temp3__);
00681   }
00682 }


swri_opencv_util
Author(s): Marc Alban
autogenerated on Tue Oct 3 2017 03:19:24