added histograms comparison into opencv_stitching
This commit is contained in:
parent
63ac784ea0
commit
767a6e8e78
@ -56,7 +56,7 @@ double estimateFocal(const vector<Mat> &images, const vector<ImageFeatures> &/*f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focals.size() >= 2 * (num_images - 1))
|
if (static_cast<int>(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];
|
||||||
|
@ -26,6 +26,9 @@ void printUsage()
|
|||||||
<< "\t[--output <result_img>]\n\n";
|
<< "\t[--output <result_img>]\n\n";
|
||||||
cout << "--matchconf\n"
|
cout << "--matchconf\n"
|
||||||
<< "\tGood values are in [0.2, 0.8] range usually.\n\n";
|
<< "\tGood values are in [0.2, 0.8] range usually.\n\n";
|
||||||
|
cout << "HINT:\n"
|
||||||
|
<< "\tDefault parameters are for '--trygpu no' configuration.\n"
|
||||||
|
<< "\tTry bigger values for --work_megapix if something is wrong.\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
@ -35,15 +38,17 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
vector<string> img_names;
|
vector<string> img_names;
|
||||||
vector<Mat> images;
|
vector<Mat> images;
|
||||||
bool trygpu = true;
|
|
||||||
double work_megapix = 1;
|
// Default parameters
|
||||||
|
bool trygpu = false;
|
||||||
|
double work_megapix = 0.2;
|
||||||
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;
|
||||||
int warp_type = Warper::SPHERICAL;
|
int warp_type = Warper::SPHERICAL;
|
||||||
bool user_match_conf = false;
|
bool user_match_conf = false;
|
||||||
float match_conf = 0.55f;
|
float match_conf = 0.6f;
|
||||||
int seam_find_type = SeamFinder::VORONOI;
|
int seam_find_type = SeamFinder::VORONOI;
|
||||||
int blend_type = Blender::MULTI_BAND;
|
int blend_type = Blender::MULTI_BAND;
|
||||||
string result_name = "result.png";
|
string result_name = "result.png";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
#include <opencv2/calib3d/calib3d.hpp>
|
#include <opencv2/calib3d/calib3d.hpp>
|
||||||
#include <opencv2/gpu/gpu.hpp>
|
#include <opencv2/gpu/gpu.hpp>
|
||||||
#include "matchers.hpp"
|
#include "matchers.hpp"
|
||||||
@ -9,6 +10,31 @@ using namespace std;
|
|||||||
using namespace cv;
|
using namespace cv;
|
||||||
using namespace cv::gpu;
|
using namespace cv::gpu;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FeaturesFinder::operator ()(const vector<Mat> &images, vector<ImageFeatures> &features)
|
||||||
|
{
|
||||||
|
features.resize(images.size());
|
||||||
|
|
||||||
|
// Calculate histograms
|
||||||
|
for (size_t i = 0; i < images.size(); ++i)
|
||||||
|
{
|
||||||
|
Mat hsv;
|
||||||
|
cvtColor(images[i], hsv, CV_BGR2HSV);
|
||||||
|
int hbins = 30, sbins = 32, vbins = 30;
|
||||||
|
int hist_size[] = { hbins, sbins, vbins };
|
||||||
|
float hranges[] = { 0, 180 };
|
||||||
|
float sranges[] = { 0, 256 };
|
||||||
|
float vranges[] = { 0, 256 };
|
||||||
|
const float* ranges[] = { hranges, sranges, vranges };
|
||||||
|
int channels[] = { 0, 1, 2 };
|
||||||
|
calcHist(&hsv, 1, channels, Mat(), features[i].hist, 3, hist_size, ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
find(images, features);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -19,7 +45,7 @@ namespace
|
|||||||
inline CpuSurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers,
|
inline CpuSurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers,
|
||||||
int num_octaves_descr, int num_layers_descr)
|
int num_octaves_descr, int num_layers_descr)
|
||||||
{
|
{
|
||||||
detector_ = new /*FastFeatureDetector;*/SurfFeatureDetector(hess_thresh, num_octaves, num_layers);
|
detector_ = new SurfFeatureDetector(hess_thresh, num_octaves, num_layers);
|
||||||
extractor_ = new SurfDescriptorExtractor(num_octaves_descr, num_layers_descr);
|
extractor_ = new SurfDescriptorExtractor(num_octaves_descr, num_layers_descr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,14 +175,32 @@ void FeaturesMatcher::operator ()(const vector<Mat> &images, const vector<ImageF
|
|||||||
for (size_t i = 0; i < images.size(); ++i)
|
for (size_t i = 0; i < images.size(); ++i)
|
||||||
{
|
{
|
||||||
LOGLN("Processing image " << i << "... ");
|
LOGLN("Processing image " << i << "... ");
|
||||||
for (size_t j = 0; j < images.size(); ++j)
|
for (size_t j = i + 1; j < images.size(); ++j)
|
||||||
{
|
{
|
||||||
if (i == j)
|
// Save time by ignoring poor pairs
|
||||||
|
if (compareHist(features[i].hist, features[j].hist, CV_COMP_INTERSECT)
|
||||||
|
< min(images[i].size().area(), images[j].size().area()) * 0.4)
|
||||||
|
{
|
||||||
|
//LOGLN("Ignoring (" << i << ", " << j << ") pair...");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
size_t pair_idx = i * images.size() + j;
|
size_t pair_idx = i * images.size() + j;
|
||||||
|
|
||||||
(*this)(images[i], features[i], images[j], features[j], pairwise_matches[pair_idx]);
|
(*this)(images[i], features[i], images[j], features[j], pairwise_matches[pair_idx]);
|
||||||
pairwise_matches[pair_idx].src_img_idx = i;
|
pairwise_matches[pair_idx].src_img_idx = i;
|
||||||
pairwise_matches[pair_idx].dst_img_idx = j;
|
pairwise_matches[pair_idx].dst_img_idx = j;
|
||||||
|
|
||||||
|
// Set up dual pair matches info
|
||||||
|
size_t dual_pair_idx = j * images.size() + i;
|
||||||
|
pairwise_matches[dual_pair_idx] = pairwise_matches[pair_idx];
|
||||||
|
pairwise_matches[dual_pair_idx].src_img_idx = j;
|
||||||
|
pairwise_matches[dual_pair_idx].dst_img_idx = i;
|
||||||
|
if (!pairwise_matches[pair_idx].H.empty())
|
||||||
|
pairwise_matches[dual_pair_idx].H = pairwise_matches[pair_idx].H.inv();
|
||||||
|
for (size_t i = 0; i < pairwise_matches[dual_pair_idx].matches.size(); ++i)
|
||||||
|
swap(pairwise_matches[dual_pair_idx].matches[i].queryIdx,
|
||||||
|
pairwise_matches[dual_pair_idx].matches[i].trainIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
struct ImageFeatures
|
struct ImageFeatures
|
||||||
{
|
{
|
||||||
|
cv::Mat hist;
|
||||||
std::vector<cv::KeyPoint> keypoints;
|
std::vector<cv::KeyPoint> keypoints;
|
||||||
cv::Mat descriptors;
|
cv::Mat descriptors;
|
||||||
};
|
};
|
||||||
@ -16,7 +17,7 @@ class FeaturesFinder
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~FeaturesFinder() {}
|
virtual ~FeaturesFinder() {}
|
||||||
void operator ()(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features) { find(images, features); }
|
void operator ()(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void find(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features) = 0;
|
virtual void find(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features) = 0;
|
||||||
@ -26,7 +27,7 @@ protected:
|
|||||||
class SurfFeaturesFinder : public FeaturesFinder
|
class SurfFeaturesFinder : public FeaturesFinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SurfFeaturesFinder(bool try_use_gpu = true, double hess_thresh = 500.0,
|
SurfFeaturesFinder(bool try_use_gpu = true, double hess_thresh = 300.0,
|
||||||
int num_octaves = 3, int num_layers = 4,
|
int num_octaves = 3, int num_layers = 4,
|
||||||
int num_octaves_descr = 4, int num_layers_descr = 2);
|
int num_octaves_descr = 4, int num_layers_descr = 2);
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ protected:
|
|||||||
class BestOf2NearestMatcher : public FeaturesMatcher
|
class BestOf2NearestMatcher : public FeaturesMatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit BestOf2NearestMatcher(bool try_use_gpu = true, float match_conf = 0.55f, int num_matches_thresh1 = 5, int num_matches_thresh2 = 5);
|
BestOf2NearestMatcher(bool try_use_gpu = true, float match_conf = 0.55f, int num_matches_thresh1 = 6, int num_matches_thresh2 = 6);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void match(const cv::Mat &img1, const ImageFeatures &features1, const cv::Mat &img2, const ImageFeatures &features2,
|
void match(const cv::Mat &img1, const ImageFeatures &features1, const cv::Mat &img2, const ImageFeatures &features2,
|
||||||
|
@ -130,7 +130,7 @@ void BundleAdjuster::estimate(const vector<Mat> &images, const vector<ImageFeatu
|
|||||||
total_num_matches_ += static_cast<int>(pairwise_matches[edges_[i].first * num_images_ + edges_[i].second].num_inliers);
|
total_num_matches_ += static_cast<int>(pairwise_matches[edges_[i].first * num_images_ + edges_[i].second].num_inliers);
|
||||||
|
|
||||||
CvLevMarq solver(num_images_ * 4, total_num_matches_ * 3,
|
CvLevMarq solver(num_images_ * 4, total_num_matches_ * 3,
|
||||||
cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 100, DBL_EPSILON));
|
cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 1000, DBL_EPSILON));
|
||||||
|
|
||||||
CvMat matParams = cameras_;
|
CvMat matParams = cameras_;
|
||||||
cvCopy(&matParams, solver.param);
|
cvCopy(&matParams, solver.param);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user