43
43
#include " precomp.hpp"
44
44
#include " opencl_kernels_stitching.hpp"
45
45
46
+ #ifdef HAVE_CUDA
47
+ namespace cv { namespace cuda { namespace device
48
+ {
49
+ namespace blend
50
+ {
51
+ void addSrcWeightGpu16S (const PtrStep<short > src, const PtrStep<short > src_weight,
52
+ PtrStep<short > dst, PtrStep<short > dst_weight, cv::Rect &rc);
53
+ void addSrcWeightGpu32F (const PtrStep<short > src, const PtrStepf src_weight,
54
+ PtrStep<short > dst, PtrStepf dst_weight, cv::Rect &rc);
55
+ void normalizeUsingWeightMapGpu16S (const PtrStep<short > weight, PtrStep<short > src,
56
+ const int width, const int height);
57
+ void normalizeUsingWeightMapGpu32F (const PtrStepf weight, PtrStep<short > src,
58
+ const int width, const int height);
59
+ }
60
+ }}}
61
+ #endif
62
+
46
63
namespace cv {
47
64
namespace detail {
48
65
@@ -228,21 +245,46 @@ void MultiBandBlender::prepare(Rect dst_roi)
228
245
229
246
Blender::prepare (dst_roi);
230
247
231
- dst_pyr_laplace_.resize (num_bands_ + 1 );
232
- dst_pyr_laplace_[0 ] = dst_;
248
+ #if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
249
+ if (can_use_gpu_)
250
+ {
251
+ gpu_dst_pyr_laplace_.resize (num_bands_ + 1 );
252
+ gpu_dst_pyr_laplace_[0 ].create (dst_roi.size (), CV_16SC3);
253
+ gpu_dst_pyr_laplace_[0 ].setTo (Scalar::all (0 ));
233
254
234
- dst_band_weights_ .resize (num_bands_ + 1 );
235
- dst_band_weights_ [0 ].create (dst_roi.size (), weight_type_);
236
- dst_band_weights_ [0 ].setTo (0 );
255
+ gpu_dst_band_weights_ .resize (num_bands_ + 1 );
256
+ gpu_dst_band_weights_ [0 ].create (dst_roi.size (), weight_type_);
257
+ gpu_dst_band_weights_ [0 ].setTo (0 );
237
258
238
- for (int i = 1 ; i <= num_bands_; ++i)
259
+ for (int i = 1 ; i <= num_bands_; ++i)
260
+ {
261
+ gpu_dst_pyr_laplace_[i].create ((gpu_dst_pyr_laplace_[i - 1 ].rows + 1 ) / 2 ,
262
+ (gpu_dst_pyr_laplace_[i - 1 ].cols + 1 ) / 2 , CV_16SC3);
263
+ gpu_dst_band_weights_[i].create ((gpu_dst_band_weights_[i - 1 ].rows + 1 ) / 2 ,
264
+ (gpu_dst_band_weights_[i - 1 ].cols + 1 ) / 2 , weight_type_);
265
+ gpu_dst_pyr_laplace_[i].setTo (Scalar::all (0 ));
266
+ gpu_dst_band_weights_[i].setTo (0 );
267
+ }
268
+ }
269
+ else
270
+ #endif
239
271
{
240
- dst_pyr_laplace_[i].create ((dst_pyr_laplace_[i - 1 ].rows + 1 ) / 2 ,
241
- (dst_pyr_laplace_[i - 1 ].cols + 1 ) / 2 , CV_16SC3);
242
- dst_band_weights_[i].create ((dst_band_weights_[i - 1 ].rows + 1 ) / 2 ,
243
- (dst_band_weights_[i - 1 ].cols + 1 ) / 2 , weight_type_);
244
- dst_pyr_laplace_[i].setTo (Scalar::all (0 ));
245
- dst_band_weights_[i].setTo (0 );
272
+ dst_pyr_laplace_.resize (num_bands_ + 1 );
273
+ dst_pyr_laplace_[0 ] = dst_;
274
+
275
+ dst_band_weights_.resize (num_bands_ + 1 );
276
+ dst_band_weights_[0 ].create (dst_roi.size (), weight_type_);
277
+ dst_band_weights_[0 ].setTo (0 );
278
+
279
+ for (int i = 1 ; i <= num_bands_; ++i)
280
+ {
281
+ dst_pyr_laplace_[i].create ((dst_pyr_laplace_[i - 1 ].rows + 1 ) / 2 ,
282
+ (dst_pyr_laplace_[i - 1 ].cols + 1 ) / 2 , CV_16SC3);
283
+ dst_band_weights_[i].create ((dst_band_weights_[i - 1 ].rows + 1 ) / 2 ,
284
+ (dst_band_weights_[i - 1 ].cols + 1 ) / 2 , weight_type_);
285
+ dst_pyr_laplace_[i].setTo (Scalar::all (0 ));
286
+ dst_band_weights_[i].setTo (0 );
287
+ }
246
288
}
247
289
}
248
290
@@ -312,6 +354,76 @@ void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
312
354
int bottom = br_new.y - tl.y - img.rows ;
313
355
int right = br_new.x - tl.x - img.cols ;
314
356
357
+ #if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
358
+ if (can_use_gpu_)
359
+ {
360
+ // Create the source image Laplacian pyramid
361
+ cuda::GpuMat gpu_img;
362
+ gpu_img.upload (img);
363
+ cuda::GpuMat img_with_border;
364
+ cuda::copyMakeBorder (gpu_img, img_with_border, top, bottom, left, right, BORDER_REFLECT);
365
+ std::vector<cuda::GpuMat> gpu_src_pyr_laplace (num_bands_ + 1 );
366
+ img_with_border.convertTo (gpu_src_pyr_laplace[0 ], CV_16S);
367
+ for (int i = 0 ; i < num_bands_; ++i)
368
+ cuda::pyrDown (gpu_src_pyr_laplace[i], gpu_src_pyr_laplace[i + 1 ]);
369
+ for (int i = 0 ; i < num_bands_; ++i)
370
+ {
371
+ cuda::GpuMat up;
372
+ cuda::pyrUp (gpu_src_pyr_laplace[i + 1 ], up);
373
+ cuda::subtract (gpu_src_pyr_laplace[i], up, gpu_src_pyr_laplace[i]);
374
+ }
375
+
376
+ // Create the weight map Gaussian pyramid
377
+ cuda::GpuMat gpu_mask;
378
+ gpu_mask.upload (mask);
379
+ cuda::GpuMat weight_map;
380
+ std::vector<cuda::GpuMat> gpu_weight_pyr_gauss (num_bands_ + 1 );
381
+
382
+ if (weight_type_ == CV_32F)
383
+ {
384
+ gpu_mask.convertTo (weight_map, CV_32F, 1 . / 255 .);
385
+ }
386
+ else // weight_type_ == CV_16S
387
+ {
388
+ gpu_mask.convertTo (weight_map, CV_16S);
389
+ cuda::GpuMat add_mask;
390
+ cuda::compare (gpu_mask, 0 , add_mask, CMP_NE);
391
+ cuda::add (weight_map, Scalar::all (1 ), weight_map, add_mask);
392
+ }
393
+ cuda::copyMakeBorder (weight_map, gpu_weight_pyr_gauss[0 ], top, bottom, left, right, BORDER_CONSTANT);
394
+ for (int i = 0 ; i < num_bands_; ++i)
395
+ cuda::pyrDown (gpu_weight_pyr_gauss[i], gpu_weight_pyr_gauss[i + 1 ]);
396
+
397
+ int y_tl = tl_new.y - dst_roi_.y ;
398
+ int y_br = br_new.y - dst_roi_.y ;
399
+ int x_tl = tl_new.x - dst_roi_.x ;
400
+ int x_br = br_new.x - dst_roi_.x ;
401
+
402
+ // Add weighted layer of the source image to the final Laplacian pyramid layer
403
+ for (int i = 0 ; i <= num_bands_; ++i)
404
+ {
405
+ Rect rc (x_tl, y_tl, x_br - x_tl, y_br - y_tl);
406
+ cuda::GpuMat &_src_pyr_laplace = gpu_src_pyr_laplace[i];
407
+ cuda::GpuMat _dst_pyr_laplace = gpu_dst_pyr_laplace_[i](rc);
408
+ cuda::GpuMat &_weight_pyr_gauss = gpu_weight_pyr_gauss[i];
409
+ cuda::GpuMat _dst_band_weights = gpu_dst_band_weights_[i](rc);
410
+
411
+ using namespace cv ::cuda::device::blend;
412
+ if (weight_type_ == CV_32F)
413
+ {
414
+ addSrcWeightGpu32F (_src_pyr_laplace, _weight_pyr_gauss, _dst_pyr_laplace, _dst_band_weights, rc);
415
+ }
416
+ else
417
+ {
418
+ addSrcWeightGpu16S (_src_pyr_laplace, _weight_pyr_gauss, _dst_pyr_laplace, _dst_band_weights, rc);
419
+ }
420
+ x_tl /= 2 ; y_tl /= 2 ;
421
+ x_br /= 2 ; y_br /= 2 ;
422
+ }
423
+ return ;
424
+ }
425
+ #endif
426
+
315
427
// Create the source image Laplacian pyramid
316
428
UMat img_with_border;
317
429
copyMakeBorder (_img, img_with_border, top, bottom, left, right,
@@ -322,10 +434,7 @@ void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
322
434
#endif
323
435
324
436
std::vector<UMat> src_pyr_laplace;
325
- if (can_use_gpu_ && img_with_border.depth () == CV_16S)
326
- createLaplacePyrGpu (img_with_border, num_bands_, src_pyr_laplace);
327
- else
328
- createLaplacePyr (img_with_border, num_bands_, src_pyr_laplace);
437
+ createLaplacePyr (img_with_border, num_bands_, src_pyr_laplace);
329
438
330
439
LOGLN (" Create the source image Laplacian pyramid, time: " << ((getTickCount () - t) / getTickFrequency ()) << " sec" );
331
440
#if ENABLE_LOG
@@ -431,20 +540,57 @@ void MultiBandBlender::feed(InputArray _img, InputArray mask, Point tl)
431
540
432
541
void MultiBandBlender::blend (InputOutputArray dst, InputOutputArray dst_mask)
433
542
{
434
- for ( int i = 0 ; i <= num_bands_; ++i)
435
- normalizeUsingWeightMap (dst_band_weights_[i], dst_pyr_laplace_[i] );
436
-
543
+ cv::UMat dst_band_weights_0;
544
+ Rect dst_rc ( 0 , 0 , dst_roi_final_. width , dst_roi_final_. height );
545
+ # if defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING)
437
546
if (can_use_gpu_)
438
- restoreImageFromLaplacePyrGpu (dst_pyr_laplace_);
547
+ {
548
+ for (int i = 0 ; i <= num_bands_; ++i)
549
+ {
550
+ cuda::GpuMat dst_i = gpu_dst_pyr_laplace_[i];
551
+ cuda::GpuMat weight_i = gpu_dst_band_weights_[i];
552
+
553
+ using namespace ::cv::cuda::device::blend;
554
+ if (weight_type_ == CV_32F)
555
+ {
556
+ normalizeUsingWeightMapGpu32F (weight_i, dst_i, weight_i.cols , weight_i.rows );
557
+ }
558
+ else
559
+ {
560
+ normalizeUsingWeightMapGpu16S (weight_i, dst_i, weight_i.cols , weight_i.rows );
561
+ }
562
+ }
563
+
564
+ // Restore image from Laplacian pyramid
565
+ for (size_t i = num_bands_; i > 0 ; --i)
566
+ {
567
+ cuda::GpuMat up;
568
+ cuda::pyrUp (gpu_dst_pyr_laplace_[i], up);
569
+ cuda::add (up, gpu_dst_pyr_laplace_[i - 1 ], gpu_dst_pyr_laplace_[i - 1 ]);
570
+ }
571
+
572
+ gpu_dst_pyr_laplace_[0 ](dst_rc).download (dst_);
573
+ gpu_dst_band_weights_[0 ].download (dst_band_weights_0);
574
+
575
+ gpu_dst_pyr_laplace_.clear ();
576
+ gpu_dst_band_weights_.clear ();
577
+ }
439
578
else
579
+ #endif
580
+ {
581
+ for (int i = 0 ; i <= num_bands_; ++i)
582
+ normalizeUsingWeightMap (dst_band_weights_[i], dst_pyr_laplace_[i]);
583
+
440
584
restoreImageFromLaplacePyr (dst_pyr_laplace_);
441
585
442
- Rect dst_rc (0 , 0 , dst_roi_final_.width , dst_roi_final_.height );
443
- dst_ = dst_pyr_laplace_[0 ](dst_rc);
444
- UMat _dst_mask;
445
- compare (dst_band_weights_[0 ](dst_rc), WEIGHT_EPS, dst_mask_, CMP_GT);
446
- dst_pyr_laplace_.clear ();
447
- dst_band_weights_.clear ();
586
+ dst_ = dst_pyr_laplace_[0 ](dst_rc);
587
+ dst_band_weights_0 = dst_band_weights_[0 ];
588
+
589
+ dst_pyr_laplace_.clear ();
590
+ dst_band_weights_.clear ();
591
+ }
592
+
593
+ compare (dst_band_weights_0 (dst_rc), WEIGHT_EPS, dst_mask_, CMP_GT);
448
594
449
595
Blender::blend (dst, dst_mask);
450
596
}
0 commit comments