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