reduced memory requirements in opencv_stitching
This commit is contained in:
@@ -56,7 +56,7 @@ double estimateFocal(const vector<Mat> &images, const vector<ImageFeatures> &/*f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focals.size() + 1 >= images.size())
|
if (focals.size() >= 2 * (num_images - 1))
|
||||||
{
|
{
|
||||||
nth_element(focals.begin(), focals.end(), focals.begin() + focals.size()/2);
|
nth_element(focals.begin(), focals.end(), focals.begin() + focals.size()/2);
|
||||||
return focals[focals.size()/2];
|
return focals[focals.size()/2];
|
||||||
|
@@ -133,19 +133,20 @@ Point MultiBandBlender::blend(const vector<Mat> &src, const vector<Point> &corne
|
|||||||
int left = corners[img_idx].x - dst_roi.x;
|
int left = corners[img_idx].x - dst_roi.x;
|
||||||
int right = dst_roi.br().x - corners[img_idx].x - src[img_idx].cols;
|
int right = dst_roi.br().x - corners[img_idx].x - src[img_idx].cols;
|
||||||
|
|
||||||
Mat big_src;
|
vector<Mat> src_pyr_gauss(num_bands_ + 1);
|
||||||
copyMakeBorder(src[img_idx], big_src, top, bottom, left, right, BORDER_REFLECT);
|
copyMakeBorder(src[img_idx], src_pyr_gauss[0], top, bottom, left, right, BORDER_REFLECT);
|
||||||
vector<Mat> src_pyr_gauss;
|
for (int i = 0; i < num_bands_; ++i)
|
||||||
|
pyrDown(src_pyr_gauss[i], src_pyr_gauss[i + 1]);
|
||||||
|
|
||||||
vector<Mat> src_pyr_laplace;
|
vector<Mat> src_pyr_laplace;
|
||||||
createGaussPyr(big_src, num_bands_, src_pyr_gauss);
|
|
||||||
createLaplacePyr(src_pyr_gauss, src_pyr_laplace);
|
createLaplacePyr(src_pyr_gauss, src_pyr_laplace);
|
||||||
|
|
||||||
Mat big_mask;
|
vector<Mat> weight_pyr_gauss(num_bands_ + 1);
|
||||||
copyMakeBorder(masks[img_idx], big_mask, top, bottom, left, right, BORDER_CONSTANT);
|
Mat mask_f;
|
||||||
Mat weight_map;
|
masks[img_idx].convertTo(mask_f, CV_32F, 1./255.);
|
||||||
big_mask.convertTo(weight_map, CV_32F, 1./255.);
|
copyMakeBorder(mask_f, weight_pyr_gauss[0], top, bottom, left, right, BORDER_CONSTANT);
|
||||||
vector<Mat> weight_pyr_gauss;
|
for (int i = 0; i < num_bands_; ++i)
|
||||||
createGaussPyr(weight_map, num_bands_, weight_pyr_gauss);
|
pyrDown(weight_pyr_gauss[i], weight_pyr_gauss[i + 1]);
|
||||||
|
|
||||||
for (int band_idx = 0; band_idx <= num_bands_; ++band_idx)
|
for (int band_idx = 0; band_idx <= num_bands_; ++band_idx)
|
||||||
{
|
{
|
||||||
@@ -286,15 +287,6 @@ void createWeightMap(const Mat &mask, float sharpness, Mat &weight)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void createGaussPyr(const Mat &img, int num_layers, vector<Mat> &pyr)
|
|
||||||
{
|
|
||||||
pyr.resize(num_layers + 1);
|
|
||||||
pyr[0] = img.clone();
|
|
||||||
for (int i = 0; i < num_layers; ++i)
|
|
||||||
pyrDown(pyr[i], pyr[i + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void createLaplacePyr(const vector<Mat> &pyr_gauss, vector<Mat> &pyr_laplace)
|
void createLaplacePyr(const vector<Mat> &pyr_gauss, vector<Mat> &pyr_laplace)
|
||||||
{
|
{
|
||||||
if (pyr_gauss.size() == 0)
|
if (pyr_gauss.size() == 0)
|
||||||
|
@@ -63,8 +63,6 @@ void normalize(const cv::Mat& weight, cv::Mat& src);
|
|||||||
|
|
||||||
void createWeightMap(const cv::Mat& mask, float sharpness, cv::Mat& weight);
|
void createWeightMap(const cv::Mat& mask, float sharpness, cv::Mat& weight);
|
||||||
|
|
||||||
void createGaussPyr(const cv::Mat& img, int num_layers, std::vector<cv::Mat>& pyr);
|
|
||||||
|
|
||||||
void createLaplacePyr(const std::vector<cv::Mat>& pyr_gauss, std::vector<cv::Mat>& pyr_laplace);
|
void createLaplacePyr(const std::vector<cv::Mat>& pyr_gauss, std::vector<cv::Mat>& pyr_laplace);
|
||||||
|
|
||||||
// Restores source image in-place. Result will be stored in pyr[0].
|
// Restores source image in-place. Result will be stored in pyr[0].
|
||||||
|
@@ -35,8 +35,8 @@ int main(int argc, char* argv[])
|
|||||||
vector<string> img_names;
|
vector<string> img_names;
|
||||||
vector<Mat> images;
|
vector<Mat> images;
|
||||||
bool trygpu = true;
|
bool trygpu = true;
|
||||||
double work_megapix = -1;
|
double work_megapix = 1;
|
||||||
double compose_megapix = -1;
|
double compose_megapix = 1;
|
||||||
int ba_space = BundleAdjuster::FOCAL_RAY_SPACE;
|
int ba_space = BundleAdjuster::FOCAL_RAY_SPACE;
|
||||||
float conf_thresh = 1.f;
|
float conf_thresh = 1.f;
|
||||||
bool wave_correct = true;
|
bool wave_correct = true;
|
||||||
@@ -47,8 +47,8 @@ int main(int argc, char* argv[])
|
|||||||
int blend_type = Blender::MULTI_BAND;
|
int blend_type = Blender::MULTI_BAND;
|
||||||
string result_name = "result.png";
|
string result_name = "result.png";
|
||||||
|
|
||||||
double work_scale = 1, compose_scale = 1;
|
double work_scale, compose_scale;
|
||||||
bool is_work_scale_set = false, is_compose_scale_set = true;
|
bool is_work_scale_set = false, is_compose_scale_set = false;
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
{
|
{
|
||||||
@@ -85,7 +85,6 @@ int main(int argc, char* argv[])
|
|||||||
else if (string(argv[i]) == "--compose_megapix")
|
else if (string(argv[i]) == "--compose_megapix")
|
||||||
{
|
{
|
||||||
compose_megapix = atof(argv[i + 1]);
|
compose_megapix = atof(argv[i + 1]);
|
||||||
is_compose_scale_set = false;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if (string(argv[i]) == "--result")
|
else if (string(argv[i]) == "--result")
|
||||||
@@ -195,7 +194,7 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
if (!is_work_scale_set)
|
if (!is_work_scale_set)
|
||||||
{
|
{
|
||||||
work_scale = min(1.0, sqrt(work_megapix * 1000000 / full_img.size().area()));
|
work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));
|
||||||
is_work_scale_set = true;
|
is_work_scale_set = true;
|
||||||
}
|
}
|
||||||
Mat img;
|
Mat img;
|
||||||
@@ -224,7 +223,11 @@ int main(int argc, char* argv[])
|
|||||||
matcher = BestOf2NearestMatcher(true, match_conf);
|
matcher = BestOf2NearestMatcher(true, match_conf);
|
||||||
matcher(images, features, pairwise_matches);
|
matcher(images, features, pairwise_matches);
|
||||||
|
|
||||||
leaveBiggestComponent(images, features, pairwise_matches, conf_thresh);
|
vector<int> indices = leaveBiggestComponent(images, 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>(images.size());
|
||||||
if (num_images < 2)
|
if (num_images < 2)
|
||||||
@@ -271,14 +274,15 @@ int main(int argc, char* argv[])
|
|||||||
nth_element(focals.begin(), focals.end(), focals.begin() + focals.size() / 2);
|
nth_element(focals.begin(), focals.end(), focals.begin() + focals.size() / 2);
|
||||||
float camera_focal = static_cast<float>(focals[focals.size() / 2]);
|
float camera_focal = static_cast<float>(focals[focals.size() / 2]);
|
||||||
|
|
||||||
if (work_megapix > 0 || compose_megapix > 0)
|
if ((work_megapix > 0 || compose_megapix > 0)
|
||||||
|
&& abs(work_megapix - compose_megapix) > 1e-3)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < num_images; ++i)
|
for (int i = 0; i < num_images; ++i)
|
||||||
{
|
{
|
||||||
Mat full_img = imread(img_names[i]);
|
Mat full_img = imread(img_names[i]);
|
||||||
if (!is_compose_scale_set)
|
if (!is_compose_scale_set)
|
||||||
{
|
{
|
||||||
compose_scale = min(1.0, sqrt(compose_megapix * 1000000 / full_img.size().area()));
|
compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area()));
|
||||||
is_compose_scale_set = true;
|
is_compose_scale_set = true;
|
||||||
}
|
}
|
||||||
Mat img;
|
Mat img;
|
||||||
|
@@ -328,8 +328,7 @@ void waveCorrect(vector<Mat> &rmats)
|
|||||||
SVD svd;
|
SVD svd;
|
||||||
svd(cov, SVD::FULL_UV);
|
svd(cov, SVD::FULL_UV);
|
||||||
svd.vt.row(2).copyTo(r1);
|
svd.vt.row(2).copyTo(r1);
|
||||||
if (determinant(svd.vt) < 0)
|
if (determinant(svd.vt) < 0) r1 *= -1;
|
||||||
r1 *= -1;
|
|
||||||
|
|
||||||
Mat avgz = Mat::zeros(3, 1, CV_32F);
|
Mat avgz = Mat::zeros(3, 1, CV_32F);
|
||||||
for (size_t i = 0; i < rmats.size(); ++i)
|
for (size_t i = 0; i < rmats.size(); ++i)
|
||||||
@@ -338,8 +337,7 @@ void waveCorrect(vector<Mat> &rmats)
|
|||||||
normalize(r0, r0);
|
normalize(r0, r0);
|
||||||
|
|
||||||
r1.cross(r0).copyTo(r2);
|
r1.cross(r0).copyTo(r2);
|
||||||
if (determinant(R) < 0)
|
if (determinant(R) < 0) R *= -1;
|
||||||
R *= -1;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < rmats.size(); ++i)
|
for (size_t i = 0; i < rmats.size(); ++i)
|
||||||
rmats[i] = R * rmats[i];
|
rmats[i] = R * rmats[i];
|
||||||
@@ -348,8 +346,8 @@ void waveCorrect(vector<Mat> &rmats)
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features,
|
vector<int> leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features,
|
||||||
vector<MatchesInfo> &pairwise_matches, float conf_threshold)
|
vector<MatchesInfo> &pairwise_matches, float conf_threshold)
|
||||||
{
|
{
|
||||||
const int num_images = static_cast<int>(images.size());
|
const int num_images = static_cast<int>(images.size());
|
||||||
|
|
||||||
@@ -393,7 +391,7 @@ void leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (static_cast<int>(images_subset.size()) == num_images)
|
if (static_cast<int>(images_subset.size()) == num_images)
|
||||||
return;
|
return indices;
|
||||||
|
|
||||||
LOG("Removed some images, because can't match them: (");
|
LOG("Removed some images, because can't match them: (");
|
||||||
LOG(indices_removed[0]);
|
LOG(indices_removed[0]);
|
||||||
@@ -403,6 +401,8 @@ void leaveBiggestComponent(vector<Mat> &images, vector<ImageFeatures> &features,
|
|||||||
images = images_subset;
|
images = images_subset;
|
||||||
features = features_subset;
|
features = features_subset;
|
||||||
pairwise_matches = pairwise_matches_subset;
|
pairwise_matches = pairwise_matches_subset;
|
||||||
|
|
||||||
|
return indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -83,8 +83,8 @@ void waveCorrect(std::vector<cv::Mat> &rmats);
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Auxiliary functions
|
// Auxiliary functions
|
||||||
|
|
||||||
void leaveBiggestComponent(std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features,
|
std::vector<int> leaveBiggestComponent(std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features,
|
||||||
std::vector<MatchesInfo> &pairwise_matches, float conf_threshold);
|
std::vector<MatchesInfo> &pairwise_matches, float conf_threshold);
|
||||||
|
|
||||||
void findMaxSpanningTree(int num_images, const std::vector<MatchesInfo> &pairwise_matches,
|
void findMaxSpanningTree(int num_images, const std::vector<MatchesInfo> &pairwise_matches,
|
||||||
Graph &span_tree, std::vector<int> ¢ers);
|
Graph &span_tree, std::vector<int> ¢ers);
|
||||||
|
Reference in New Issue
Block a user