Skip to content

Commit 076a4e5

Browse files
committed
bilateral filter
1 parent c33d7f2 commit 076a4e5

4 files changed

Lines changed: 119 additions & 65 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}
166166
--expt-relaxed-constexpr
167167
--expt-extended-lambda
168168
--default-stream per-thread
169+
--use_fast_math
169170
-Xcudafe "--diag_suppress=integer_sign_change"
170171
-Xcudafe "--diag_suppress=partial_override"
171172
-Xcudafe "--diag_suppress=virtual_function_decl_hidden")

src/cupoch/geometry/image.cu

Lines changed: 87 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -33,52 +33,32 @@ std::pair<utility::device_vector<float>, utility::device_vector<float>>
3333
GetFilterKernel(Image::FilterType ftype) {
3434
switch (ftype) {
3535
case Image::FilterType::Gaussian3: {
36-
utility::device_vector<float> g3(3);
37-
g3[0] = 0.25;
38-
g3[1] = 0.5;
39-
g3[2] = 0.25;
36+
const float k[3] = {0.25, 0.5, 0.25};
37+
utility::device_vector<float> g3(k, k + 3);
4038
return std::make_pair(g3, g3);
4139
}
4240
case Image::FilterType::Gaussian5: {
43-
utility::device_vector<float> g5(5);
44-
g5[0] = 0.0625;
45-
g5[1] = 0.25;
46-
g5[2] = 0.375;
47-
g5[3] = 0.25;
48-
g5[4] = 0.0625;
41+
const float k[5] = {0.0625, 0.25, 0.375, 0.25, 0.0625};
42+
utility::device_vector<float> g5(k, k + 5);
4943
return std::make_pair(g5, g5);
5044
}
5145
case Image::FilterType::Gaussian7: {
52-
utility::device_vector<float> g7(7);
53-
g7[0] = 0.03125;
54-
g7[1] = 0.109375;
55-
g7[2] = 0.21875;
56-
g7[3] = 0.28125;
57-
g7[4] = 0.21875;
58-
g7[5] = 0.109375;
59-
g7[6] = 0.03125;
46+
const float k[7] = {0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125};
47+
utility::device_vector<float> g7(k, k + 7);
6048
return std::make_pair(g7, g7);
6149
}
6250
case Image::FilterType::Sobel3Dx: {
63-
utility::device_vector<float> s31(3);
64-
utility::device_vector<float> s32(3);
65-
s31[0] = -1.0;
66-
s31[1] = 0.0;
67-
s31[2] = 1.0;
68-
s32[0] = 1.0;
69-
s32[1] = 2.0;
70-
s32[2] = 1.0;
51+
const float k1[3] = {-1.0, 0.0, 1.0};
52+
const float k2[3] = {1.0, 2.0, 1.0};
53+
utility::device_vector<float> s31(k1, k1 + 3);
54+
utility::device_vector<float> s32(k2, k2 + 3);
7155
return std::make_pair(s31, s32);
7256
}
7357
case Image::FilterType::Sobel3Dy: {
74-
utility::device_vector<float> s31(3);
75-
utility::device_vector<float> s32(3);
76-
s31[0] = -1.0;
77-
s31[1] = 0.0;
78-
s31[2] = 1.0;
79-
s32[0] = 1.0;
80-
s32[1] = 2.0;
81-
s32[2] = 1.0;
58+
const float k1[3] = {-1.0, 0.0, 1.0};
59+
const float k2[3] = {1.0, 2.0, 1.0};
60+
utility::device_vector<float> s31(k1, k1 + 3);
61+
utility::device_vector<float> s32(k2, k2 + 3);
8262
return std::make_pair(s32, s31);
8363
}
8464
default: {
@@ -185,9 +165,7 @@ struct filter_horizontal_functor {
185165
float *po = (float *)(dst_ + idx * sizeof(float));
186166
float temp = 0;
187167
for (int i = -half_kernel_size_; i <= half_kernel_size_; i++) {
188-
int x_shift = x + i;
189-
if (x_shift < 0) x_shift = 0;
190-
if (x_shift > width_ - 1) x_shift = width_ - 1;
168+
int x_shift = min(max(0, x + i), width_ - 1);
191169
float *pi =
192170
(float *)(src_ + (y * width_ + x_shift) * sizeof(float));
193171
temp += (*pi * kernel_[i + half_kernel_size_]);
@@ -243,6 +221,52 @@ struct horizontal_flip_functor {
243221
}
244222
};
245223

224+
struct bilateral_filter_functor {
225+
bilateral_filter_functor(const uint8_t *src,
226+
int width,
227+
int height,
228+
int diameter,
229+
float sigma_color,
230+
const float* gaussian_const,
231+
uint8_t *dst)
232+
: src_(src),
233+
width_(width),
234+
height_(height),
235+
diameter_(diameter),
236+
sigma_color_(sigma_color),
237+
gaussian_const_(gaussian_const),
238+
dst_(dst){};
239+
const uint8_t *src_;
240+
const int width_;
241+
const int height_;
242+
const int diameter_;
243+
const float sigma_color_;
244+
const float* gaussian_const_;
245+
uint8_t *dst_;
246+
__device__ float gaussian(float x, float sig) const {
247+
return exp(-(powf(x, 2)) / (2 * powf(sig, 2)));
248+
}
249+
__device__ void operator() (size_t idx) {
250+
const int y = idx / width_;
251+
const int x = idx % width_;
252+
float filtered = 0;
253+
float total_w = 0;
254+
float center_p = *(float *)(src_ + idx * sizeof(float));
255+
for (int dy = -diameter_; dy <= diameter_; dy++) {
256+
for (int dx = -diameter_; dx <= diameter_; dx++) {
257+
int mdy = min(max(0, dy), height_);
258+
int mdx = min(max(0, dx), width_);
259+
float cur_p = *(float *)(src_ + ((y + mdy) * width_ + x + mdx) * sizeof(float));
260+
float w = gaussian_const_[dy + diameter_] * gaussian_const_[dx + diameter_] * gaussian(center_p - cur_p, sigma_color_);
261+
filtered += w * cur_p;
262+
total_w += w;
263+
}
264+
}
265+
float* p = (float *)(dst_ + idx * sizeof(float));
266+
*p = filtered / total_w;
267+
}
268+
};
269+
246270
struct depth_to_float_functor {
247271
depth_to_float_functor(int depth_scale, int depth_trunc)
248272
: depth_scale_(depth_scale),
@@ -483,6 +507,32 @@ std::shared_ptr<Image> Image::FlipHorizontal() const {
483507
return output;
484508
}
485509

510+
std::shared_ptr<Image> Image::BilateralFilter(
511+
int diameter, float sigma_color, float sigma_space) const {
512+
auto output = std::make_shared<Image>();
513+
if (diameter >= 64) {
514+
utility::LogError("[BilateralFilter] Diameter should be less than 64.");
515+
return output;
516+
}
517+
output->Prepare(width_, height_, num_of_channels_, bytes_per_channel_);
518+
float fgaussian[64];
519+
const float sigma2 = sigma_space * sigma_space;
520+
for (int i = 0; i < 2 * diameter + 1; i++) {
521+
const float x = i - diameter;
522+
fgaussian[i] = std::exp(-(x * x) / (2 * sigma2));
523+
}
524+
utility::device_vector<float> gaussian_const(fgaussian, fgaussian + 64);
525+
bilateral_filter_functor func(
526+
thrust::raw_pointer_cast(data_.data()), width_,
527+
height_, diameter, sigma_color,
528+
thrust::raw_pointer_cast(gaussian_const.data()),
529+
thrust::raw_pointer_cast(output->data_.data()));
530+
thrust::for_each(thrust::make_counting_iterator<size_t>(0),
531+
thrust::make_counting_iterator<size_t>(width_ * height_),
532+
func);
533+
return output;
534+
}
535+
486536
void Image::AllocateDataBuffer() {
487537
data_.resize(width_ * height_ * num_of_channels_ * bytes_per_channel_);
488538
}

src/cupoch/geometry/image.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ class Image : public GeometryBase<2> {
170170
std::shared_ptr<Image> FilterHorizontal(
171171
const utility::device_vector<float> &kernel) const;
172172

173+
std::shared_ptr<Image> BilateralFilter(
174+
int diameter, float sigma_color, float sigma_space) const;
175+
173176
/// Function to 2x image downsample using simple 2x2 averaging.
174177
std::shared_ptr<Image> Downsample() const;
175178

src/tests/geometry/image.cpp

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,14 @@ void TEST_CreateFloatImage(
228228
TEST(Image, CreateFloatImage_1_1) {
229229
// reference data used to validate the creation of the float image
230230
uint8_t raw_ref[] = {
231-
215, 214, 86, 63, 201, 200, 200, 62, 200, 199, 71, 63, 204,
232-
203, 75, 63, 233, 232, 104, 63, 201, 200, 72, 62, 171, 170,
233-
170, 62, 196, 195, 67, 63, 141, 140, 140, 62, 142, 141, 13,
234-
63, 243, 242, 242, 62, 161, 160, 32, 63, 187, 186, 186, 62,
235-
131, 130, 2, 63, 243, 242, 114, 63, 234, 233, 105, 63, 163,
231+
216, 214, 86, 63, 202, 200, 200, 62, 201, 199, 71, 63, 205,
232+
203, 75, 63, 234, 232, 104, 63, 202, 200, 72, 62, 171, 170,
233+
170, 62, 197, 195, 67, 63, 141, 140, 140, 62, 142, 141, 13,
234+
63, 244, 242, 242, 62, 161, 160, 32, 63, 187, 186, 186, 62,
235+
131, 130, 2, 63, 244, 242, 114, 63, 235, 233, 105, 63, 163,
236236
162, 34, 63, 183, 182, 54, 63, 145, 144, 16, 62, 155, 154,
237-
26, 63, 129, 128, 128, 60, 245, 244, 116, 62, 137, 136, 8,
238-
62, 206, 205, 77, 63, 157, 156, 28, 62};
237+
26, 63, 129, 128, 128, 60, 246, 244, 116, 62, 137, 136, 8,
238+
62, 207, 205, 77, 63, 157, 156, 28, 62};
239239
thrust::host_vector<uint8_t> ref;
240240
for (int i = 0; i < 100; ++i) ref.push_back(raw_ref[i]);
241241

@@ -278,13 +278,13 @@ TEST(Image, CreateFloatImage_1_4) {
278278
TEST(Image, CreateFloatImage_3_1_Weighted) {
279279
// reference data used to validate the creation of the float image
280280
uint8_t raw_ref[] = {
281-
44, 241, 17, 63, 29, 96, 75, 63, 154, 112, 20, 63, 255,
282-
240, 3, 63, 180, 56, 4, 63, 139, 60, 58, 63, 115, 8,
283-
204, 62, 215, 59, 119, 62, 64, 47, 151, 62, 251, 20, 36,
284-
63, 194, 101, 54, 63, 138, 51, 5, 63, 54, 35, 64, 63,
285-
94, 59, 32, 63, 28, 161, 44, 63, 137, 77, 46, 63, 199,
286-
12, 35, 63, 121, 21, 90, 62, 100, 168, 243, 62, 209, 97,
287-
143, 62, 9, 228, 61, 63, 223, 255, 239, 62, 58, 33, 29,
281+
45, 241, 17, 63, 30, 96, 75, 63, 154, 112, 20, 63, 0,
282+
241, 3, 63, 180, 56, 4, 63, 139, 60, 58, 63, 116, 8,
283+
204, 62, 216, 59, 119, 62, 65, 47, 151, 62, 252, 20, 36,
284+
63, 194, 101, 54, 63, 138, 51, 5, 63, 55, 35, 64, 63,
285+
95, 59, 32, 63, 29, 161, 44, 63, 137, 77, 46, 63, 199,
286+
12, 35, 63, 122, 21, 90, 62, 101, 168, 243, 62, 209, 97,
287+
143, 62, 10, 228, 61, 63, 224, 255, 239, 62, 59, 33, 29,
288288
63, 197, 186, 3, 63, 145, 27, 72, 63};
289289
thrust::host_vector<uint8_t> ref;
290290
for (int i = 0; i < 100; ++i) ref.push_back(raw_ref[i]);
@@ -295,13 +295,13 @@ TEST(Image, CreateFloatImage_3_1_Weighted) {
295295
TEST(Image, CreateFloatImage_3_1_Equal) {
296296
// reference data used to validate the creation of the float image
297297
uint8_t raw_ref[] = {
298-
44, 241, 17, 63, 29, 96, 75, 63, 154, 112, 20, 63, 255,
299-
240, 3, 63, 180, 56, 4, 63, 139, 60, 58, 63, 115, 8,
300-
204, 62, 215, 59, 119, 62, 64, 47, 151, 62, 251, 20, 36,
301-
63, 194, 101, 54, 63, 138, 51, 5, 63, 54, 35, 64, 63,
302-
94, 59, 32, 63, 28, 161, 44, 63, 137, 77, 46, 63, 199,
303-
12, 35, 63, 121, 21, 90, 62, 100, 168, 243, 62, 209, 97,
304-
143, 62, 9, 228, 61, 63, 223, 255, 239, 62, 58, 33, 29,
298+
45, 241, 17, 63, 30, 96, 75, 63, 154, 112, 20, 63, 0,
299+
241, 3, 63, 180, 56, 4, 63, 139, 60, 58, 63, 116, 8,
300+
204, 62, 216, 59, 119, 62, 65, 47, 151, 62, 252, 20, 36,
301+
63, 194, 101, 54, 63, 138, 51, 5, 63, 55, 35, 64, 63,
302+
95, 59, 32, 63, 29, 161, 44, 63, 137, 77, 46, 63, 199,
303+
12, 35, 63, 122, 21, 90, 62, 101, 168, 243, 62, 209, 97,
304+
143, 62, 10, 228, 61, 63, 224, 255, 239, 62, 59, 33, 29,
305305
63, 197, 186, 3, 63, 145, 27, 72, 63};
306306
thrust::host_vector<uint8_t> ref;
307307
for (int i = 0; i < 100; ++i) ref.push_back(raw_ref[i]);
@@ -380,14 +380,14 @@ TEST(Image, CreateFloatImage_3_4_Equal) {
380380
TEST(Image, ConvertDepthToFloatImage) {
381381
// reference data used to validate the creation of the float image
382382
uint8_t raw_ref[] = {
383-
208, 254, 91, 58, 103, 154, 205, 57, 59, 147, 76, 58, 236,
384-
175, 80, 58, 232, 127, 110, 58, 103, 154, 77, 57, 62, 195,
385-
174, 57, 139, 118, 72, 58, 22, 236, 143, 57, 66, 243, 16,
386-
58, 161, 199, 248, 57, 134, 123, 36, 58, 255, 53, 191, 57,
387-
93, 164, 5, 58, 161, 199, 120, 58, 20, 135, 111, 58, 222,
383+
210, 254, 91, 58, 105, 154, 205, 57, 61, 147, 76, 58, 237,
384+
175, 80, 58, 234, 127, 110, 58, 105, 154, 77, 57, 63, 195,
385+
174, 57, 141, 118, 72, 58, 22, 236, 143, 57, 66, 243, 16,
386+
58, 163, 199, 248, 57, 135, 123, 36, 58, 0, 54, 191, 57,
387+
94, 164, 5, 58, 163, 199, 120, 58, 22, 135, 111, 58, 223,
388388
137, 38, 58, 79, 25, 59, 58, 198, 8, 20, 57, 126, 80,
389-
30, 58, 5, 150, 131, 55, 249, 213, 122, 57, 101, 207, 11,
390-
57, 68, 190, 82, 58, 214, 94, 32, 57};
389+
30, 58, 6, 150, 131, 55, 251, 213, 122, 57, 102, 207, 11,
390+
57, 69, 190, 82, 58, 215, 94, 32, 57};
391391
thrust::host_vector<uint8_t> ref;
392392
for (int i = 0; i < 100; ++i) ref.push_back(raw_ref[i]);
393393
geometry::Image image;

0 commit comments

Comments
 (0)