Commit 2de0e1fc authored by Alexey Spizhevoy's avatar Alexey Spizhevoy

refactored opencv_stitching

parent 5b50d637
......@@ -35,10 +35,9 @@ void focalsFromHomography(const Mat& H, double &f0, double &f1, bool &f0_ok, boo
}
double estimateFocal(const vector<Mat> &images, const vector<ImageFeatures> &/*features*/,
const vector<MatchesInfo> &pairwise_matches)
double estimateFocal(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches)
{
const int num_images = static_cast<int>(images.size());
const int num_images = static_cast<int>(features.size());
vector<double> focals;
for (int src_idx = 0; src_idx < num_images; ++src_idx)
......@@ -65,6 +64,6 @@ double estimateFocal(const vector<Mat> &images, const vector<ImageFeatures> &/*f
LOGLN("Can't estimate focal length, will use naive approach");
double focals_sum = 0;
for (int i = 0; i < num_images; ++i)
focals_sum += images[i].rows + images[i].cols;
focals_sum += features[i].img_size.width + features[i].img_size.height;
return focals_sum / num_images;
}
......@@ -9,7 +9,6 @@
// by Heung-Yeung Shum and Richard Szeliski.
void focalsFromHomography(const cv::Mat &H, double &f0, double &f1, bool &f0_ok, bool &f1_ok);
double estimateFocal(const std::vector<cv::Mat> &images, const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches);
double estimateFocal(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches);
#endif // __OPENCV_AUTOCALIB_HPP__
......@@ -37,7 +37,6 @@ int main(int argc, char* argv[])
cv::setBreakOnError(true);
vector<string> img_names;
vector<Mat> images;
// Default parameters
bool trygpu = false;
......@@ -188,32 +187,11 @@ int main(int argc, char* argv[])
i++;
}
else
{
img_names.push_back(argv[i]);
Mat full_img = imread(argv[i]);
if (full_img.empty())
{
cout << "Can't open image " << argv[i] << endl;
return -1;
}
if (work_megapix < 0)
images.push_back(full_img);
else
{
if (!is_work_scale_set)
{
work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));
is_work_scale_set = true;
}
Mat img;
resize(full_img, img, Size(), work_scale, work_scale);
images.push_back(img);
}
}
}
LOGLN("Parsing params and reading images, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
int num_images = static_cast<int>(images.size());
int num_images = static_cast<int>(img_names.size());
if (num_images < 2)
{
cout << "Need more images\n";
......@@ -222,9 +200,30 @@ int main(int argc, char* argv[])
t = getTickCount();
LOGLN("Finding features...");
vector<ImageFeatures> features;
vector<ImageFeatures> features(num_images);
SurfFeaturesFinder finder(trygpu);
finder(images, features);
Mat full_img, img;
for (int i = 0; i < num_images; ++i)
{
full_img = imread(img_names[i]);
if (full_img.empty())
{
cout << "Can't open image " << img_names[i] << endl;
return -1;
}
if (work_megapix < 0)
img = full_img;
else
{
if (!is_work_scale_set)
{
work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));
is_work_scale_set = true;
}
resize(full_img, img, Size(), work_scale, work_scale);
}
finder(img, features[i]);
}
LOGLN("Finding features, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
t = getTickCount();
......@@ -233,16 +232,16 @@ int main(int argc, char* argv[])
BestOf2NearestMatcher matcher(trygpu);
if (user_match_conf)
matcher = BestOf2NearestMatcher(trygpu, match_conf);
matcher(images, features, pairwise_matches);
matcher(features, pairwise_matches);
LOGLN("Pairwise matching, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
vector<int> indices = leaveBiggestComponent(images, features, pairwise_matches, conf_thresh);
vector<int> indices = leaveBiggestComponent(features, pairwise_matches, conf_thresh);
vector<string> img_names_subset;
for (size_t i = 0; i < indices.size(); ++i)
img_names_subset.push_back(img_names[indices[i]]);
img_names = img_names_subset;
num_images = static_cast<int>(images.size());
num_images = static_cast<int>(img_names.size());
if (num_images < 2)
{
cout << "Need more images\n";
......@@ -253,7 +252,7 @@ int main(int argc, char* argv[])
LOGLN("Estimating rotations...");
HomographyBasedEstimator estimator;
vector<CameraParams> cameras;
estimator(images, features, pairwise_matches, cameras);
estimator(features, pairwise_matches, cameras);
LOGLN("Estimating rotations, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
for (size_t i = 0; i < cameras.size(); ++i)
......@@ -267,7 +266,7 @@ int main(int argc, char* argv[])
t = getTickCount();
LOGLN("Bundle adjustment... ");
BundleAdjuster adjuster(ba_space, conf_thresh);
adjuster(images, features, pairwise_matches, cameras);
adjuster(features, pairwise_matches, cameras);
LOGLN("Bundle adjustment, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
if (wave_correct)
......@@ -293,27 +292,24 @@ int main(int argc, char* argv[])
nth_element(focals.begin(), focals.end(), focals.begin() + focals.size() / 2);
float camera_focal = static_cast<float>(focals[focals.size() / 2]);
if ((work_megapix > 0 || compose_megapix > 0)
&& abs(work_megapix - compose_megapix) > 1e-3)
t = getTickCount();
vector<Mat> images(num_images);
LOGLN("Compose scaling...");
for (int i = 0; i < num_images; ++i)
{
t = getTickCount();
LOGLN("Compose scaling...");
for (int i = 0; i < num_images; ++i)
Mat full_img = imread(img_names[i]);
if (!is_compose_scale_set)
{
Mat full_img = imread(img_names[i]);
if (!is_compose_scale_set)
{
compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area()));
is_compose_scale_set = true;
}
Mat img;
resize(full_img, img, Size(), compose_scale, compose_scale);
images[i] = img;
cameras[i].focal *= compose_scale / work_scale;
compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area()));
is_compose_scale_set = true;
}
camera_focal *= static_cast<float>(compose_scale / work_scale);
LOGLN("Compose scaling, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
Mat img;
resize(full_img, img, Size(), compose_scale, compose_scale);
images[i] = img;
cameras[i].focal *= compose_scale / work_scale;
}
camera_focal *= static_cast<float>(compose_scale / work_scale);
LOGLN("Compose scaling, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
vector<Mat> masks(num_images);
for (int i = 0; i < num_images; ++i)
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
struct ImageFeatures
{
cv::Size img_size;
cv::Mat hist;
std::vector<cv::KeyPoint> keypoints;
cv::Mat descriptors;
......@@ -17,10 +18,10 @@ class FeaturesFinder
{
public:
virtual ~FeaturesFinder() {}
void operator ()(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features);
void operator ()(const cv::Mat &image, ImageFeatures &features);
protected:
virtual void find(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features) = 0;
virtual void find(const cv::Mat &image, ImageFeatures &features) = 0;
};
......@@ -32,7 +33,7 @@ public:
int num_octaves_descr = 4, int num_layers_descr = 2);
protected:
void find(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features);
void find(const cv::Mat &image, ImageFeatures &features);
cv::Ptr<FeaturesFinder> impl_;
};
......@@ -57,14 +58,12 @@ class FeaturesMatcher
{
public:
virtual ~FeaturesMatcher() {}
void operator ()(const cv::Mat &img1, const ImageFeatures &features1, const cv::Mat &img2, const ImageFeatures &features2,
MatchesInfo& matches_info) { match(img1, features1, img2, features2, matches_info); }
void operator ()(const std::vector<cv::Mat> &images, const std::vector<ImageFeatures> &features,
std::vector<MatchesInfo> &pairwise_matches);
void operator ()(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info)
{ match(features1, features2, matches_info); }
void operator ()(const std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches);
protected:
virtual void match(const cv::Mat &img1, const ImageFeatures &features1, const cv::Mat &img2, const ImageFeatures &features2,
MatchesInfo& matches_info) = 0;
virtual void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo& matches_info) = 0;
};
......@@ -74,8 +73,7 @@ public:
BestOf2NearestMatcher(bool try_use_gpu = true, float match_conf = 0.55f, int num_matches_thresh1 = 6, int num_matches_thresh2 = 6);
protected:
void match(const cv::Mat &img1, const ImageFeatures &features1, const cv::Mat &img2, const ImageFeatures &features2,
MatchesInfo &matches_info);
void match(const ImageFeatures &features1, const ImageFeatures &features2, MatchesInfo &matches_info);
int num_matches_thresh1_;
int num_matches_thresh2_;
......
......@@ -64,13 +64,13 @@ struct CalcRotation
};
void HomographyBasedEstimator::estimate(const vector<Mat> &images, const vector<ImageFeatures> &features,
const vector<MatchesInfo> &pairwise_matches, vector<CameraParams> &cameras)
void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches,
vector<CameraParams> &cameras)
{
const int num_images = static_cast<int>(images.size());
const int num_images = static_cast<int>(features.size());
// Estimate focal length and set it for all cameras
double focal = estimateFocal(images, features, pairwise_matches);
double focal = estimateFocal(features, pairwise_matches);
cameras.resize(num_images);
for (int i = 0; i < num_images; ++i)
cameras[i].focal = focal;
......@@ -85,11 +85,10 @@ void HomographyBasedEstimator::estimate(const vector<Mat> &images, const vector<
//////////////////////////////////////////////////////////////////////////////
void BundleAdjuster::estimate(const vector<Mat> &images, const vector<ImageFeatures> &features,
const vector<MatchesInfo> &pairwise_matches, vector<CameraParams> &cameras)
void BundleAdjuster::estimate(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches,
vector<CameraParams> &cameras)
{
num_images_ = static_cast<int>(images.size());
images_ = &images[0];
num_images_ = static_cast<int>(features.size());
features_ = &features[0];
pairwise_matches_ = &pairwise_matches[0];
......@@ -227,11 +226,11 @@ void BundleAdjuster::calcError(Mat &err)
const DMatch& m = matches_info.matches[k];
Point2d kp1 = features1.keypoints[m.queryIdx].pt;
kp1.x -= 0.5 * images_[i].cols;
kp1.y -= 0.5 * images_[i].rows;
kp1.x -= 0.5 * features1.img_size.width;
kp1.y -= 0.5 * features1.img_size.height;
Point2d kp2 = features2.keypoints[m.trainIdx].pt;
kp2.x -= 0.5 * images_[j].cols;
kp2.y -= 0.5 * images_[j].rows;
kp2.x -= 0.5 * features2.img_size.width;
kp2.y -= 0.5 * features2.img_size.height;
double len1 = sqrt(kp1.x * kp1.x + kp1.y * kp1.y + f1 * f1);
double len2 = sqrt(kp2.x * kp2.x + kp2.y * kp2.y + f2 * f2);
Point3d p1(kp1.x / len1, kp1.y / len1, f1 / len1);
......@@ -346,10 +345,10 @@ void waveCorrect(vector<Mat> &rmats)
//////////////////////////////////////////////////////////////////////////////
vector<int> leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features,
vector<MatchesInfo> &pairwise_matches, float conf_threshold)
vector<int> leaveBiggestComponent(vector<ImageFeatures> &features, vector<MatchesInfo> &pairwise_matches,
float conf_threshold)
{
const int num_images = static_cast<int>(images.size());
const int num_images = static_cast<int>(features.size());
DjSets comps(num_images);
for (int i = 0; i < num_images; ++i)
......@@ -375,12 +374,10 @@ vector<int> leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &fe
else
indices_removed.push_back(i);
vector<Mat> images_subset;
vector<ImageFeatures> features_subset;
vector<MatchesInfo> pairwise_matches_subset;
for (size_t i = 0; i < indices.size(); ++i)
{
images_subset.push_back(images[indices[i]]);
features_subset.push_back(features[indices[i]]);
for (size_t j = 0; j < indices.size(); ++j)
{
......@@ -390,7 +387,7 @@ vector<int> leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &fe
}
}
if (static_cast<int>(images_subset.size()) == num_images)
if (static_cast<int>(features_subset.size()) == num_images)
return indices;
LOG("Removed some images, because can't match them: (");
......@@ -398,7 +395,6 @@ vector<int> leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &fe
for (size_t i = 1; i < indices_removed.size(); ++i) LOG(", " << indices_removed[i]);
LOGLN(")");
images = images_subset;
features = features_subset;
pairwise_matches = pairwise_matches_subset;
......
......@@ -21,15 +21,15 @@ struct CameraParams
class Estimator
{
public:
void operator ()(const std::vector<cv::Mat> &images, const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras)
void operator ()(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras)
{
estimate(images, features, pairwise_matches, cameras);
estimate(features, pairwise_matches, cameras);
}
protected:
virtual void estimate(const std::vector<cv::Mat> &images, const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras) = 0;
virtual void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras) = 0;
};
......@@ -40,8 +40,8 @@ public:
bool isFocalsEstimated() const { return is_focals_estimated_; }
private:
void estimate(const std::vector<cv::Mat> &images, const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras);
void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras);
bool is_focals_estimated_;
};
......@@ -56,15 +56,14 @@ public:
: cost_space_(cost_space), conf_thresh_(conf_thresh) {}
private:
void estimate(const std::vector<cv::Mat> &images, const std::vector<ImageFeatures> &features,
const std::vector<MatchesInfo> &pairwise_matches, std::vector<CameraParams> &cameras);
void estimate(const std::vector<ImageFeatures> &features, const std::vector<MatchesInfo> &pairwise_matches,
std::vector<CameraParams> &cameras);
void calcError(cv::Mat &err);
void calcJacobian();
int num_images_;
int total_num_matches_;
const cv::Mat *images_;
const ImageFeatures *features_;
const MatchesInfo *pairwise_matches_;
cv::Mat cameras_;
......@@ -83,8 +82,8 @@ void waveCorrect(std::vector<cv::Mat> &rmats);
//////////////////////////////////////////////////////////////////////////////
// Auxiliary functions
std::vector<int> leaveBiggestComponent(std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features,
std::vector<MatchesInfo> &pairwise_matches, float conf_threshold);
std::vector<int> leaveBiggestComponent(std::vector<ImageFeatures> &features, std::vector<MatchesInfo> &pairwise_matches,
float conf_threshold);
void findMaxSpanningTree(int num_images, const std::vector<MatchesInfo> &pairwise_matches,
Graph &span_tree, std::vector<int> &centers);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment