Commit 56f7e54c authored by Alexey Spizhevoy's avatar Alexey Spizhevoy

added GC_COLOR_GRAD cost function type into opencv_stitching

parent 8e377767
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
using namespace std; using namespace std;
using namespace cv; using namespace cv;
using namespace cv::gpu;
Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type) Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type)
...@@ -53,6 +54,8 @@ Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type) ...@@ -53,6 +54,8 @@ Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type)
return new NoExposureCompensator(); return new NoExposureCompensator();
if (type == OVERLAP) if (type == OVERLAP)
return new OverlapExposureCompensator(); return new OverlapExposureCompensator();
if (type == SEGMENT)
return new SegmentExposureCompensator();
CV_Error(CV_StsBadArg, "unsupported exposure compensation method"); CV_Error(CV_StsBadArg, "unsupported exposure compensation method");
return NULL; return NULL;
} }
...@@ -61,13 +64,15 @@ Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type) ...@@ -61,13 +64,15 @@ Ptr<ExposureCompensator> ExposureCompensator::createDefault(int type)
void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector<Mat> &images, void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector<Mat> &images,
const vector<Mat> &masks) const vector<Mat> &masks)
{ {
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());
Mat_<int> N(num_images, num_images); N.setTo(0); Mat_<int> N(num_images, num_images); N.setTo(0);
Mat_<double> I(num_images, num_images); I.setTo(0); Mat_<double> I(num_images, num_images); I.setTo(0);
Rect dst_roi = resultRoi(corners, images); Rect dst_roi = resultRoi(corners, images);
Mat subimg1, subimg2; Mat subimg1, subimg2;
Mat_<uchar> submask1, submask2, overlap; Mat_<uchar> submask1, submask2, intersect;
for (int i = 0; i < num_images; ++i) for (int i = 0; i < num_images; ++i)
{ {
...@@ -81,9 +86,9 @@ void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector ...@@ -81,9 +86,9 @@ void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector
submask1 = masks[i](Rect(roi.tl() - corners[i], roi.br() - corners[i])); submask1 = masks[i](Rect(roi.tl() - corners[i], roi.br() - corners[i]));
submask2 = masks[j](Rect(roi.tl() - corners[j], roi.br() - corners[j])); submask2 = masks[j](Rect(roi.tl() - corners[j], roi.br() - corners[j]));
overlap = submask1 & submask2; intersect = submask1 & submask2;
N(i, j) = N(j, i) = countNonZero(overlap); N(i, j) = N(j, i) = countNonZero(intersect);
double Isum1 = 0, Isum2 = 0; double Isum1 = 0, Isum2 = 0;
for (int y = 0; y < roi.height; ++y) for (int y = 0; y < roi.height; ++y)
...@@ -92,7 +97,7 @@ void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector ...@@ -92,7 +97,7 @@ void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector
const Point3_<uchar>* r2 = subimg2.ptr<Point3_<uchar> >(y); const Point3_<uchar>* r2 = subimg2.ptr<Point3_<uchar> >(y);
for (int x = 0; x < roi.width; ++x) for (int x = 0; x < roi.width; ++x)
{ {
if (overlap(y, x)) if (intersect(y, x))
{ {
Isum1 += sqrt(static_cast<double>(sqr(r1[x].x) + sqr(r1[x].y) + sqr(r1[x].z))); Isum1 += sqrt(static_cast<double>(sqr(r1[x].x) + sqr(r1[x].y) + sqr(r1[x].z)));
Isum2 += sqrt(static_cast<double>(sqr(r2[x].x) + sqr(r2[x].y) + sqr(r2[x].z))); Isum2 += sqrt(static_cast<double>(sqr(r2[x].x) + sqr(r2[x].y) + sqr(r2[x].z)));
...@@ -122,7 +127,7 @@ void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector ...@@ -122,7 +127,7 @@ void OverlapExposureCompensator::feed(const vector<Point> &corners, const vector
} }
} }
solve(A, b, gains_, DECOMP_SVD); solve(A, b, gains_);
} }
...@@ -130,3 +135,14 @@ void OverlapExposureCompensator::apply(int index, Point /*corner*/, Mat &image, ...@@ -130,3 +135,14 @@ void OverlapExposureCompensator::apply(int index, Point /*corner*/, Mat &image,
{ {
image *= gains_(index, 0); image *= gains_(index, 0);
} }
void SegmentExposureCompensator::feed(const vector<Point> &/*corners*/, const vector<Mat> &/*images*/,
const vector<Mat> &/*masks*/)
{
}
void SegmentExposureCompensator::apply(int /*index*/, Point /*corner*/, Mat &/*image*/, const Mat &/*mask*/)
{
}
\ No newline at end of file
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
class ExposureCompensator class ExposureCompensator
{ {
public: public:
enum { NO, OVERLAP }; enum { NO, OVERLAP, SEGMENT };
static cv::Ptr<ExposureCompensator> createDefault(int type); static cv::Ptr<ExposureCompensator> createDefault(int type);
virtual void feed(const std::vector<cv::Point> &corners, const std::vector<cv::Mat> &images, virtual void feed(const std::vector<cv::Point> &corners, const std::vector<cv::Mat> &images,
...@@ -78,4 +78,12 @@ private: ...@@ -78,4 +78,12 @@ private:
}; };
class SegmentExposureCompensator : public ExposureCompensator
{
public:
void feed(const std::vector<cv::Point> &corners, const std::vector<cv::Mat> &images,
const std::vector<cv::Mat> &masks);
void apply(int index, cv::Point corner, cv::Mat &image, const cv::Mat &mask);
};
#endif // __OPENCV_EXPOSURE_COMPENSATE_HPP__ #endif // __OPENCV_EXPOSURE_COMPENSATE_HPP__
\ No newline at end of file
...@@ -71,7 +71,7 @@ void printUsage() ...@@ -71,7 +71,7 @@ void printUsage()
<< "\t[--wavecorrect (no|yes)]\n" << "\t[--wavecorrect (no|yes)]\n"
<< "\t[--warp (plane|cylindrical|spherical)]\n" << "\t[--warp (plane|cylindrical|spherical)]\n"
<< "\t[--exposcomp (no|overlap)]\n" << "\t[--exposcomp (no|overlap)]\n"
<< "\t[--seam (no|voronoi|graphcut)]\n" << "\t[--seam (no|voronoi|gc_color|gc_colorgrad)]\n"
<< "\t[--blend (no|feather|multiband)]\n" << "\t[--blend (no|feather|multiband)]\n"
<< "\t[--numbands <int>]\n" << "\t[--numbands <int>]\n"
<< "\t[--output <result_img>]\n\n"; << "\t[--output <result_img>]\n\n";
...@@ -95,7 +95,7 @@ int warp_type = Warper::SPHERICAL; ...@@ -95,7 +95,7 @@ int warp_type = Warper::SPHERICAL;
int expos_comp_type = ExposureCompensator::OVERLAP; int expos_comp_type = ExposureCompensator::OVERLAP;
bool user_match_conf = false; bool user_match_conf = false;
float match_conf = 0.6f; float match_conf = 0.6f;
int seam_find_type = SeamFinder::GRAPH_CUT; int seam_find_type = SeamFinder::GC_COLOR;
int blend_type = Blender::MULTI_BAND; int blend_type = Blender::MULTI_BAND;
int numbands = 5; int numbands = 5;
string result_name = "result.png"; string result_name = "result.png";
...@@ -201,6 +201,8 @@ int parseCmdArgs(int argc, char** argv) ...@@ -201,6 +201,8 @@ int parseCmdArgs(int argc, char** argv)
expos_comp_type = ExposureCompensator::NO; expos_comp_type = ExposureCompensator::NO;
else if (string(argv[i + 1]) == "overlap") else if (string(argv[i + 1]) == "overlap")
expos_comp_type = ExposureCompensator::OVERLAP; expos_comp_type = ExposureCompensator::OVERLAP;
else if (string(argv[i + 1]) == "segment")
expos_comp_type = ExposureCompensator::SEGMENT;
else else
{ {
cout << "Bad exposure compensation method\n"; cout << "Bad exposure compensation method\n";
...@@ -214,8 +216,10 @@ int parseCmdArgs(int argc, char** argv) ...@@ -214,8 +216,10 @@ int parseCmdArgs(int argc, char** argv)
seam_find_type = SeamFinder::NO; seam_find_type = SeamFinder::NO;
else if (string(argv[i + 1]) == "voronoi") else if (string(argv[i + 1]) == "voronoi")
seam_find_type = SeamFinder::VORONOI; seam_find_type = SeamFinder::VORONOI;
else if (string(argv[i + 1]) == "graphcut") else if (string(argv[i + 1]) == "gc_color")
seam_find_type = SeamFinder::GRAPH_CUT; seam_find_type = SeamFinder::GC_COLOR;
else if (string(argv[i + 1]) == "gc_colorgrad")
seam_find_type = SeamFinder::GC_COLOR_GRAD;
else else
{ {
cout << "Bad seam finding method\n"; cout << "Bad seam finding method\n";
......
...@@ -65,8 +65,8 @@ namespace ...@@ -65,8 +65,8 @@ namespace
class CpuSurfFeaturesFinder : public FeaturesFinder class CpuSurfFeaturesFinder : public FeaturesFinder
{ {
public: public:
inline CpuSurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers, 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 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);
...@@ -80,20 +80,12 @@ namespace ...@@ -80,20 +80,12 @@ namespace
Ptr<DescriptorExtractor> extractor_; Ptr<DescriptorExtractor> extractor_;
}; };
void CpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
{
Mat gray_image;
CV_Assert(image.depth() == CV_8U);
cvtColor(image, gray_image, CV_BGR2GRAY);
detector_->detect(gray_image, features.keypoints);
extractor_->compute(gray_image, features.keypoints, features.descriptors);
}
class GpuSurfFeaturesFinder : public FeaturesFinder class GpuSurfFeaturesFinder : public FeaturesFinder
{ {
public: public:
inline GpuSurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers, GpuSurfFeaturesFinder(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)
{ {
surf_.keypointsRatio = 0.1f; surf_.keypointsRatio = 0.1f;
surf_.hessianThreshold = hess_thresh; surf_.hessianThreshold = hess_thresh;
...@@ -113,6 +105,17 @@ namespace ...@@ -113,6 +105,17 @@ namespace
int num_octaves_descr_, num_layers_descr_; int num_octaves_descr_, num_layers_descr_;
}; };
void CpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
{
Mat gray_image;
CV_Assert(image.depth() == CV_8U);
cvtColor(image, gray_image, CV_BGR2GRAY);
detector_->detect(gray_image, features.keypoints);
extractor_->compute(gray_image, features.keypoints, features.descriptors);
}
void GpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features) void GpuSurfFeaturesFinder::find(const Mat &image, ImageFeatures &features)
{ {
GpuMat gray_image; GpuMat gray_image;
...@@ -132,7 +135,8 @@ namespace ...@@ -132,7 +135,8 @@ namespace
d_descriptors.download(features.descriptors); d_descriptors.download(features.descriptors);
} }
} } // anonymous namespace
SurfFeaturesFinder::SurfFeaturesFinder(bool try_use_gpu, double hess_thresh, int num_octaves, int num_layers, SurfFeaturesFinder::SurfFeaturesFinder(bool try_use_gpu, 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)
......
This diff is collapsed.
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
class SeamFinder class SeamFinder
{ {
public: public:
enum { NO, VORONOI, GRAPH_CUT }; enum { NO, VORONOI, GC_COLOR, GC_COLOR_GRAD };
static cv::Ptr<SeamFinder> createDefault(int type); static cv::Ptr<SeamFinder> createDefault(int type);
virtual ~SeamFinder() {} virtual ~SeamFinder() {}
...@@ -66,34 +66,36 @@ public: ...@@ -66,34 +66,36 @@ public:
class PairwiseSeamFinder : public SeamFinder class PairwiseSeamFinder : public SeamFinder
{ {
public: public:
void find(const std::vector<cv::Mat> &src, const std::vector<cv::Point> &corners, virtual void find(const std::vector<cv::Mat> &src, const std::vector<cv::Point> &corners,
std::vector<cv::Mat> &masks); std::vector<cv::Mat> &masks);
protected: protected:
virtual void findInPair(const cv::Mat &img1, const cv::Mat &img2, cv::Point tl1, cv::Point tl2, virtual void findInPair(size_t first, size_t second, cv::Rect roi) = 0;
cv::Rect roi, cv::Mat &mask1, cv::Mat &mask2) = 0;
std::vector<cv::Mat> images_;
std::vector<cv::Point> corners_;
std::vector<cv::Mat> masks_;
}; };
class VoronoiSeamFinder : public PairwiseSeamFinder class VoronoiSeamFinder : public PairwiseSeamFinder
{ {
private: private:
void findInPair(const cv::Mat &img1, const cv::Mat &img2, cv::Point tl1, cv::Point tl2, void findInPair(size_t first, size_t second, cv::Rect roi);
cv::Rect roi, cv::Mat &mask1, cv::Mat &mask2);
}; };
class GraphCutSeamFinder : public PairwiseSeamFinder class GraphCutSeamFinder : public SeamFinder
{ {
public: public:
// TODO add COST_COLOR_GRAD support enum { COST_COLOR, COST_COLOR_GRAD };
enum { COST_COLOR }; GraphCutSeamFinder(int cost_type = COST_COLOR_GRAD, float terminal_cost = 10000.f,
GraphCutSeamFinder(int cost_type = COST_COLOR, float terminal_cost = 10000.f,
float bad_region_penalty = 1000.f); float bad_region_penalty = 1000.f);
private: void find(const std::vector<cv::Mat> &src, const std::vector<cv::Point> &corners,
void findInPair(const cv::Mat &img1, const cv::Mat &img2, cv::Point tl1, cv::Point tl2, std::vector<cv::Mat> &masks);
cv::Rect roi, cv::Mat &mask1, cv::Mat &mask2);
private:
class Impl; class Impl;
cv::Ptr<Impl> impl_; cv::Ptr<Impl> impl_;
}; };
......
...@@ -91,10 +91,17 @@ B Graph::walkBreadthFirst(int from, B body) const ...@@ -91,10 +91,17 @@ B Graph::walkBreadthFirst(int from, B body) const
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Some auxiliary math functions // Some auxiliary math functions
static inline
float normL2(const cv::Point3f& a)
{
return a.x * a.x + a.y * a.y + a.z * a.z;
}
static inline static inline
float normL2(const cv::Point3f& a, const cv::Point3f& b) float normL2(const cv::Point3f& a, const cv::Point3f& b)
{ {
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z); return normL2(a - b);
} }
......
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