00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <swri_image_util/geometry_util.h>
00031
00032 #include <cmath>
00033 #include <limits>
00034 #include <vector>
00035
00036 #include <opencv2/imgproc/imgproc.hpp>
00037
00038 #include <Eigen/Dense>
00039 #include <Eigen/SVD>
00040
00041 #include <swri_geometry_util/intersection.h>
00042 #include <swri_math_util/constants.h>
00043
00044 namespace swri_image_util
00045 {
00046 bool Intersects(const BoundingBox& box1, const BoundingBox& box2)
00047 {
00048 return (box1 & box2).area() > 0;
00049 }
00050
00051 double GetOverlappingArea(const cv::Rect& rect, const cv::Mat& rigid_transform)
00052 {
00053
00054 std::vector<cv::Vec2d> points;
00055
00056
00057 std::vector<cv::Vec2d> points_t;
00058
00059
00060 points.push_back(cv::Vec2d(rect.x, rect.y));
00061 points.push_back(cv::Vec2d(rect.x + rect.width, rect.y));
00062 points.push_back(cv::Vec2d(rect.x + rect.width, rect.y + rect.height));
00063 points.push_back(cv::Vec2d(rect.x, rect.y + rect.height));
00064
00065
00066
00067 cv::transform(cv::InputArray(points), cv::OutputArray(points_t), rigid_transform);
00068
00069
00070 return swri_geometry_util::PolygonIntersectionArea(points, points_t);
00071 }
00072
00073 cv::Mat ProjectEllipsoid(const cv::Mat& ellipsoid)
00074 {
00075 cv::Mat ellipse;
00076
00077 if (ellipsoid.rows == 3 && ellipsoid.cols == 3 && ellipsoid.type() == CV_32FC1)
00078 {
00079 if (ellipsoid.at<float>(2, 2) >= std::numeric_limits<double>::max() * 0.5)
00080 {
00081 ellipse.create(2, 2, CV_32FC1);
00082 ellipse.at<float>(0, 0) = ellipsoid.at<float>(0, 0);
00083 ellipse.at<float>(0, 1) = ellipsoid.at<float>(0, 1);
00084 ellipse.at<float>(1, 0) = ellipsoid.at<float>(1, 0);
00085 ellipse.at<float>(1, 1) = ellipsoid.at<float>(1, 1);
00086
00087 return ellipse;
00088 }
00089
00090 Eigen::Matrix3d A;
00091 for (size_t r = 0; r < 3; r++)
00092 {
00093 for (size_t c = 0; c < 3; c++)
00094 {
00095 A(r, c) = ellipsoid.at<float>(r, c);
00096 }
00097 }
00098
00099
00100 Eigen::Vector3d ax1;
00101 Eigen::Vector3d ax2;
00102 ax1 << 1, 0, 0;
00103 ax2 << 0, 1, 0;
00104
00105
00106
00107 Eigen::Vector3d n_ax;
00108 n_ax << 0, 0, 1;
00109
00111
00113
00114 Eigen::Matrix3d A_sym_temp = A.transpose() + A;
00115
00116
00117 Eigen::Matrix3d N_ax_temp = n_ax * n_ax.transpose();
00118
00119
00120
00121 Eigen::Matrix3d A_prime_1 = A_sym_temp * N_ax_temp;
00122
00123
00124
00125 Eigen::Matrix3d A_prime_2 = A_prime_1 * A_sym_temp;
00126
00127
00128 Eigen::RowVector3d scale_1 = n_ax.transpose() * A;
00129
00130
00131
00132 double scale = (scale_1 * n_ax)(0,0) * -4.0;
00133
00134
00135
00136 Eigen::Matrix3d A_temp = A * scale;
00137
00138
00139
00140 Eigen::Matrix3d Aprime = A_prime_2 + A_temp;
00141
00143
00145
00146
00147 Eigen::RowVector3d C_temp = n_ax.transpose() * A;
00148
00149
00150
00151 double cp = (-4.0 * C_temp) * n_ax;
00152
00153
00154 Eigen::Matrix3d Bprime = Aprime / cp;
00155
00156
00157
00158 Eigen::Matrix<double, 3, 2> Jp;
00159 Jp << 1, 0,
00160 0, 1,
00161 0, 0;
00162
00164
00166
00167
00168 Eigen::Matrix<double, 2, 3> Dprime_temp = Jp.transpose() * Bprime;
00169
00170
00171
00172 Eigen::Matrix2d Dprime = Dprime_temp * Jp;
00173
00174 for (size_t r = 0; r < 2; r++)
00175 {
00176 for (size_t c = 0; c < 2; c++)
00177 {
00178 if (Dprime(r, c) != Dprime(r, c))
00179 {
00180 return ellipse;
00181 }
00182 }
00183 }
00184
00185 ellipse.create(2, 2, CV_32FC1);
00186 ellipse.at<float>(0, 0) = Dprime(0, 0);
00187 ellipse.at<float>(0, 1) = Dprime(0, 1);
00188 ellipse.at<float>(1, 0) = Dprime(1, 0);
00189 ellipse.at<float>(1, 1) = Dprime(1, 1);
00190 }
00191
00192 return ellipse;
00193 }
00194
00195 std::vector<tf::Vector3> GetEllipsePoints(
00196 const cv::Mat& ellipse,
00197 const tf::Vector3& center,
00198 double scale,
00199 int32_t num_points)
00200 {
00201 std::vector<tf::Vector3> perimeter;
00202
00203 if (ellipse.rows == 2 && ellipse.cols == 2 && ellipse.type() == CV_32FC1 &&
00204 num_points > 2)
00205 {
00206 Eigen::Matrix2d Dprime;
00207 Dprime(0, 0) = ellipse.at<float>(0, 0);
00208 Dprime(0, 1) = ellipse.at<float>(0, 1);
00209 Dprime(1, 0) = ellipse.at<float>(1, 0);
00210 Dprime(1, 1) = ellipse.at<float>(1, 1);
00211
00212 Eigen::JacobiSVD<Eigen::Matrix2d> svd(Dprime, Eigen::ComputeFullV);
00213
00214 Eigen::Vector2d Sigma = svd.singularValues();
00215 Eigen::Matrix2d Vt = svd.matrixV().transpose();
00216
00217 double xprime_scale = std::sqrt(Sigma(0));
00218 double yprime_scale = std::sqrt(Sigma(1));
00219
00220 if (xprime_scale <= 0 || yprime_scale <= 0)
00221 {
00222 return perimeter;
00223 }
00224
00225 Eigen::MatrixX2d Xp1(num_points, 2);
00226 for (int32_t i = 0; i < num_points; i++)
00227 {
00228 double phi =
00229 (static_cast<double>(i) / static_cast<double>(num_points))
00230 * swri_math_util::_2pi;
00231
00232 Xp1(i, 0) = xprime_scale * std::cos(phi) * scale;
00233 Xp1(i, 1) = yprime_scale * std::sin(phi) * scale;
00234 }
00235
00236
00237 Eigen::MatrixX2d Xell = Xp1 * Vt;
00238
00239 perimeter.resize(num_points);
00240 for (int32_t i = 0; i < num_points; i++)
00241 {
00242 perimeter[i].setX(Xell(i, 0) + center.x());
00243 perimeter[i].setY(Xell(i, 1) + center.y());
00244 }
00245 }
00246
00247 return perimeter;
00248 }
00249 }