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
50namespace cv {
51namespace detail {
52
53//! @addtogroup stitching_seam
54//! @{
55
56/** @brief Base class for a seam estimator.
57 */
58class CV_EXPORTS SeamFinder
59{
60public:
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 */
74class CV_EXPORTS NoSeamFinder : public SeamFinder
75{
76public:
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 */
82class CV_EXPORTS PairwiseSeamFinder : public SeamFinder
83{
84public:
85    virtual void find(const std::vector<UMat> &src, const std::vector<Point> &corners,
86                      std::vector<UMat> &masks);
87
88protected:
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 */
106class CV_EXPORTS VoronoiSeamFinder : public PairwiseSeamFinder
107{
108public:
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);
113private:
114    void findInPair(size_t first, size_t second, Rect roi);
115};
116
117
118class CV_EXPORTS DpSeamFinder : public SeamFinder
119{
120public:
121    enum CostFunction { COLOR, COLOR_GRAD };
122
123    DpSeamFinder(CostFunction costFunc = COLOR);
124
125    CostFunction costFunction() const { return costFunc_; }
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
131private:
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:
142        ImagePairLess(const std::vector<Mat> &images, const std::vector<Point> &corners)
143            : src_(&images[0]), corners_(&corners[0]) {}
144
145        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:
166        ClosePoints(int minDist) : minDist_(minDist) {}
167
168        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 */
228class CV_EXPORTS GraphCutSeamFinderBase
229{
230public:
231    enum CostType { COST_COLOR, COST_COLOR_GRAD };
232};
233
234/** @brief Minimum graph cut-based seam estimator. See details in @cite V03 .
235 */
236class CV_EXPORTS GraphCutSeamFinder : public GraphCutSeamFinderBase, public SeamFinder
237{
238public:
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
247private:
248    // To avoid GCGraph dependency
249    class Impl;
250    Ptr<PairwiseSeamFinder> impl_;
251};
252
253
254#ifdef HAVE_OPENCV_CUDALEGACY
255class CV_EXPORTS GraphCutSeamFinderGpu : public GraphCutSeamFinderBase, public PairwiseSeamFinder
256{
257public:
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
267private:
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