refactored opencv_stitching, added possibility to turn off BA
This commit is contained in:
parent
6e3a1f7b49
commit
b97ecdff0d
@ -114,7 +114,7 @@ void createLaplacePyr(const cv::Mat &img, int num_levels, std::vector<cv::Mat>&
|
|||||||
void createLaplacePyrGpu(const cv::Mat &img, int num_levels, std::vector<cv::Mat>& pyr);
|
void createLaplacePyrGpu(const cv::Mat &img, int num_levels, std::vector<cv::Mat>& pyr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Restores source image in-place (result will be stored in pyr[0])
|
// Restores source image
|
||||||
void restoreImageFromLaplacePyr(std::vector<cv::Mat>& pyr);
|
void restoreImageFromLaplacePyr(std::vector<cv::Mat>& pyr);
|
||||||
|
|
||||||
#endif // __OPENCV_BLENDERS_HPP__
|
#endif // __OPENCV_BLENDERS_HPP__
|
||||||
|
@ -74,6 +74,9 @@ void ExposureCompensator::feed(const vector<Point> &corners, const vector<Mat> &
|
|||||||
void GainCompensator::feed(const vector<Point> &corners, const vector<Mat> &images,
|
void GainCompensator::feed(const vector<Point> &corners, const vector<Mat> &images,
|
||||||
const vector<pair<Mat,uchar> > &masks)
|
const vector<pair<Mat,uchar> > &masks)
|
||||||
{
|
{
|
||||||
|
LOGLN("Exposure compensation...");
|
||||||
|
int64 t = getTickCount();
|
||||||
|
|
||||||
CV_Assert(corners.size() == images.size() && images.size() == masks.size());
|
CV_Assert(corners.size() == images.size() && images.size() == masks.size());
|
||||||
|
|
||||||
const int num_images = static_cast<int>(images.size());
|
const int num_images = static_cast<int>(images.size());
|
||||||
@ -138,6 +141,8 @@ void GainCompensator::feed(const vector<Point> &corners, const vector<Mat> &imag
|
|||||||
}
|
}
|
||||||
|
|
||||||
solve(A, b, gains_);
|
solve(A, b, gains_);
|
||||||
|
|
||||||
|
LOGLN("Exposure compensation, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ void printUsage()
|
|||||||
" --conf_thresh <float>\n"
|
" --conf_thresh <float>\n"
|
||||||
" Threshold for two images are from the same panorama confidence.\n"
|
" Threshold for two images are from the same panorama confidence.\n"
|
||||||
" The default is 1.0.\n"
|
" The default is 1.0.\n"
|
||||||
" --ba (ray|focal_ray)\n"
|
" --ba (no|ray|focal_ray)\n"
|
||||||
" Bundle adjustment cost function. The default is 'focal_ray'.\n"
|
" Bundle adjustment cost function. The default is 'focal_ray'.\n"
|
||||||
" --wave_correct (no|yes)\n"
|
" --wave_correct (no|yes)\n"
|
||||||
" Perform wave effect correction. The default is 'yes'.\n"
|
" Perform wave effect correction. The default is 'yes'.\n"
|
||||||
@ -187,7 +187,9 @@ int parseCmdArgs(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else if (string(argv[i]) == "--ba")
|
else if (string(argv[i]) == "--ba")
|
||||||
{
|
{
|
||||||
if (string(argv[i + 1]) == "ray")
|
if (string(argv[i + 1]) == "no")
|
||||||
|
ba_space = BundleAdjuster::NO;
|
||||||
|
else if (string(argv[i + 1]) == "ray")
|
||||||
ba_space = BundleAdjuster::RAY_SPACE;
|
ba_space = BundleAdjuster::RAY_SPACE;
|
||||||
else if (string(argv[i + 1]) == "focal_ray")
|
else if (string(argv[i + 1]) == "focal_ray")
|
||||||
ba_space = BundleAdjuster::FOCAL_RAY_SPACE;
|
ba_space = BundleAdjuster::FOCAL_RAY_SPACE;
|
||||||
@ -423,12 +425,9 @@ int main(int argc, char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGLN("Estimating rotations...");
|
|
||||||
t = getTickCount();
|
|
||||||
HomographyBasedEstimator estimator;
|
HomographyBasedEstimator estimator;
|
||||||
vector<CameraParams> cameras;
|
vector<CameraParams> cameras;
|
||||||
estimator(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)
|
for (size_t i = 0; i < cameras.size(); ++i)
|
||||||
{
|
{
|
||||||
@ -438,11 +437,8 @@ int main(int argc, char* argv[])
|
|||||||
LOGLN("Initial focal length #" << indices[i]+1 << ": " << cameras[i].focal);
|
LOGLN("Initial focal length #" << indices[i]+1 << ": " << cameras[i].focal);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("Bundle adjustment");
|
|
||||||
t = getTickCount();
|
|
||||||
BundleAdjuster adjuster(ba_space, conf_thresh);
|
BundleAdjuster adjuster(ba_space, conf_thresh);
|
||||||
adjuster(features, pairwise_matches, cameras);
|
adjuster(features, pairwise_matches, cameras);
|
||||||
LOGLN("Bundle adjustment, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
|
||||||
|
|
||||||
// Find median focal length
|
// Find median focal length
|
||||||
vector<double> focals;
|
vector<double> focals;
|
||||||
@ -456,15 +452,12 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (wave_correct)
|
if (wave_correct)
|
||||||
{
|
{
|
||||||
LOGLN("Wave correcting...");
|
|
||||||
t = getTickCount();
|
|
||||||
vector<Mat> rmats;
|
vector<Mat> rmats;
|
||||||
for (size_t i = 0; i < cameras.size(); ++i)
|
for (size_t i = 0; i < cameras.size(); ++i)
|
||||||
rmats.push_back(cameras[i].R);
|
rmats.push_back(cameras[i].R);
|
||||||
waveCorrect(rmats);
|
waveCorrect(rmats);
|
||||||
for (size_t i = 0; i < cameras.size(); ++i)
|
for (size_t i = 0; i < cameras.size(); ++i)
|
||||||
cameras[i].R = rmats[i];
|
cameras[i].R = rmats[i];
|
||||||
LOGLN("Wave correcting, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGLN("Warping images (auxiliary)... ");
|
LOGLN("Warping images (auxiliary)... ");
|
||||||
@ -501,17 +494,11 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
LOGLN("Warping images, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
LOGLN("Warping images, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
|
|
||||||
LOGLN("Exposure compensation (feed)...");
|
|
||||||
t = getTickCount();
|
|
||||||
Ptr<ExposureCompensator> compensator = ExposureCompensator::createDefault(expos_comp_type);
|
Ptr<ExposureCompensator> compensator = ExposureCompensator::createDefault(expos_comp_type);
|
||||||
compensator->feed(corners, images_warped, masks_warped);
|
compensator->feed(corners, images_warped, masks_warped);
|
||||||
LOGLN("Exposure compensation (feed), time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
|
||||||
|
|
||||||
LOGLN("Finding seams...");
|
|
||||||
t = getTickCount();
|
|
||||||
Ptr<SeamFinder> seam_finder = SeamFinder::createDefault(seam_find_type);
|
Ptr<SeamFinder> seam_finder = SeamFinder::createDefault(seam_find_type);
|
||||||
seam_finder->find(images_warped_f, corners, masks_warped);
|
seam_finder->find(images_warped_f, corners, masks_warped);
|
||||||
LOGLN("Finding seams, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
|
||||||
|
|
||||||
// Release unused memory
|
// Release unused memory
|
||||||
images.clear();
|
images.clear();
|
||||||
@ -612,7 +599,7 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
FeatherBlender* fb = dynamic_cast<FeatherBlender*>(static_cast<Blender*>(blender));
|
FeatherBlender* fb = dynamic_cast<FeatherBlender*>(static_cast<Blender*>(blender));
|
||||||
fb->setSharpness(1.f/blend_width);
|
fb->setSharpness(1.f/blend_width);
|
||||||
LOGLN("Feather blender, number of bands: " << fb->sharpness());
|
LOGLN("Feather blender, sharpness: " << fb->sharpness());
|
||||||
}
|
}
|
||||||
blender->prepare(corners, sizes);
|
blender->prepare(corners, sizes);
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,9 @@ struct CalcRotation
|
|||||||
void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches,
|
void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches,
|
||||||
vector<CameraParams> &cameras)
|
vector<CameraParams> &cameras)
|
||||||
{
|
{
|
||||||
|
LOGLN("Estimating rotations...");
|
||||||
|
int64 t = getTickCount();
|
||||||
|
|
||||||
const int num_images = static_cast<int>(features.size());
|
const int num_images = static_cast<int>(features.size());
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -142,6 +145,8 @@ void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, c
|
|||||||
vector<int> span_tree_centers;
|
vector<int> span_tree_centers;
|
||||||
findMaxSpanningTree(num_images, pairwise_matches, span_tree, span_tree_centers);
|
findMaxSpanningTree(num_images, pairwise_matches, span_tree, span_tree_centers);
|
||||||
span_tree.walkBreadthFirst(span_tree_centers[0], CalcRotation(num_images, pairwise_matches, cameras));
|
span_tree.walkBreadthFirst(span_tree_centers[0], CalcRotation(num_images, pairwise_matches, cameras));
|
||||||
|
|
||||||
|
LOGLN("Estimating rotations, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -150,6 +155,12 @@ void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, c
|
|||||||
void BundleAdjuster::estimate(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches,
|
void BundleAdjuster::estimate(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches,
|
||||||
vector<CameraParams> &cameras)
|
vector<CameraParams> &cameras)
|
||||||
{
|
{
|
||||||
|
if (cost_space_ == NO)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG("Bundle adjustment");
|
||||||
|
int64 t = getTickCount();
|
||||||
|
|
||||||
num_images_ = static_cast<int>(features.size());
|
num_images_ = static_cast<int>(features.size());
|
||||||
features_ = &features[0];
|
features_ = &features[0];
|
||||||
pairwise_matches_ = &pairwise_matches[0];
|
pairwise_matches_ = &pairwise_matches[0];
|
||||||
@ -251,6 +262,8 @@ void BundleAdjuster::estimate(const vector<ImageFeatures> &features, const vecto
|
|||||||
Mat R_inv = cameras[span_tree_centers[0]].R.inv();
|
Mat R_inv = cameras[span_tree_centers[0]].R.inv();
|
||||||
for (int i = 0; i < num_images_; ++i)
|
for (int i = 0; i < num_images_; ++i)
|
||||||
cameras[i].R = R_inv * cameras[i].R;
|
cameras[i].R = R_inv * cameras[i].R;
|
||||||
|
|
||||||
|
LOGLN("Bundle adjustment, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -306,7 +319,7 @@ void BundleAdjuster::calcError(Mat &err)
|
|||||||
p2.x * R2[3] + p2.y * R2[4] + p2.z * R2[5],
|
p2.x * R2[3] + p2.y * R2[4] + p2.z * R2[5],
|
||||||
p2.x * R2[6] + p2.y * R2[7] + p2.z * R2[8]);
|
p2.x * R2[6] + p2.y * R2[7] + p2.z * R2[8]);
|
||||||
|
|
||||||
double mult = 1;
|
double mult = 1; // For cost_space_ == RAY_SPACE
|
||||||
if (cost_space_ == FOCAL_RAY_SPACE)
|
if (cost_space_ == FOCAL_RAY_SPACE)
|
||||||
mult = sqrt(f1 * f2);
|
mult = sqrt(f1 * f2);
|
||||||
err.at<double>(3 * match_idx, 0) = mult * (d1.x - d2.x);
|
err.at<double>(3 * match_idx, 0) = mult * (d1.x - d2.x);
|
||||||
@ -374,6 +387,9 @@ void BundleAdjuster::calcJacobian()
|
|||||||
|
|
||||||
void waveCorrect(vector<Mat> &rmats)
|
void waveCorrect(vector<Mat> &rmats)
|
||||||
{
|
{
|
||||||
|
LOGLN("Wave correcting...");
|
||||||
|
int64 t = getTickCount();
|
||||||
|
|
||||||
float data[9];
|
float data[9];
|
||||||
Mat r0(1, 3, CV_32F, data);
|
Mat r0(1, 3, CV_32F, data);
|
||||||
Mat r1(1, 3, CV_32F, data + 3);
|
Mat r1(1, 3, CV_32F, data + 3);
|
||||||
@ -403,6 +419,8 @@ void waveCorrect(vector<Mat> &rmats)
|
|||||||
|
|
||||||
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];
|
||||||
|
|
||||||
|
LOGLN("Wave correcting, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ private:
|
|||||||
class BundleAdjuster : public Estimator
|
class BundleAdjuster : public Estimator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum { RAY_SPACE, FOCAL_RAY_SPACE };
|
enum { NO, RAY_SPACE, FOCAL_RAY_SPACE };
|
||||||
|
|
||||||
BundleAdjuster(int cost_space = FOCAL_RAY_SPACE, float conf_thresh = 1.f)
|
BundleAdjuster(int cost_space = FOCAL_RAY_SPACE, float conf_thresh = 1.f)
|
||||||
: cost_space_(cost_space), conf_thresh_(conf_thresh) {}
|
: cost_space_(cost_space), conf_thresh_(conf_thresh) {}
|
||||||
|
@ -64,6 +64,9 @@ Ptr<SeamFinder> SeamFinder::createDefault(int type)
|
|||||||
void PairwiseSeamFinder::find(const vector<Mat> &src, const vector<Point> &corners,
|
void PairwiseSeamFinder::find(const vector<Mat> &src, const vector<Point> &corners,
|
||||||
vector<Mat> &masks)
|
vector<Mat> &masks)
|
||||||
{
|
{
|
||||||
|
LOGLN("Finding seams...");
|
||||||
|
int64 t = getTickCount();
|
||||||
|
|
||||||
if (src.size() == 0)
|
if (src.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -80,6 +83,8 @@ void PairwiseSeamFinder::find(const vector<Mat> &src, const vector<Point> &corne
|
|||||||
findInPair(i, j, roi);
|
findInPair(i, j, roi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGLN("Finding seams, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user