1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                          License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42 
43 #ifndef __OPENCV_STITCHING_SEAM_FINDERS_HPP__
44 #define __OPENCV_STITCHING_SEAM_FINDERS_HPP__
45 
46 #include <set>
47 #include "opencv2/core.hpp"
48 #include "opencv2/opencv_modules.hpp"
49 
50 namespace cv {
51 namespace detail {
52 
53 //! @addtogroup stitching_seam
54 //! @{
55 
56 /** @brief Base class for a seam estimator.
57  */
58 class CV_EXPORTS SeamFinder
59 {
60 public:
~SeamFinder()61     virtual ~SeamFinder() {}
62     /** @brief Estimates seams.
63 
64     @param src Source images
65     @param corners Source image top-left corners
66     @param masks Source image masks to update
67      */
68     virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
69                       std::vector<UMat> &masks) = 0;
70 };
71 
72 /** @brief Stub seam estimator which does nothing.
73  */
74 class CV_EXPORTS NoSeamFinder : public SeamFinder
75 {
76 public:
find(const std::vector<UMat> &,const std::vector<Point> &,std::vector<UMat> &)77     void find(const std::vector<UMat>&, const std::vector<Point>&, std::vector<UMat>&) {}
78 };
79 
80 /** @brief Base class for all pairwise seam estimators.
81  */
82 class CV_EXPORTS PairwiseSeamFinder : public SeamFinder
83 {
84 public:
85     virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
86                       std::vector<UMat> &masks);
87 
88 protected:
89     void run();
90     /** @brief Resolves masks intersection of two specified images in the given ROI.
91 
92     @param first First image index
93     @param second Second image index
94     @param roi Region of interest
95      */
96     virtual void findInPair(size_t first, size_t second, Rect roi) = 0;
97 
98     std::vector<UMat> images_;
99     std::vector<Size> sizes_;
100     std::vector<Point> corners_;
101     std::vector<UMat> masks_;
102 };
103 
104 /** @brief Voronoi diagram-based seam estimator.
105  */
106 class CV_EXPORTS VoronoiSeamFinder : public PairwiseSeamFinder
107 {
108 public:
109     virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
110                       std::vector<UMat> &masks);
111     virtual void find(const std::vector<Size> &size, const std::vector<Point> &corners,
112                       std::vector<UMat> &masks);
113 private:
114     void findInPair(size_t first, size_t second, Rect roi);
115 };
116 
117 
118 class CV_EXPORTS DpSeamFinder : public SeamFinder
119 {
120 public:
121     enum CostFunction { COLOR, COLOR_GRAD };
122 
123     DpSeamFinder(CostFunction costFunc = COLOR);
124 
costFunction() const125     CostFunction costFunction() const { return costFunc_; }
setCostFunction(CostFunction val)126     void setCostFunction(CostFunction val) { costFunc_ = val; }
127 
128     virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
129                       std::vector<UMat> &masks);
130 
131 private:
132     enum ComponentState
133     {
134         FIRST = 1, SECOND = 2, INTERS = 4,
135         INTERS_FIRST = INTERS | FIRST,
136         INTERS_SECOND = INTERS | SECOND
137     };
138 
139     class ImagePairLess
140     {
141     public:
ImagePairLess(const std::vector<Mat> & images,const std::vector<Point> & corners)142         ImagePairLess(const std::vector<Mat> &images, const std::vector<Point> &corners)
143             : src_(&images[0]), corners_(&corners[0]) {}
144 
operator ()(const std::pair<size_t,size_t> & l,const std::pair<size_t,size_t> & r) const145         bool operator() (const std::pair<size_t, size_t> &l, const std::pair<size_t, size_t> &r) const
146         {
147             Point c1 = corners_[l.first] + Point(src_[l.first].cols / 2, src_[l.first].rows / 2);
148             Point c2 = corners_[l.second] + Point(src_[l.second].cols / 2, src_[l.second].rows / 2);
149             int d1 = (c1 - c2).dot(c1 - c2);
150 
151             c1 = corners_[r.first] + Point(src_[r.first].cols / 2, src_[r.first].rows / 2);
152             c2 = corners_[r.second] + Point(src_[r.second].cols / 2, src_[r.second].rows / 2);
153             int d2 = (c1 - c2).dot(c1 - c2);
154 
155             return d1 < d2;
156         }
157 
158     private:
159         const Mat *src_;
160         const Point *corners_;
161     };
162 
163     class ClosePoints
164     {
165     public:
ClosePoints(int minDist)166         ClosePoints(int minDist) : minDist_(minDist) {}
167 
operator ()(const Point & p1,const Point & p2) const168         bool operator() (const Point &p1, const Point &p2) const
169         {
170             int dist2 = (p1.x-p2.x) * (p1.x-p2.x) + (p1.y-p2.y) * (p1.y-p2.y);
171             return dist2 < minDist_ * minDist_;
172         }
173 
174     private:
175         int minDist_;
176     };
177 
178     void process(
179             const Mat &image1, const Mat &image2, Point tl1, Point tl2,  Mat &mask1, Mat &mask2);
180 
181     void findComponents();
182 
183     void findEdges();
184 
185     void resolveConflicts(
186             const Mat &image1, const Mat &image2, Point tl1, Point tl2, Mat &mask1, Mat &mask2);
187 
188     void computeGradients(const Mat &image1, const Mat &image2);
189 
190     bool hasOnlyOneNeighbor(int comp);
191 
192     bool closeToContour(int y, int x, const Mat_<uchar> &contourMask);
193 
194     bool getSeamTips(int comp1, int comp2, Point &p1, Point &p2);
195 
196     void computeCosts(
197             const Mat &image1, const Mat &image2, Point tl1, Point tl2,
198             int comp, Mat_<float> &costV, Mat_<float> &costH);
199 
200     bool estimateSeam(
201             const Mat &image1, const Mat &image2, Point tl1, Point tl2, int comp,
202             Point p1, Point p2, std::vector<Point> &seam, bool &isHorizontal);
203 
204     void updateLabelsUsingSeam(
205             int comp1, int comp2, const std::vector<Point> &seam, bool isHorizontalSeam);
206 
207     CostFunction costFunc_;
208 
209     // processing images pair data
210     Point unionTl_, unionBr_;
211     Size unionSize_;
212     Mat_<uchar> mask1_, mask2_;
213     Mat_<uchar> contour1mask_, contour2mask_;
214     Mat_<float> gradx1_, grady1_;
215     Mat_<float> gradx2_, grady2_;
216 
217     // components data
218     int ncomps_;
219     Mat_<int> labels_;
220     std::vector<ComponentState> states_;
221     std::vector<Point> tls_, brs_;
222     std::vector<std::vector<Point> > contours_;
223     std::set<std::pair<int, int> > edges_;
224 };
225 
226 /** @brief Base class for all minimum graph-cut-based seam estimators.
227  */
228 class CV_EXPORTS GraphCutSeamFinderBase
229 {
230 public:
231     enum CostType { COST_COLOR, COST_COLOR_GRAD };
232 };
233 
234 /** @brief Minimum graph cut-based seam estimator. See details in @cite V03 .
235  */
236 class CV_EXPORTS GraphCutSeamFinder : public GraphCutSeamFinderBase, public SeamFinder
237 {
238 public:
239     GraphCutSeamFinder(int cost_type = COST_COLOR_GRAD, float terminal_cost = 10000.f,
240                        float bad_region_penalty = 1000.f);
241 
242     ~GraphCutSeamFinder();
243 
244     void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
245               std::vector<UMat> &masks);
246 
247 private:
248     // To avoid GCGraph dependency
249     class Impl;
250     Ptr<PairwiseSeamFinder> impl_;
251 };
252 
253 
254 #ifdef HAVE_OPENCV_CUDALEGACY
255 class CV_EXPORTS GraphCutSeamFinderGpu : public GraphCutSeamFinderBase, public PairwiseSeamFinder
256 {
257 public:
GraphCutSeamFinderGpu(int cost_type=COST_COLOR_GRAD,float terminal_cost=10000.f,float bad_region_penalty=1000.f)258     GraphCutSeamFinderGpu(int cost_type = COST_COLOR_GRAD, float terminal_cost = 10000.f,
259                           float bad_region_penalty = 1000.f)
260                           : cost_type_(cost_type), terminal_cost_(terminal_cost),
261                             bad_region_penalty_(bad_region_penalty) {}
262 
263     void find(const std::vector<cv::UMat> &src, const std::vector<cv::Point> &corners,
264               std::vector<cv::UMat> &masks);
265     void findInPair(size_t first, size_t second, Rect roi);
266 
267 private:
268     void setGraphWeightsColor(const cv::Mat &img1, const cv::Mat &img2, const cv::Mat &mask1, const cv::Mat &mask2,
269                               cv::Mat &terminals, cv::Mat &leftT, cv::Mat &rightT, cv::Mat &top, cv::Mat &bottom);
270     void setGraphWeightsColorGrad(const cv::Mat &img1, const cv::Mat &img2, const cv::Mat &dx1, const cv::Mat &dx2,
271                                   const cv::Mat &dy1, const cv::Mat &dy2, const cv::Mat &mask1, const cv::Mat &mask2,
272                                   cv::Mat &terminals, cv::Mat &leftT, cv::Mat &rightT, cv::Mat &top, cv::Mat &bottom);
273     std::vector<Mat> dx_, dy_;
274     int cost_type_;
275     float terminal_cost_;
276     float bad_region_penalty_;
277 };
278 #endif
279 
280 //! @}
281 
282 } // namespace detail
283 } // namespace cv
284 
285 #endif // __OPENCV_STITCHING_SEAM_FINDERS_HPP__
286