Commit 767a6e8e authored by Alexey Spizhevoy's avatar Alexey Spizhevoy

added histograms comparison into opencv_stitching

parent 63ac784e
...@@ -56,7 +56,7 @@ double estimateFocal(const vector<Mat> &images, const vector<ImageFeatures> &/*f ...@@ -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() ...@@ -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[]) ...@@ -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";
......
#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; ...@@ -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 ...@@ -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 ...@@ -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);
} }
} }
} }
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
#include <opencv2/features2d/features2d.hpp> #include <opencv2/features2d/features2d.hpp>
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 ...@@ -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,9 +27,9 @@ protected: ...@@ -26,9 +27,9 @@ 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);
protected: protected:
void find(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features); void find(const std::vector<cv::Mat> &images, std::vector<ImageFeatures> &features);
...@@ -70,7 +71,7 @@ protected: ...@@ -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 ...@@ -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);
...@@ -142,7 +142,7 @@ void BundleAdjuster::estimate(const vector<Mat> &images, const vector<ImageFeatu ...@@ -142,7 +142,7 @@ void BundleAdjuster::estimate(const vector<Mat> &images, const vector<ImageFeatu
CvMat* _J = 0; CvMat* _J = 0;
CvMat* _err = 0; CvMat* _err = 0;
bool proceed = solver.update( _param, _J, _err ); bool proceed = solver.update(_param, _J, _err);
cvCopy( _param, &matParams ); cvCopy( _param, &matParams );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment