class MultiBandBlender : public Blender
{
public:
- MultiBandBlender(int num_bands = 10) : num_bands_(num_bands) {}
+ MultiBandBlender(int num_bands = 7) : num_bands_(num_bands) {}
private:
cv::Point blend(const std::vector<cv::Mat> &src, const std::vector<cv::Point> &corners, const std::vector<cv::Mat> &masks,
cout << "Rotation model images stitcher.\n" \r
<< "Usage: opencv_stitching img1 img2 [...imgN]\n" \r
<< "\t[--matchconf <0.0-1.0>]\n"\r
- << "\t[--ba (ray_space|focal_ray_space)]\n"\r
+ << "\t[--ba (ray|focal_ray)]\n"\r
+ //<< "\t[--wavecorrect (no|yes)]\n"\r
<< "\t[--warp (plane|cylindrical|spherical)]\n" \r
<< "\t[--seam (no|voronoi|graphcut)]\n" \r
<< "\t[--blend (no|feather|multiband)]\n"\r
vector<Mat> images;\r
string result_name = "result.png";\r
int ba_space = BundleAdjuster::RAY_SPACE;\r
+ bool wave_correct = false;\r
int warp_type = Warper::SPHERICAL;\r
bool user_match_conf = false;\r
float match_conf = 0.55f;\r
}\r
else if (string(argv[i]) == "--ba")\r
{\r
- if (string(argv[i + 1]) == "ray_space")\r
+ if (string(argv[i + 1]) == "ray")\r
ba_space = BundleAdjuster::RAY_SPACE;\r
- else if (string(argv[i + 1]) == "focal_ray_space")\r
+ else if (string(argv[i + 1]) == "focal_ray")\r
ba_space = BundleAdjuster::FOCAL_RAY_SPACE;\r
else\r
{\r
}\r
i++;\r
}\r
+ //else if (string(argv[i]) == "--wavecorrect")\r
+ //{\r
+ // if (string(argv[i + 1]) == "no")\r
+ // wave_correct = false;\r
+ // else if (string(argv[i + 1]) == "yes")\r
+ // wave_correct = true;\r
+ // else\r
+ // {\r
+ // cout << "Bad wave correct flag value\n";\r
+ // return -1;\r
+ // }\r
+ // i++;\r
+ //}\r
else if (string(argv[i]) == "--warp")\r
{\r
if (string(argv[i + 1]) == "plane")\r
BundleAdjuster adjuster(ba_space);\r
adjuster(images, features, pairwise_matches, cameras);\r
\r
+ if (wave_correct)\r
+ {\r
+ LOGLN("Wave correcting...");\r
+ vector<Mat> rmats;\r
+ for (size_t i = 0; i < cameras.size(); ++i)\r
+ rmats.push_back(cameras[i].M);\r
+ waveCorrect(rmats);\r
+ for (size_t i = 0; i < cameras.size(); ++i)\r
+ cameras[i].M = rmats[i];\r
+ }\r
+\r
// Find median focal length\r
vector<double> focals;\r
for (size_t i = 0; i < cameras.size(); ++i)\r
public:
inline CpuSurfFeaturesFinder()
{
- detector_ = new SurfFeatureDetector(500.0);
- extractor_ = new SurfDescriptorExtractor;
+ detector_ = new SurfFeatureDetector(500);
+ extractor_ = new SurfDescriptorExtractor();
}
protected:
edges_.clear();
for (int i = 0; i < num_images_ - 1; ++i)
- {
for (int j = i + 1; j < num_images_; ++j)
- {
- int pair_idx = i * num_images_ + j;
- const MatchesInfo& mi = pairwise_matches_[pair_idx];
- float ni = static_cast<float>(mi.num_inliers);
- float nf = static_cast<float>(mi.matches.size());
- if (ni / (8.f + 0.3f * nf) > 1.f)
- edges_.push_back(make_pair(i, j));
- }
- }
+ edges_.push_back(make_pair(i, j));
total_num_matches_ = 0;
for (size_t i = 0; i < edges_.size(); ++i)
}
+//////////////////////////////////////////////////////////////////////////////
+
+// TODO test on adobe/halfdome
+void waveCorrect(vector<Mat> &rmats)
+{
+ float data[9];
+ Mat r0(1, 3, CV_32F, data);
+ Mat r1(1, 3, CV_32F, data + 3);
+ Mat r2(1, 3, CV_32F, data + 6);
+ Mat R(3, 3, CV_32F, data);
+
+ Mat cov = Mat::zeros(3, 3, CV_32F);
+ for (size_t i = 0; i < rmats.size(); ++i)
+ {
+ Mat r0 = rmats[i].col(0);
+ cov += r0 * r0.t();
+ }
+
+ SVD svd;
+ svd(cov, SVD::FULL_UV);
+ svd.vt.row(2).copyTo(r1);
+ if (determinant(svd.vt) < 0)
+ r1 *= -1;
+
+ Mat avgz = Mat::zeros(3, 1, CV_32F);
+ for (size_t i = 0; i < rmats.size(); ++i)
+ avgz += rmats[i].col(2);
+ avgz.t().cross(r1).copyTo(r0);
+ normalize(r0, r0);
+
+ r0.cross(r1).copyTo(r2);
+
+ for (size_t i = 0; i < rmats.size(); ++i)
+ rmats[i] = R * rmats[i];
+}
+
+
//////////////////////////////////////////////////////////////////////////////
void findMaxSpanningTree(int num_images, const vector<MatchesInfo> &pairwise_matches,
};
+void waveCorrect(std::vector<cv::Mat> &rmats);
+
+
//////////////////////////////////////////////////////////////////////////////
// Auxiliary functions