00001
00002
00003
00004
00005
00006
00007 #include "pano_core/ModelFitter.h"
00008 #include "pano_core/feature_utils.h"
00009 using namespace cv;
00010
00011 #define ROOT_2 1.41421356
00012 #define EPS_EQ(t,val) (t >= val - 1.0e-3 && t <= val + 1.0e-3)
00013
00014 namespace pano
00015 {
00016
00017
00018
00019
00020
00021
00022
00023 void SVDRSolverParams::serialize(cv::FileStorage& fs) const
00024 {
00025 fs << "{";
00026 fs << "error_thresh" << error_thresh;
00027 fs << "inliers_thresh" << inliers_thresh;
00028 fs << "maxiters" << maxiters;
00029 fs << "nNeeded" << nNeeded;
00030 fs << "}";
00031 }
00032 void SVDRSolverParams::deserialize(const cv::FileNode& node)
00033 {
00034 error_thresh = (double)node["error_thresh"];
00035 inliers_thresh = (double)node["inliers_thresh"];
00036 maxiters = (int)node["maxiters"];
00037 nNeeded = (int)node["nNeeded"];
00038 }
00039
00040 namespace
00041 {
00042
00043 Mat svdsolve(const cv::Mat& correlation)
00044 {
00045
00046 cv::SVD svd(correlation);
00047
00048
00049 int s = cv::determinant(svd.u * svd.vt) > 0 ? 1 : -1;
00050
00051 cv::Mat diagm = cv::Mat::eye(3, 3, svd.u.type());
00052
00053
00054 diagm.at<float> (2, 2) = s;
00055
00056
00057 return svd.u * diagm * svd.vt;
00058 }
00059
00060 Mat svdcorrelation(const vector<Point3f>& pts1, const vector<Point3f>& pts2, const vector<uchar>& mask)
00061 {
00062 cv::Mat r1 = cv::Mat(3, 1, CV_32F);
00063 cv::Mat r2 = cv::Mat(3, 1, CV_32F);
00064
00065 cv::Mat correlation = cv::Mat::zeros(3, 3, cv::DataType<float>::type);
00066 float* r1p = r1.ptr<float> (0);
00067 float* r2p = r2.ptr<float> (0);
00068 for (size_t i = 0; i < pts1.size(); i++)
00069 {
00070 if (mask.empty() || mask[i])
00071 {
00072 memcpy(r1p, &pts1[i], 3 * sizeof(float));
00073 memcpy(r2p, &pts2[i], 3 * sizeof(float));
00074
00075 correlation += r2 * r1.t();
00076
00077 }
00078 }
00079 return correlation;
00080 }
00081
00082 Mat svdsolve(const vector<Point3f>& pts1, const vector<Point3f>& pts2, const vector<uchar>& mask)
00083 {
00084 return svdsolve(svdcorrelation(pts1, pts2, mask));
00085 }
00086
00087 Mat svdsolve(const vector<Point2f>& pts1, const vector<Point2f>& pts2, const vector<uchar>& mask, const Mat& K)
00088 {
00089
00090 cv::Mat correlation = cv::Mat::zeros(3, 3, cv::DataType<float>::type);
00091 for (size_t i = 0; i < pts1.size(); i++)
00092 {
00093 if (mask.empty() || mask[i])
00094 {
00095
00096 cv::Mat r1 = pt2f_to_3d(pts1[i], K);
00097
00098
00099 cv::Mat r2 = pt2f_to_3d(pts2[i], K);
00100
00101
00102 correlation += r2 * r1.t();
00103 }
00104 }
00105
00106 return svdsolve(correlation);
00107
00108 }
00109
00110 struct NextNum
00111 {
00112 int num_;
00113 NextNum() :
00114 num_(0)
00115 {
00116 }
00117 int operator()()
00118 {
00119 return num_++;
00120 }
00121 };
00122
00123 void ransacSolveR(const vector<Point3f>& pts1, const vector<Point3f>& pts2, FitterResult& result, int maxiters,
00124 int inliers_thresh, int nNeeded, double error_thresh, cv::Mat K, cv::Mat Kinv)
00125 {
00126 float bestdist = 1e8;
00127 int bestinliers = 0;
00128 if (pts1.empty() || pts1.size() < size_t(inliers_thresh))
00129 {
00130 result = FitterResult(FitterResult::GenerateStdMats(), false, bestdist, error_thresh, vector<uchar> (), 0);
00131 return;
00132 }
00133
00134 int iters = 0;
00135
00136 vector<uchar> _best(pts1.size()), _mask(pts1.size());
00137
00138 vector<uchar> * best = &_best;
00139 vector<uchar> * mask = &_mask;
00140
00141 Mat bestR = Mat::eye(3, 3, DataType<float>::type);
00142
00143 vector<Point3f> rpts1(nNeeded);
00144 vector<Point3f> rpts2(nNeeded);
00145
00146 int ntotal = pts1.size();
00147 ;
00148 Mat R = cv::Mat::eye(3, 3, CV_32F);
00149
00150 vector<int> idxs(pts1.size());
00151 generate(idxs.begin(), idxs.end(), NextNum());
00152
00153
00154
00155
00156 int r_idx = 0;
00157
00158 maxiters = std::min(int(pts1.size()),maxiters);
00159
00160 while (iters++ < maxiters)
00161 {
00162
00163
00164 int numinliers = 0;
00165 float sumdist = 0;
00166
00167 rpts1.clear();
00168 rpts2.clear();
00169
00170
00171 while ((int)rpts1.size() < nNeeded)
00172 {
00173
00174 if (find(rpts2.begin(), rpts2.end(), RadiusPoint(0.01, pts2[idxs[r_idx]])) == rpts2.end()
00175 && find(rpts1.begin(), rpts1.end(), RadiusPoint(0.01, pts1[idxs[r_idx]])) == rpts1.end())
00176 {
00177 rpts1.push_back(pts1[idxs[r_idx]]);
00178 rpts2.push_back(pts2[idxs[r_idx]]);
00179
00180 }
00181
00182 r_idx++;
00183 if (r_idx >= (int)idxs.size())
00184 {
00185 break;
00186 }
00187
00188 }
00189
00190 if (r_idx >= (int)idxs.size())
00191 {
00192
00193 r_idx = 0;
00194 Mat idxs_m(idxs);
00195 randShuffle(idxs_m);
00196 continue;
00197 }
00198
00199
00200 R = svdsolve(rpts1, rpts2, vector<uchar> ());
00201
00202 std::fill(mask->begin(), mask->end(), 0);
00203
00204 for (int i = 0; i < ntotal; i++)
00205 {
00206 float error_point_i = calcError(pts1[i], pts2[i], R, K);
00207 if (error_point_i < error_thresh)
00208 {
00209 numinliers++;
00210 (*mask)[i] = 1;
00211 sumdist += error_point_i;
00212 }
00213 }
00214 if (numinliers >= inliers_thresh)
00215 {
00216
00217 Mat tR = svdsolve(pts1, pts2, *mask);
00218 float cur_dist = calcError(pts1, pts2, *mask, tR, K);
00219
00220 if (cur_dist <= bestdist)
00221 {
00222 bestinliers = numinliers;
00223 vector<uchar> * temp = best;
00224 best = mask;
00225 mask = temp;
00226 bestR = tR;
00227 bestdist = cur_dist;
00228 }
00229
00230 }
00231
00232 if (inliers_thresh < bestinliers * 2){
00233 std::cout << "early break iters: " << iters << std::endl;
00234 break;
00235 }
00236
00237 }
00238
00239 cv::Mat omega_(3, 1, CV_32F);
00240 cv::Rodrigues(bestR, omega_);
00241 int good = bestinliers >= inliers_thresh;
00242 good = good * (bestdist < error_thresh);
00243 vector<Mat> mats = FitterResult::GenerateStdMats();
00244
00245 mats[FitterResult::R] = bestR;
00246 mats[FitterResult::W_HAT] = omega_;
00247
00248 result = FitterResult(mats, good, bestdist, error_thresh, *best, bestinliers);
00249
00250 }
00251
00252 void svdSolveR(const vector<Point3f>& rays1, const vector<Point3f>& rays2, FitterResult& result, int maxiters,
00253 int inliers_thresh, int nNeeded, double error_thresh, cv::Mat K, cv::Mat Kinv)
00254 {
00255
00256
00257 Mat R = svdsolve(rays1, rays2, vector<uchar> ());
00258 cv::Mat omega_(3, 1, CV_32F);
00259 cv::Rodrigues(R, omega_);
00260 vector<Mat> mats = FitterResult::GenerateStdMats();
00261
00262 mats[FitterResult::R] = R;
00263 mats[FitterResult::W_HAT] = omega_;
00264
00265 result = FitterResult(mats, true, 1.0, error_thresh, vector<uchar> (1,rays1.size()), rays1.size());
00266
00267 }
00268
00269 void ransacSolveR(const vector<Point2f>& _pts1, const vector<Point2f>& _pts2, FitterResult& result, int maxiters,
00270 int inliers_thresh, int nNeeded, double error_thresh, cv::Mat K, cv::Mat Kinv)
00271 {
00272
00273 vector<Point3f> m_pts1, m_pts2;
00274 m_pts1.resize(_pts1.size());
00275 m_pts2.resize(_pts2.size());
00276 points2fto3f(_pts1.begin(), _pts1.end(), m_pts1.begin(), Kinv);
00277 points2fto3f(_pts2.begin(), _pts2.end(), m_pts2.begin(), Kinv);
00278 ransacSolveR(m_pts1, m_pts2, result, maxiters, inliers_thresh, nNeeded, error_thresh, K, Kinv);
00279
00280 }
00281
00282 }
00283
00284 void SVDFitR::operator ()(SVDRSolverParams& params, AtomPair& pair) const
00285 {
00286
00287 if (params.nNeeded < 0 && pair.rays1().size() >= 2)
00288 {
00289 svdSolveR(pair.rays1(), pair.rays2(), pair.result(), params.maxiters, params.inliers_thresh, params.nNeeded,
00290 params.error_thresh, pair.atom1()->camera().K(), pair.atom1()->camera().Kinv());
00291 return;
00292 }
00293 if (pair.rays1().size() < params.inliers_thresh)
00294 return;
00295 ransacSolveR(pair.rays1(), pair.rays2(), pair.result(), params.maxiters, params.inliers_thresh, params.nNeeded,
00296 params.error_thresh, pair.atom1()->camera().K(), pair.atom1()->camera().Kinv());
00297 }
00298
00299 }