ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
gpu_mat_ref_image.cu
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include <iostream>
9 
10 #include "mvs/gpu_mat_ref_image.h"
11 #include "util/cudacc.h"
12 
13 namespace colmap {
14 namespace mvs {
15 namespace {
16 
17 __global__ void FilterKernel(const cudaTextureObject_t image_texture,
18  GpuMat<uint8_t> image,
19  GpuMat<float> sum_image,
20  GpuMat<float> squared_sum_image,
21  const int window_radius,
22  const int window_step,
23  const float sigma_spatial,
24  const float sigma_color) {
25  const size_t row = blockDim.y * blockIdx.y + threadIdx.y;
26  const size_t col = blockDim.x * blockIdx.x + threadIdx.x;
27  if (row >= image.GetHeight() || col >= image.GetWidth()) {
28  return;
29  }
30 
31  BilateralWeightComputer bilateral_weight_computer(sigma_spatial,
32  sigma_color);
33 
34  const float center_color = tex2D<float>(image_texture, col, row);
35 
36  float color_sum = 0.0f;
37  float color_squared_sum = 0.0f;
38  float bilateral_weight_sum = 0.0f;
39 
40  for (int window_row = -window_radius; window_row <= window_radius;
41  window_row += window_step) {
42  for (int window_col = -window_radius; window_col <= window_radius;
43  window_col += window_step) {
44  const float color = tex2D<float>(image_texture, col + window_col,
45  row + window_row);
46  const float bilateral_weight = bilateral_weight_computer.Compute(
47  window_row, window_col, center_color, color);
48  color_sum += bilateral_weight * color;
49  color_squared_sum += bilateral_weight * color * color;
50  bilateral_weight_sum += bilateral_weight;
51  }
52  }
53 
54  color_sum /= bilateral_weight_sum;
55  color_squared_sum /= bilateral_weight_sum;
56 
57  image.Set(row, col, static_cast<uint8_t>(255.0f * center_color));
58  sum_image.Set(row, col, color_sum);
59  squared_sum_image.Set(row, col, color_squared_sum);
60 }
61 
62 } // namespace
63 
64 GpuMatRefImage::GpuMatRefImage(const size_t width, const size_t height)
65  : width_(width), height_(height) {
66  image.reset(new GpuMat<uint8_t>(width, height));
67  sum_image.reset(new GpuMat<float>(width, height));
68  squared_sum_image.reset(new GpuMat<float>(width, height));
69 }
70 
71 void GpuMatRefImage::Filter(const uint8_t* image_data,
72  const size_t window_radius,
73  const size_t window_step,
74  const float sigma_spatial,
75  const float sigma_color) {
76  cudaTextureDesc texture_desc;
77  memset(&texture_desc, 0, sizeof(texture_desc));
78  texture_desc.addressMode[0] = cudaAddressModeBorder;
79  texture_desc.addressMode[1] = cudaAddressModeBorder;
80  texture_desc.addressMode[2] = cudaAddressModeBorder;
81  texture_desc.filterMode = cudaFilterModePoint;
82  texture_desc.readMode = cudaReadModeNormalizedFloat;
83  texture_desc.normalizedCoords = false;
84  auto image_texture = CudaArrayLayeredTexture<uint8_t>::FromHostArray(
85  texture_desc, width_, height_, 1, image_data);
86 
87  const dim3 block_size(kBlockDimX, kBlockDimY);
88  const dim3 grid_size((width_ - 1) / block_size.x + 1,
89  (height_ - 1) / block_size.y + 1);
90 
91  FilterKernel<<<grid_size, block_size>>>(
92  image_texture->GetObj(), *image, *sum_image, *squared_sum_image,
93  window_radius, window_step, sigma_spatial, sigma_color);
94  CUDA_SYNC_AND_CHECK();
95 }
96 
97 } // namespace mvs
98 } // namespace colmap