1 /*
2  *  By downloading, copying, installing or using the software you agree to this license.
3  *  If you do not agree to this license, do not download, install,
4  *  copy or use the software.
5  *
6  *
7  *  License Agreement
8  *  For Open Source Computer Vision Library
9  *  (3 - clause BSD License)
10  *
11  *  Redistribution and use in source and binary forms, with or without modification,
12  *  are permitted provided that the following conditions are met :
13  *
14  *  * Redistributions of source code must retain the above copyright notice,
15  *  this list of conditions and the following disclaimer.
16  *
17  *  * Redistributions in binary form must reproduce the above copyright notice,
18  *  this list of conditions and the following disclaimer in the documentation
19  *  and / or other materials provided with the distribution.
20  *
21  *  * Neither the names of the copyright holders nor the names of the contributors
22  *  may be used to endorse or promote products derived from this software
23  *  without specific prior written permission.
24  *
25  *  This software is provided by the copyright holders and contributors "as is" and
26  *  any express or implied warranties, including, but not limited to, the implied
27  *  warranties of merchantability and fitness for a particular purpose are disclaimed.
28  *  In no event shall copyright holders or contributors be liable for any direct,
29  *  indirect, incidental, special, exemplary, or consequential damages
30  *  (including, but not limited to, procurement of substitute goods or services;
31  *  loss of use, data, or profits; or business interruption) however caused
32  *  and on any theory of liability, whether in contract, strict liability,
33  *  or tort(including negligence or otherwise) arising in any way out of
34  *  the use of this software, even if advised of the possibility of such damage.
35  */
36 
37 #ifndef __OPENCV_DTFILTER_INL_HPP__
38 #define __OPENCV_DTFILTER_INL_HPP__
39 #include "precomp.hpp"
40 #include "edgeaware_filters_common.hpp"
41 #include <limits>
42 
43 namespace cv
44 {
45 namespace ximgproc
46 {
47 
48 using namespace cv::ximgproc::intrinsics;
49 
50 #define NC_USE_INTEGRAL_SRC
51 //#undef NC_USE_INTEGRAL_SRC
52 
53 template<typename GuideVec>
create_(const Mat & guide,double sigmaSpatial,double sigmaColor,int mode,int numIters)54 DTFilterCPU DTFilterCPU::create_(const Mat& guide, double sigmaSpatial, double sigmaColor, int mode, int numIters)
55 {
56     DTFilterCPU dtf;
57     dtf.init_<GuideVec>(guide, sigmaSpatial, sigmaColor, mode, numIters);
58     return dtf;
59 }
60 
61 template<typename GuideVec>
create_p_(const Mat & guide,double sigmaSpatial,double sigmaColor,int mode,int numIters)62 DTFilterCPU* DTFilterCPU::create_p_(const Mat& guide, double sigmaSpatial, double sigmaColor, int mode, int numIters)
63 {
64     DTFilterCPU* dtf = new DTFilterCPU();
65     dtf->init_<GuideVec>(guide, sigmaSpatial, sigmaColor, mode, numIters);
66     return dtf;
67 }
68 
69 template<typename GuideVec>
init_(Mat & guide,double sigmaSpatial_,double sigmaColor_,int mode_,int numIters_)70 void DTFilterCPU::init_(Mat& guide, double sigmaSpatial_, double sigmaColor_, int mode_, int numIters_)
71 {
72     CV_Assert(guide.type() == traits::Type<GuideVec>::value);
73 
74     this->release();
75 
76     h = guide.rows;
77     w = guide.cols;
78 
79     sigmaSpatial = std::max(1.0f, (float)sigmaSpatial_);
80     sigmaColor   = std::max(0.01f, (float)sigmaColor_);
81 
82     mode = mode_;
83     numIters = std::max(1, numIters_);
84 
85     if (mode == DTF_NC)
86     {
87         {
88             ComputeIDTHor_ParBody<GuideVec> horBody(*this, guide, idistHor);
89             parallel_for_(horBody.getRange(), horBody);
90         }
91         {
92             Mat guideT = guide.t();
93             ComputeIDTHor_ParBody<GuideVec> horBody(*this, guideT, idistVert);
94             parallel_for_(horBody.getRange(), horBody);
95         }
96     }
97     else if (mode == DTF_IC)
98     {
99         {
100             ComputeDTandIDTHor_ParBody<GuideVec> horBody(*this, guide, distHor, idistHor);
101             parallel_for_(horBody.getRange(), horBody);
102         }
103         {
104             Mat guideT = guide.t();
105             ComputeDTandIDTHor_ParBody<GuideVec> horBody(*this, guideT, distVert, idistVert);
106             parallel_for_(horBody.getRange(), horBody);
107         }
108     }
109     else if (mode == DTF_RF)
110     {
111         ComputeA0DTHor_ParBody<GuideVec> horBody(*this, guide);
112         ComputeA0DTVert_ParBody<GuideVec> vertBody(*this, guide);
113         parallel_for_(horBody.getRange(), horBody);
114         parallel_for_(vertBody.getRange(), vertBody);
115     }
116     else
117     {
118         CV_Error(Error::StsBadFlag, "Incorrect DT filter mode");
119     }
120 }
121 
122 template <typename SrcVec>
filter_(const Mat & src,Mat & dst,int dDepth)123 void DTFilterCPU::filter_(const Mat& src, Mat& dst, int dDepth)
124 {
125     typedef typename DataType<Vec<WorkType, SrcVec::channels> >::vec_type WorkVec;
126     CV_Assert( src.type() == traits::Type<SrcVec>::value );
127     if ( src.cols != w || src.rows != h )
128     {
129         CV_Error(Error::StsBadSize, "Size of filtering image must be equal to size of guide image");
130     }
131 
132     if (singleFilterCall)
133     {
134         CV_Assert(numFilterCalls == 0);
135     }
136     numFilterCalls++;
137 
138     Mat res;
139     if (dDepth == -1) dDepth = src.depth();
140 
141     //small optimization to avoid extra copying of data
142     bool useDstAsRes = (dDepth == traits::Depth<WorkVec>::value && (mode == DTF_NC || mode == DTF_RF));
143     if (useDstAsRes)
144     {
145         dst.create(h, w, traits::Type<WorkVec>::value);
146         res = dst;
147     }
148 
149     if (mode == DTF_NC)
150     {
151         Mat resT(src.cols, src.rows, traits::Type<WorkVec>::value);
152         src.convertTo(res, traits::Type<WorkVec>::value);
153 
154         FilterNC_horPass<WorkVec> horParBody(res, idistHor, resT);
155         FilterNC_horPass<WorkVec> vertParBody(resT, idistVert, res);
156 
157         for (int iter = 1; iter <= numIters; iter++)
158         {
159             horParBody.radius = vertParBody.radius = getIterRadius(iter);
160 
161             parallel_for_(Range(0, res.rows), horParBody);
162             parallel_for_(Range(0, resT.rows), vertParBody);
163         }
164     }
165     else if (mode == DTF_IC)
166     {
167         Mat resT;
168         prepareSrcImg_IC<WorkVec>(src, res, resT);
169 
170         FilterIC_horPass<WorkVec> horParBody(res, idistHor, distHor, resT);
171         FilterIC_horPass<WorkVec> vertParBody(resT, idistVert, distVert, res);
172 
173         for (int iter = 1; iter <= numIters; iter++)
174         {
175             horParBody.radius = vertParBody.radius = getIterRadius(iter);
176 
177             parallel_for_(Range(0, res.rows), horParBody);
178             parallel_for_(Range(0, resT.rows), vertParBody);
179         }
180     }
181     else if (mode == DTF_RF)
182     {
183         src.convertTo(res, traits::Type<WorkVec>::value);
184 
185         for (int iter = 1; iter <= numIters; iter++)
186         {
187             if (!singleFilterCall && iter == 2)
188             {
189                 a0distHor.copyTo(adistHor);
190                 a0distVert.copyTo(adistVert);
191             }
192 
193             bool useA0DT = (singleFilterCall || iter == 1);
194             Mat& a0dHor  = (useA0DT) ? a0distHor : adistHor;
195             Mat& a0dVert = (useA0DT) ? a0distVert : adistVert;
196 
197             FilterRF_horPass<WorkVec> horParBody(res, a0dHor, iter);
198             FilterRF_vertPass<WorkVec> vertParBody(res, a0dVert, iter);
199             parallel_for_(horParBody.getRange(), horParBody);
200             parallel_for_(vertParBody.getRange(), vertParBody);
201         }
202     }
203 
204     if (!useDstAsRes)
205     {
206         res.convertTo(dst, dDepth);
207     }
208 }
209 
210 template<typename SrcVec, typename SrcWorkVec>
integrateRow(const SrcVec * src,SrcWorkVec * dst,int cols)211 void DTFilterCPU::integrateRow(const SrcVec *src, SrcWorkVec *dst, int cols)
212 {
213     SrcWorkVec sum = SrcWorkVec::all(0);
214     dst[0] = sum;
215 
216     for (int j = 0; j < cols; j++)
217     {
218         sum += SrcWorkVec(src[j]);
219         dst[j + 1] = sum;
220     }
221 }
222 
223 
224 template<typename SrcVec, typename SrcWorkVec>
integrateSparseRow(const SrcVec * src,const float * dist,SrcWorkVec * dst,int cols)225 void DTFilterCPU::integrateSparseRow(const SrcVec *src, const float *dist, SrcWorkVec *dst, int cols)
226 {
227     SrcWorkVec sum = SrcWorkVec::all(0);
228     dst[0] = sum;
229 
230     for (int j = 0; j < cols-1; j++)
231     {
232         sum += dist[j] * 0.5f * (SrcWorkVec(src[j]) + SrcWorkVec(src[j+1]));
233         dst[j + 1] = sum;
234     }
235 }
236 
237 template<typename WorkVec>
prepareSrcImg_IC(const Mat & src,Mat & dst,Mat & dstT)238 void DTFilterCPU::prepareSrcImg_IC(const Mat& src, Mat& dst, Mat& dstT)
239 {
240     Mat dstOut(src.rows, src.cols + 2, traits::Type<WorkVec>::value);
241     Mat dstOutT(src.cols, src.rows + 2, traits::Type<WorkVec>::value);
242 
243     dst = dstOut(Range::all(), Range(1, src.cols+1));
244     dstT = dstOutT(Range::all(), Range(1, src.rows+1));
245 
246     src.convertTo(dst, traits::Type<WorkVec>::value);
247 
248     WorkVec *line;
249     int ri = dstOut.cols - 1;
250     for (int i = 0; i < src.rows; i++)
251     {
252         line        = dstOut.ptr<WorkVec>(i);
253         line[0]     = line[1];
254         line[ri]    = line[ri - 1];
255     }
256 
257     WorkVec *topLine = dst.ptr<WorkVec>(0);
258     WorkVec *bottomLine = dst.ptr<WorkVec>(dst.rows - 1);
259     ri = dstOutT.cols - 1;
260     for (int i = 0; i < src.cols; i++)
261     {
262         line        = dstOutT.ptr<WorkVec>(i);
263         line[0]     = topLine[i];
264         line[ri]    = bottomLine[i];
265     }
266 }
267 
268 
269 template <typename WorkVec>
FilterNC_horPass(Mat & src_,Mat & idist_,Mat & dst_)270 DTFilterCPU::FilterNC_horPass<WorkVec>::FilterNC_horPass(Mat& src_, Mat& idist_, Mat& dst_)
271 : src(src_), idist(idist_), dst(dst_), radius(1.0f)
272 {
273     CV_DbgAssert(src.type() == traits::Type<WorkVec>::value && dst.type() == traits::Type<WorkVec>::value && dst.rows == src.cols && dst.cols == src.rows);
274 }
275 
276 template <typename WorkVec>
operator ()(const Range & range) const277 void DTFilterCPU::FilterNC_horPass<WorkVec>::operator()(const Range& range) const
278 {
279     #ifdef NC_USE_INTEGRAL_SRC
280     std::vector<WorkVec> isrcBuf(src.cols + 1);
281     WorkVec *isrcLine = &isrcBuf[0];
282     #endif
283 
284     for (int i = range.start; i < range.end; i++)
285     {
286         const WorkVec   *srcLine    = src.ptr<WorkVec>(i);
287         IDistType       *idistLine  = idist.ptr<IDistType>(i);
288         int leftBound = 0, rightBound = 0;
289         WorkVec sum;
290 
291         #ifdef NC_USE_INTEGRAL_SRC
292         integrateRow(srcLine, isrcLine, src.cols);
293         #else
294         sum = srcLine[0];
295         #endif
296 
297         for (int j = 0; j < src.cols; j++)
298         {
299             IDistType curVal = idistLine[j];
300             #ifdef NC_USE_INTEGRAL_SRC
301             leftBound  = getLeftBound(idistLine, leftBound, curVal - radius);
302             rightBound = getRightBound(idistLine, rightBound, curVal + radius);
303             sum = (isrcLine[rightBound + 1] - isrcLine[leftBound]);
304             #else
305             while (idistLine[leftBound] < curVal - radius)
306             {
307                 sum -= srcLine[leftBound];
308                 leftBound++;
309             }
310 
311             while (idistLine[rightBound + 1] < curVal + radius)
312             {
313                 rightBound++;
314                 sum += srcLine[rightBound];
315             }
316             #endif
317 
318             dst.at<WorkVec>(j, i) = sum / (float)(rightBound + 1 - leftBound);
319         }
320     }
321 }
322 
323 template <typename WorkVec>
FilterIC_horPass(Mat & src_,Mat & idist_,Mat & dist_,Mat & dst_)324 DTFilterCPU::FilterIC_horPass<WorkVec>::FilterIC_horPass(Mat& src_, Mat& idist_, Mat& dist_, Mat& dst_)
325 : src(src_), idist(idist_), dist(dist_), dst(dst_), radius(1.0f)
326 {
327     CV_DbgAssert(src.type() == traits::Type<WorkVec>::value && dst.type() == traits::Type<WorkVec>::value && dst.rows == src.cols && dst.cols == src.rows);
328 
329     #ifdef CV_GET_NUM_THREAD_WORKS_PROPERLY
330     isrcBuf.create(cv::getNumThreads(), src.cols + 1, traits::Type<WorkVec>::value);
331     #else
332     isrcBuf.create(src.rows, src.cols + 1, traits::Type<WorkVec>::value);
333     #endif
334 }
335 
336 template <typename WorkVec>
operator ()(const Range & range) const337 void DTFilterCPU::FilterIC_horPass<WorkVec>::operator()(const Range& range) const
338 {
339     #ifdef CV_GET_NUM_THREAD_WORKS_PROPERLY
340     WorkVec *isrcLine = const_cast<WorkVec*>( isrcBuf.ptr<WorkVec>(cv::getThreadNum()) );
341     #else
342     WorkVec *isrcLine = const_cast<WorkVec*>( isrcBuf.ptr<WorkVec>(range.start) );
343     #endif
344 
345     for (int i = range.start; i < range.end; i++)
346     {
347         WorkVec   *srcLine      = src.ptr<WorkVec>(i);
348         DistType  *distLine     = dist.ptr<DistType>(i);
349         IDistType *idistLine    = idist.ptr<IDistType>(i);
350 
351         integrateSparseRow(srcLine, distLine, isrcLine, src.cols);
352 
353         int leftBound = 0, rightBound = 0;
354         WorkVec sumL, sumR, sumC;
355 
356         srcLine[-1] = srcLine[0];
357         srcLine[src.cols] = srcLine[src.cols - 1];
358 
359         for (int j = 0; j < src.cols; j++)
360         {
361             IDistType curVal = idistLine[j];
362             IDistType valueLeft = curVal - radius;
363             IDistType valueRight = curVal + radius;
364 
365             leftBound = getLeftBound(idistLine, leftBound, valueLeft);
366             rightBound = getRightBound(idistLine, rightBound, valueRight);
367 
368             float areaL = idistLine[leftBound] - valueLeft;
369             float areaR = valueRight - idistLine[rightBound];
370             float dl = areaL / distLine[leftBound - 1];
371             float dr = areaR / distLine[rightBound];
372 
373             sumL = 0.5f*areaL*(dl*srcLine[leftBound - 1] + (2.0f - dl)*srcLine[leftBound]);
374             sumR = 0.5f*areaR*((2.0f - dr)*srcLine[rightBound] + dr*srcLine[rightBound + 1]);
375             sumC = isrcLine[rightBound] - isrcLine[leftBound];
376 
377             dst.at<WorkVec>(j, i) = (sumL + sumC + sumR) / (2.0f * radius);
378         }
379     }
380 }
381 
382 
383 template <typename WorkVec>
FilterRF_horPass(Mat & res_,Mat & alphaD_,int iteration_)384 DTFilterCPU::FilterRF_horPass<WorkVec>::FilterRF_horPass(Mat& res_, Mat& alphaD_, int iteration_)
385 : res(res_), alphaD(alphaD_), iteration(iteration_)
386 {
387     CV_DbgAssert(res.type() == traits::Type<WorkVec>::value);
388     CV_DbgAssert(res.type() == traits::Type<WorkVec>::value && res.size() == res.size());
389 }
390 
391 
392 template <typename WorkVec>
operator ()(const Range & range) const393 void DTFilterCPU::FilterRF_horPass<WorkVec>::operator()(const Range& range) const
394 {
395     for (int i = range.start; i < range.end; i++)
396     {
397         WorkVec     *dstLine = res.ptr<WorkVec>(i);
398         DistType    *adLine  = alphaD.ptr<DistType>(i);
399         int j;
400 
401         if (iteration > 1)
402         {
403             for (j = res.cols - 2; j >= 0; j--)
404                 adLine[j] *= adLine[j];
405         }
406 
407         for (j = 1; j < res.cols; j++)
408         {
409             dstLine[j] += adLine[j-1] * (dstLine[j-1] - dstLine[j]);
410         }
411 
412         for (j = res.cols - 2; j >= 0; j--)
413         {
414             dstLine[j] += adLine[j] * (dstLine[j+1] - dstLine[j]);
415         }
416     }
417 }
418 
419 
420 template <typename WorkVec>
FilterRF_vertPass(Mat & res_,Mat & alphaD_,int iteration_)421 DTFilterCPU::FilterRF_vertPass<WorkVec>::FilterRF_vertPass(Mat& res_, Mat& alphaD_, int iteration_)
422 : res(res_), alphaD(alphaD_), iteration(iteration_)
423 {
424     CV_DbgAssert(res.type() == traits::Type<WorkVec>::value);
425     CV_DbgAssert(res.type() == traits::Type<WorkVec>::value && res.size() == res.size());
426 }
427 
428 
429 template <typename WorkVec>
operator ()(const Range & range) const430 void DTFilterCPU::FilterRF_vertPass<WorkVec>::operator()(const Range& range) const
431 {
432     #ifdef CV_GET_NUM_THREAD_WORKS_PROPERLY
433     Range rcols = getWorkRangeByThread(res.cols, range);
434     #else
435     Range rcols = range;
436     #endif
437 
438     for (int i = 1; i < res.rows; i++)
439     {
440         WorkVec     *curRow  = res.ptr<WorkVec>(i);
441         WorkVec     *prevRow = res.ptr<WorkVec>(i - 1);
442         DistType    *adRow   = alphaD.ptr<DistType>(i - 1);
443 
444         if (iteration > 1)
445         {
446             for (int j = rcols.start; j < rcols.end; j++)
447                 adRow[j] *= adRow[j];
448         }
449 
450         for (int j = rcols.start; j < rcols.end; j++)
451         {
452             curRow[j] += adRow[j] * (prevRow[j] - curRow[j]);
453         }
454     }
455 
456     for (int i = res.rows - 2; i >= 0; i--)
457     {
458         WorkVec     *prevRow = res.ptr<WorkVec>(i + 1);
459         WorkVec     *curRow  = res.ptr<WorkVec>(i);
460         DistType    *adRow   = alphaD.ptr<DistType>(i);
461 
462         for (int j = rcols.start; j < rcols.end; j++)
463         {
464             curRow[j] += adRow[j] * (prevRow[j] - curRow[j]);
465         }
466     }
467 }
468 
469 template <typename GuideVec>
ComputeIDTHor_ParBody(DTFilterCPU & dtf_,Mat & guide_,Mat & dst_)470 DTFilterCPU::ComputeIDTHor_ParBody<GuideVec>::ComputeIDTHor_ParBody(DTFilterCPU& dtf_, Mat& guide_, Mat& dst_)
471 : dtf(dtf_), guide(guide_), dst(dst_)
472 {
473     dst.create(guide.rows, guide.cols + 1, traits::Type<IDistVec>::value);
474 }
475 
476 template <typename GuideVec>
operator ()(const Range & range) const477 void DTFilterCPU::ComputeIDTHor_ParBody<GuideVec>::operator()(const Range& range) const
478 {
479     for (int i = range.start; i < range.end; i++)
480     {
481         const GuideVec *guideLine   = guide.ptr<GuideVec>(i);
482         IDistType *idistLine        = dst.ptr<IDistType>(i);
483 
484         IDistType curDist   = (IDistType)0;
485         idistLine[0]        = (IDistType)0;
486 
487         for (int j = 1; j < guide.cols; j++)
488         {
489             curDist += dtf.getTransformedDistance(guideLine[j-1], guideLine[j]);
490             idistLine[j] = curDist;
491         }
492         idistLine[guide.cols] = std::numeric_limits<IDistType>::max();
493     }
494 }
495 
496 template <typename GuideVec>
ComputeDTandIDTHor_ParBody(DTFilterCPU & dtf_,Mat & guide_,Mat & dist_,Mat & idist_)497 DTFilterCPU::ComputeDTandIDTHor_ParBody<GuideVec>::ComputeDTandIDTHor_ParBody(DTFilterCPU& dtf_, Mat& guide_, Mat& dist_, Mat& idist_)
498 : dtf(dtf_), guide(guide_), dist(dist_), idist(idist_)
499 {
500     dist = getWExtendedMat(guide.rows, guide.cols, traits::Type<IDistVec>::value, 1, 1);
501     idist = getWExtendedMat(guide.rows, guide.cols + 1, traits::Type<IDistVec>::value);
502     maxRadius = dtf.getIterRadius(1);
503 }
504 
505 template <typename GuideVec>
operator ()(const Range & range) const506 void DTFilterCPU::ComputeDTandIDTHor_ParBody<GuideVec>::operator()(const Range& range) const
507 {
508     for (int i = range.start; i < range.end; i++)
509     {
510         const GuideVec  *guideLine  = guide.ptr<GuideVec>(i);
511               DistType  *distLine   = dist.ptr<DistType>(i);
512               IDistType *idistLine  = idist.ptr<IDistType>(i);
513 
514         DistType  curDist;
515         IDistType curIDist = (IDistType)0;
516         int j;
517 
518         distLine[-1] = maxRadius;
519         //idistLine[-1] = curIDist - maxRadius;
520         idistLine[0] = curIDist;
521         for (j = 0; j < guide.cols-1; j++)
522         {
523             curDist = (DistType) dtf.getTransformedDistance(guideLine[j], guideLine[j + 1]);
524             curIDist += curDist;
525 
526             distLine[j] = curDist;
527             idistLine[j + 1] = curIDist;
528         }
529         idistLine[j + 1] = curIDist + maxRadius;
530         distLine[j] = maxRadius;
531     }
532 }
533 
534 template <typename GuideVec>
ComputeA0DTHor_ParBody(DTFilterCPU & dtf_,Mat & guide_)535 DTFilterCPU::ComputeA0DTHor_ParBody<GuideVec>::ComputeA0DTHor_ParBody(DTFilterCPU& dtf_, Mat& guide_)
536 : dtf(dtf_), guide(guide_)
537 {
538     dtf.a0distHor.create(guide.rows, guide.cols - 1, traits::Type<DistVec>::value);
539     lna = std::log(dtf.getIterAlpha(1));
540 }
541 
542 template <typename GuideVec>
operator ()(const Range & range) const543 void DTFilterCPU::ComputeA0DTHor_ParBody<GuideVec>::operator()(const Range& range) const
544 {
545     for (int i = range.start; i < range.end; i++)
546     {
547         const GuideVec  *guideLine  = guide.ptr<GuideVec>(i);
548               DistType  *dstLine    = dtf.a0distHor.ptr<DistType>(i);
549 
550         for (int j = 0; j < guide.cols - 1; j++)
551         {
552             DistType d = (DistType)dtf.getTransformedDistance(guideLine[j], guideLine[j + 1]);
553             dstLine[j] = lna*d;
554         }
555     }
556 }
557 
558 template <typename GuideVec>
~ComputeA0DTHor_ParBody()559 DTFilterCPU::ComputeA0DTHor_ParBody<GuideVec>::~ComputeA0DTHor_ParBody()
560 {
561     cv::exp(dtf.a0distHor, dtf.a0distHor);
562 }
563 
564 template <typename GuideVec>
ComputeA0DTVert_ParBody(DTFilterCPU & dtf_,Mat & guide_)565 DTFilterCPU::ComputeA0DTVert_ParBody<GuideVec>::ComputeA0DTVert_ParBody(DTFilterCPU& dtf_, Mat& guide_)
566 : dtf(dtf_), guide(guide_)
567 {
568     dtf.a0distVert.create(guide.rows - 1, guide.cols, traits::Type<DistVec>::value);
569     lna = std::log(dtf.getIterAlpha(1));
570 }
571 
572 template <typename GuideVec>
operator ()(const Range & range) const573 void DTFilterCPU::ComputeA0DTVert_ParBody<GuideVec>::operator()(const Range& range) const
574 {
575     for (int i = range.start; i < range.end; i++)
576     {
577         DistType *dstLine = dtf.a0distVert.ptr<DistType>(i);
578         GuideVec *guideRow1 = guide.ptr<GuideVec>(i);
579         GuideVec *guideRow2 = guide.ptr<GuideVec>(i+1);
580 
581         for (int j = 0; j < guide.cols; j++)
582         {
583             DistType d = (DistType)dtf.getTransformedDistance(guideRow1[j], guideRow2[j]);
584             dstLine[j] = lna*d;
585         }
586     }
587 }
588 
589 template <typename GuideVec>
~ComputeA0DTVert_ParBody()590 DTFilterCPU::ComputeA0DTVert_ParBody<GuideVec>::~ComputeA0DTVert_ParBody()
591 {
592     cv::exp(dtf.a0distVert, dtf.a0distVert);
593 }
594 
595 
596 template<typename GuideVec, typename SrcVec>
domainTransformFilter(const Mat_<GuideVec> & guide,const Mat_<SrcVec> & source,Mat & dst,double sigmaSpatial,double sigmaColor,int mode,int numPasses)597 void domainTransformFilter( const Mat_<GuideVec>& guide,
598                             const Mat_<SrcVec>& source,
599                             Mat& dst,
600                             double sigmaSpatial, double sigmaColor,
601                             int mode, int numPasses
602                             )
603 {
604     DTFilterCPU *dtf = DTFilterCPU::create_p_<GuideVec>(guide, sigmaSpatial, sigmaColor, mode, numPasses);
605     dtf->filter_<SrcVec>(source, dst);
606     delete dtf;
607 }
608 
609 template<typename GuideVec, typename SrcVec>
domainTransformFilter(const Mat & guide,const Mat & source,Mat & dst,double sigmaSpatial,double sigmaColor,int mode,int numPasses)610 void domainTransformFilter( const Mat& guide,
611                             const Mat& source,
612                             Mat& dst,
613                             double sigmaSpatial, double sigmaColor,
614                             int mode, int numPasses
615                           )
616 {
617     DTFilterCPU *dtf = DTFilterCPU::create_p_<GuideVec>(guide, sigmaSpatial, sigmaColor, mode, numPasses);
618     dtf->filter_<SrcVec>(source, dst);
619     delete dtf;
620 }
621 
622 }
623 }
624 #endif
625