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);
|
||||
#endif
|
||||
|
||||
// Restores source image in-place (result will be stored in pyr[0])
|
||||
// Restores source image
|
||||
void restoreImageFromLaplacePyr(std::vector<cv::Mat>& pyr);
|
||||
|
||||
#endif // __OPENCV_BLENDERS_HPP__
|
||||
|
@ -50,13 +50,13 @@ using namespace cv::gpu;
|
||||
|
||||
Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type)
|
||||
{
|
||||
if (type == NO)
|
||||
return new NoExposureCompensator();
|
||||
if (type == GAIN)
|
||||
return new GainCompensator();
|
||||
if (type == GAIN_BLOCKS)
|
||||
return new BlocksGainCompensator();
|
||||
CV_Error(CV_StsBadArg, "unsupported exposure compensation method");
|
||||
if (type == NO)
|
||||
return new NoExposureCompensator();
|
||||
if (type == GAIN)
|
||||
return new GainCompensator();
|
||||
if (type == GAIN_BLOCKS)
|
||||
return new BlocksGainCompensator();
|
||||
CV_Error(CV_StsBadArg, "unsupported exposure compensation method");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
const vector<pair<Mat,uchar> > &masks)
|
||||
{
|
||||
LOGLN("Exposure compensation...");
|
||||
int64 t = getTickCount();
|
||||
|
||||
CV_Assert(corners.size() == images.size() && images.size() == masks.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_);
|
||||
|
||||
LOGLN("Exposure compensation, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
}
|
||||
|
||||
|
||||
@ -237,4 +242,4 @@ void BlocksGainCompensator::apply(int index, Point /*corner*/, Mat &image, const
|
||||
row[x].z = saturate_cast<uchar>(row[x].z * gain_row[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ void printUsage()
|
||||
" --conf_thresh <float>\n"
|
||||
" Threshold for two images are from the same panorama confidence.\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"
|
||||
" --wave_correct (no|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")
|
||||
{
|
||||
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;
|
||||
else if (string(argv[i + 1]) == "focal_ray")
|
||||
ba_space = BundleAdjuster::FOCAL_RAY_SPACE;
|
||||
@ -423,12 +425,9 @@ int main(int argc, char* argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGLN("Estimating rotations...");
|
||||
t = getTickCount();
|
||||
HomographyBasedEstimator estimator;
|
||||
vector<CameraParams> cameras;
|
||||
estimator(features, pairwise_matches, cameras);
|
||||
LOGLN("Estimating rotations, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
LOG("Bundle adjustment");
|
||||
t = getTickCount();
|
||||
BundleAdjuster adjuster(ba_space, conf_thresh);
|
||||
adjuster(features, pairwise_matches, cameras);
|
||||
LOGLN("Bundle adjustment, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
|
||||
// Find median focal length
|
||||
vector<double> focals;
|
||||
@ -456,15 +452,12 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (wave_correct)
|
||||
{
|
||||
LOGLN("Wave correcting...");
|
||||
t = getTickCount();
|
||||
vector<Mat> rmats;
|
||||
for (size_t i = 0; i < cameras.size(); ++i)
|
||||
rmats.push_back(cameras[i].R);
|
||||
waveCorrect(rmats);
|
||||
for (size_t i = 0; i < cameras.size(); ++i)
|
||||
cameras[i].R = rmats[i];
|
||||
LOGLN("Wave correcting, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
}
|
||||
|
||||
LOGLN("Warping images (auxiliary)... ");
|
||||
@ -501,17 +494,11 @@ int main(int argc, char* argv[])
|
||||
|
||||
LOGLN("Warping images, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
|
||||
LOGLN("Exposure compensation (feed)...");
|
||||
t = getTickCount();
|
||||
Ptr<ExposureCompensator> compensator = ExposureCompensator::createDefault(expos_comp_type);
|
||||
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);
|
||||
seam_finder->find(images_warped_f, corners, masks_warped);
|
||||
LOGLN("Finding seams, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
|
||||
// Release unused memory
|
||||
images.clear();
|
||||
@ -612,7 +599,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
FeatherBlender* fb = dynamic_cast<FeatherBlender*>(static_cast<Blender*>(blender));
|
||||
fb->setSharpness(1.f/blend_width);
|
||||
LOGLN("Feather blender, number of bands: " << fb->sharpness());
|
||||
LOGLN("Feather blender, sharpness: " << fb->sharpness());
|
||||
}
|
||||
blender->prepare(corners, sizes);
|
||||
}
|
||||
|
@ -107,6 +107,9 @@ struct CalcRotation
|
||||
void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, const vector<MatchesInfo> &pairwise_matches,
|
||||
vector<CameraParams> &cameras)
|
||||
{
|
||||
LOGLN("Estimating rotations...");
|
||||
int64 t = getTickCount();
|
||||
|
||||
const int num_images = static_cast<int>(features.size());
|
||||
|
||||
#if 0
|
||||
@ -142,6 +145,8 @@ void HomographyBasedEstimator::estimate(const vector<ImageFeatures> &features, c
|
||||
vector<int> 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));
|
||||
|
||||
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,
|
||||
vector<CameraParams> &cameras)
|
||||
{
|
||||
if (cost_space_ == NO)
|
||||
return;
|
||||
|
||||
LOG("Bundle adjustment");
|
||||
int64 t = getTickCount();
|
||||
|
||||
num_images_ = static_cast<int>(features.size());
|
||||
features_ = &features[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();
|
||||
for (int i = 0; i < num_images_; ++i)
|
||||
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[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)
|
||||
mult = sqrt(f1 * f2);
|
||||
err.at<double>(3 * match_idx, 0) = mult * (d1.x - d2.x);
|
||||
@ -374,6 +387,9 @@ void BundleAdjuster::calcJacobian()
|
||||
|
||||
void waveCorrect(vector<Mat> &rmats)
|
||||
{
|
||||
LOGLN("Wave correcting...");
|
||||
int64 t = getTickCount();
|
||||
|
||||
float data[9];
|
||||
Mat r0(1, 3, CV_32F, data);
|
||||
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)
|
||||
rmats[i] = R * rmats[i];
|
||||
|
||||
LOGLN("Wave correcting, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,7 +90,7 @@ private:
|
||||
class BundleAdjuster : public Estimator
|
||||
{
|
||||
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)
|
||||
: 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,
|
||||
vector<Mat> &masks)
|
||||
{
|
||||
LOGLN("Finding seams...");
|
||||
int64 t = getTickCount();
|
||||
|
||||
if (src.size() == 0)
|
||||
return;
|
||||
|
||||
@ -80,6 +83,8 @@ void PairwiseSeamFinder::find(const vector<Mat> &src, const vector<Point> &corne
|
||||
findInPair(i, j, roi);
|
||||
}
|
||||
}
|
||||
|
||||
LOGLN("Finding seams, time: " << ((getTickCount() - t) / getTickFrequency()) << " sec");
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user