@@ -128,18 +128,21 @@ class GuidedFilterImpl : public GuidedFilter
128128{
129129public:
130130
131- static Ptr<GuidedFilterImpl> create (InputArray guide, int radius, double eps);
131+ static Ptr<GuidedFilterImpl> create (InputArray guide, int radius, double eps, double scale );
132132
133133 void filter (InputArray src, OutputArray dst, int dDepth = -1 ) CV_OVERRIDE;
134134
135135protected:
136136
137137 int radius;
138138 double eps;
139+ double scale;
139140 int h, w;
141+ int hOriginal, wOriginal;
140142
141143 vector<Mat> guideCn;
142144 vector<Mat> guideCnMean;
145+ vector<Mat> guideCnOriginal;
143146
144147 SymArray2D<Mat> covarsInv;
145148
@@ -149,7 +152,7 @@ class GuidedFilterImpl : public GuidedFilter
149152
150153 GuidedFilterImpl () {}
151154
152- void init (InputArray guide, int radius, double eps);
155+ void init (InputArray guide, int radius, double eps, double scale );
153156
154157 void computeCovGuide (SymArray2D<Mat>& covars);
155158
@@ -167,6 +170,16 @@ class GuidedFilterImpl : public GuidedFilter
167170 src.convertTo (dst, CV_32F);
168171 }
169172
173+ inline void subsample (Mat& src, Mat& dst)
174+ {
175+ resize (src, dst, Size (w, h), 0 , 0 , INTER_LINEAR);
176+ }
177+
178+ inline void upsample (Mat& src, Mat& dst)
179+ {
180+ resize (src, dst, Size (wOriginal, hOriginal), 0 , 0 , INTER_LINEAR);
181+ }
182+
170183private: /* Routines to parallelize boxFilter and convertTo*/
171184
172185 typedef void (GuidedFilterImpl::*TransformFunc)(Mat& src, Mat& dst);
@@ -203,6 +216,20 @@ class GuidedFilterImpl : public GuidedFilter
203216 parallel_for_ (pb.getRange (), pb);
204217 }
205218
219+ template <typename V>
220+ void parSubsample (V &src, V &dst)
221+ {
222+ GFTransform_ParBody pb (*this , src, dst, &GuidedFilterImpl::subsample);
223+ parallel_for_ (pb.getRange (), pb);
224+ }
225+
226+ template <typename V>
227+ void parUpsample (V &src, V &dst)
228+ {
229+ GFTransform_ParBody pb (*this , src, dst, &GuidedFilterImpl::upsample);
230+ parallel_for_ (pb.getRange (), pb);
231+ }
232+
206233private: /* Parallel body classes*/
207234
208235 inline void runParBody (const ParallelLoopBody& pb)
@@ -582,7 +609,7 @@ void GuidedFilterImpl::ApplyTransform_ParBody::operator()(const Range& range) co
582609 {
583610 float *_g[4 ];
584611 for (int gi = 0 ; gi < gf.gCnNum ; gi++)
585- _g[gi] = gf.guideCn [gi].ptr <float >(i);
612+ _g[gi] = gf.guideCnOriginal [gi].ptr <float >(i);
586613
587614 float *betaDst, *g, *a;
588615 for (int si = 0 ; si < srcCnNum; si++)
@@ -593,7 +620,7 @@ void GuidedFilterImpl::ApplyTransform_ParBody::operator()(const Range& range) co
593620 a = alpha[si][gi].ptr <float >(i);
594621 g = _g[gi];
595622
596- add_mul (betaDst, a, g, gf.w );
623+ add_mul (betaDst, a, g, gf.wOriginal );
597624 }
598625 }
599626 }
@@ -666,28 +693,42 @@ void GuidedFilterImpl::getWalkPattern(int eid, int &cn1, int &cn2)
666693 cn2 = wdata[6 * 2 * (gCnNum -1 ) + 6 + eid];
667694}
668695
669- Ptr<GuidedFilterImpl> GuidedFilterImpl::create (InputArray guide, int radius, double eps)
696+ Ptr<GuidedFilterImpl> GuidedFilterImpl::create (InputArray guide, int radius, double eps, double scale )
670697{
671698 GuidedFilterImpl *gf = new GuidedFilterImpl ();
672- gf->init (guide, radius, eps);
699+ gf->init (guide, radius, eps, scale );
673700 return Ptr<GuidedFilterImpl>(gf);
674701}
675702
676- void GuidedFilterImpl::init (InputArray guide, int radius_, double eps_)
703+ void GuidedFilterImpl::init (InputArray guide, int radius_, double eps_, double scale_ )
677704{
678705 CV_Assert ( !guide.empty () && radius_ >= 0 && eps_ >= 0 );
679706 CV_Assert ( (guide.depth () == CV_32F || guide.depth () == CV_8U || guide.depth () == CV_16U) && (guide.channels () <= 3 ) );
707+ CV_Assert ( scale_ <= 1.0 );
680708
681709 radius = radius_;
682710 eps = eps_;
711+ scale = scale_;
683712
684- splitFirstNChannels (guide, guideCn, 3 );
685- gCnNum = (int )guideCn.size ();
686- h = guideCn[0 ].rows ;
687- w = guideCn[0 ].cols ;
713+ splitFirstNChannels (guide, guideCnOriginal, 3 );
714+ gCnNum = (int )guideCnOriginal.size ();
715+ hOriginal = guideCnOriginal[0 ].rows ;
716+ wOriginal = guideCnOriginal[0 ].cols ;
717+ h = int (hOriginal * scale);
718+ w = int (wOriginal * scale);
719+
720+ parConvertToWorkType (guideCnOriginal, guideCnOriginal);
721+ if (scale < 1.0 )
722+ {
723+ guideCn.resize (gCnNum );
724+ parSubsample (guideCnOriginal, guideCn);
725+ }
726+ else
727+ {
728+ guideCn = guideCnOriginal;
729+ }
688730
689731 guideCnMean.resize (gCnNum );
690- parConvertToWorkType (guideCn, guideCn);
691732 parMeanFilter (guideCn, guideCnMean);
692733
693734 SymArray2D<Mat> covars;
@@ -712,7 +753,7 @@ void GuidedFilterImpl::computeCovGuide(SymArray2D<Mat>& covars)
712753void GuidedFilterImpl::filter (InputArray src, OutputArray dst, int dDepth /* = -1*/ )
713754{
714755 CV_Assert ( !src.empty () && (src.depth () == CV_32F || src.depth () == CV_8U) );
715- if (src.rows () != h || src.cols () != w )
756+ if (src.rows () != hOriginal || src.cols () != wOriginal )
716757 {
717758 CV_Error (Error::StsBadSize, " Size of filtering image must be equal to size of guide image" );
718759 return ;
@@ -725,6 +766,11 @@ void GuidedFilterImpl::filter(InputArray src, OutputArray dst, int dDepth /*= -1
725766 vector<Mat>& srcCnMean = srcCn;
726767 split (src, srcCn);
727768
769+ if (scale < 1.0 )
770+ {
771+ parSubsample (srcCn, srcCn);
772+ }
773+
728774 if (src.depth () != CV_32F)
729775 {
730776 parConvertToWorkType (srcCn, srcCn);
@@ -749,7 +795,13 @@ void GuidedFilterImpl::filter(InputArray src, OutputArray dst, int dDepth /*= -1
749795 parMeanFilter (beta, beta);
750796 parMeanFilter (alpha, alpha);
751797
752- runParBody (ApplyTransform_ParBody (*this , alpha, beta));
798+ if (scale < 1.0 )
799+ {
800+ parUpsample (beta, beta);
801+ parUpsample (alpha, alpha);
802+ }
803+
804+ parallel_for_ (Range (0 , hOriginal), ApplyTransform_ParBody (*this , alpha, beta));
753805 if (dDepth != CV_32F)
754806 {
755807 for (int i = 0 ; i < srcCnNum; i++)
@@ -782,15 +834,15 @@ void GuidedFilterImpl::computeCovGuideAndSrc(vector<Mat>& srcCn, vector<Mat>& sr
782834// ////////////////////////////////////////////////////////////////////////
783835
784836CV_EXPORTS_W
785- Ptr<GuidedFilter> createGuidedFilter (InputArray guide, int radius, double eps)
837+ Ptr<GuidedFilter> createGuidedFilter (InputArray guide, int radius, double eps, double scale )
786838{
787- return Ptr<GuidedFilter>(GuidedFilterImpl::create (guide, radius, eps));
839+ return Ptr<GuidedFilter>(GuidedFilterImpl::create (guide, radius, eps, scale ));
788840}
789841
790842CV_EXPORTS_W
791- void guidedFilter (InputArray guide, InputArray src, OutputArray dst, int radius, double eps, int dDepth)
843+ void guidedFilter (InputArray guide, InputArray src, OutputArray dst, int radius, double eps, int dDepth, double scale )
792844{
793- Ptr<GuidedFilter> gf = createGuidedFilter (guide, radius, eps);
845+ Ptr<GuidedFilter> gf = createGuidedFilter (guide, radius, eps, scale );
794846 gf->filter (src, dst, dDepth);
795847}
796848
0 commit comments