refactored opencv_stitching, added possibility to turn off BA

This commit is contained in:
Alexey Spizhevoy 2011-08-15 12:20:27 +00:00
parent 6e3a1f7b49
commit b97ecdff0d
6 changed files with 44 additions and 29 deletions

View File

@ -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__

View File

@ -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]);
}
}
}
}

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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) {}

View File

@ -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");
}