Repository: Project-MONAI/MONAI

Issue:
Efficient, differentiable bilateral filter
**Is your feature request related to a problem? Please describe.**
This would be a useful tool to have in the box, both on its own or part of a larger algorithm such as #315

similar issue for more context... 
https://github.com/kornia/kornia/issues/702

**Describe the solution you'd like**
Would be nice to have an implementation which can operate on arbitrary spatial dimensions and channels. 
Due to the high computational load I think dropping down to c++ and cuda could be worth the extra work. 



Discussion:

Resolving patch:
diff --git a/monai/networks/layers/__init__.py b/monai/networks/layers/__init__.py
--- a/monai/networks/layers/__init__.py
+++ b/monai/networks/layers/__init__.py
@@ -11,5 +11,6 @@
 
 from .convutils import *
 from .factories import *
+from .filtering import *
 from .simplelayers import *
 from .spatial_transforms import *
diff --git a/monai/networks/layers/filtering.py b/monai/networks/layers/filtering.py
new file mode 100644
--- /dev/null
+++ b/monai/networks/layers/filtering.py
@@ -0,0 +1,58 @@
+# Copyright 2020 MONAI Consortium
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#     http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import torch
+
+from monai.utils.module import optional_import
+
+_C, _ = optional_import("monai._C")
+
+__all__ = ["BilateralFilter"]
+
+
+class BilateralFilter(torch.autograd.Function):
+    """
+    Blurs the input tensor spatially whilst preserving edges. Can run on 1D, 2D, or 3D,
+    tensors (on top of Batch and Channel dimensions). Two implementations are provided,
+    an exact solution and a much faster approximation which uses a permutohedral lattice.
+
+    See:
+        https://en.wikipedia.org/wiki/Bilateral_filter
+        https://graphics.stanford.edu/papers/permutohedral/
+
+    Args:
+        input: input tensor.
+
+        spatial sigma: the standard deviation of the spatial blur. Higher values can
+            hurt performace when not using the approximate method (see fast approx).
+
+        color sigma: the standard deviation of the color blur. Lower values preserve
+            edges better whilst higher values tend to a simple gaussian spatial blur.
+
+        fast approx: This flag chooses between two implementations. The approximate method may
+            produce artifacts in some scenarios whereas the exact solution may be intolerably
+            slow for high spatial standard deviations.
+
+    Returns:
+        output (torch.Tensor): output tensor.
+    """
+
+    @staticmethod
+    def forward(ctx, input, spatial_sigma=5, color_sigma=0.5, fast_approx=True):
+        ctx.save_for_backward(spatial_sigma, color_sigma, fast_approx)
+        output_data = _C.bilateral_filter(input, spatial_sigma, color_sigma, fast_approx)
+        return output_data
+
+    @staticmethod
+    def backward(ctx, grad_output):
+        spatial_sigma, color_sigma, fast_approx = ctx.saved_variables
+        grad_input = _C.bilateral_filter(grad_output, spatial_sigma, color_sigma, fast_approx)
+        return grad_input


Test patch:
diff --git a/tests/test_bilateral_approx_cpu.py b/tests/test_bilateral_approx_cpu.py
new file mode 100644
--- /dev/null
+++ b/tests/test_bilateral_approx_cpu.py
@@ -0,0 +1,381 @@
+# Copyright 2020 MONAI Consortium
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#     http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+import numpy as np
+import torch
+from parameterized import parameterized
+
+from monai.networks.layers.filtering import BilateralFilter
+from tests.utils import skip_if_no_cpp_extention
+
+TEST_CASES = [
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, low spatial sigma, low color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.2),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1.000000, 0.000000, 0.000000, 0.000000, 1.000000]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.000000, 0.000000, 1.000000, 0.000000, 0.000000]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, low spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.631360, 0.099349, 0.070177, 0.164534, 0.649869]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.052271, 0.173599, 0.481337, 0.183721, 0.045619]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, high spatial sigma, low color sigma",
+        # Spatial and Color Sigmas
+        (4, 0.2),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1.000000, 0.000000, 0.000000, 0.000000, 1.000000]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.000000, 0.000000, 1.000000, 0.000000, 0.000000]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.497667, 0.268683, 0.265026, 0.261467, 0.495981]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.145959, 0.142282, 0.315710, 0.135609, 0.132572]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 4 channel, low spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 0],
+                # Channel 1
+                [1, 0, 1, 0, 0],
+                # Channel 2
+                [0, 0, 1, 0, 1],
+                # Channel 3
+                [0, 0, 0, 0, 1],
+            ]
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.960843, 0.073540, 0.027689, 0.002676, 0.000000],
+                # Channel 1
+                [0.960843, 0.073540, 0.951248, 0.003033, 0.000750],
+                # Channel 2
+                [0.000000, 0.000000, 0.923559, 0.000357, 0.981324],
+                # Channel 3
+                [0.000000, 0.000000, 0.000000, 0.000000, 0.980574],
+            ]
+        ],
+    ],
+    [
+        # Case Descirption
+        "2 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    [0.213684, 0.094356, 0.092973, 0.091650, 0.216281],
+                    [0.094085, 0.092654, 0.091395, 0.090186, 0.089302],
+                    [0.092436, 0.091150, 0.090008, 0.088896, 0.088897],
+                    [0.090849, 0.089717, 0.088759, 0.087751, 0.088501],
+                    [0.211458, 0.088334, 0.087495, 0.087049, 0.212173],
+                ]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [
+                    [0.033341, 0.031314, 0.029367, 0.027494, 0.025692],
+                    [0.031869, 0.030632, 0.028820, 0.027074, 0.025454],
+                    [0.030455, 0.029628, 0.084257, 0.026704, 0.025372],
+                    [0.029095, 0.028391, 0.027790, 0.026375, 0.025292],
+                    [0.027786, 0.027197, 0.026692, 0.026181, 0.025213],
+                ]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "2 dimension, 4 channel, high spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 1]],
+                # Channel 1
+                [[1, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 1]],
+                # Channel 2
+                [[0, 0, 1, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 1, 0, 0]],
+                # Channel 3
+                [[0, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 0]],
+            ]
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    [0.244373, 0.014488, 0.036589, 0.014226, 0.024329],
+                    [0.014108, 0.014228, 0.014096, 0.013961, 0.013823],
+                    [0.013574, 0.013757, 0.013836, 0.013699, 0.013558],
+                    [0.013008, 0.013211, 0.013404, 0.013438, 0.013295],
+                    [0.025179, 0.012634, 0.034555, 0.013050, 0.237582],
+                ],
+                # Channel 1
+                [
+                    [0.271496, 0.015547, 0.439432, 0.015700, 0.089579],
+                    [0.015252, 0.015702, 0.015779, 0.015859, 0.015940],
+                    [0.015020, 0.015556, 0.015935, 0.016015, 0.016098],
+                    [0.014774, 0.015331, 0.015860, 0.016171, 0.016255],
+                    [0.107384, 0.015094, 0.462471, 0.016166, 0.263480],
+                ],
+                # Channel 2
+                [
+                    [0.027123, 0.003527, 0.467273, 0.004912, 0.645776],
+                    [0.003810, 0.004908, 0.005605, 0.006319, 0.007050],
+                    [0.004816, 0.005991, 0.006989, 0.007716, 0.008459],
+                    [0.005880, 0.007060, 0.008179, 0.009101, 0.009858],
+                    [0.633398, 0.008191, 0.496893, 0.010376, 0.025898],
+                ],
+                # Channel 3
+                [
+                    [0.000000, 0.002468, 0.064430, 0.003437, 0.580526],
+                    [0.002666, 0.003434, 0.003922, 0.004422, 0.004933],
+                    [0.003370, 0.004192, 0.004890, 0.005399, 0.005919],
+                    [0.004115, 0.004940, 0.005723, 0.006368, 0.006898],
+                    [0.551194, 0.005731, 0.068977, 0.007260, 0.000000],
+                ],
+            ]
+        ],
+    ],
+    [
+        # Case Descirption
+        "3 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    # Frame 0
+                    [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]],
+                    # Frame 1
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 2
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 3
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 4
+                    [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]],
+                ]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    # Frame 0
+                    [
+                        [0.086801, 0.036670, 0.035971, 0.035304, 0.088456],
+                        [0.036639, 0.035652, 0.035009, 0.034394, 0.033803],
+                        [0.035899, 0.034897, 0.034136, 0.033566, 0.033129],
+                        [0.035180, 0.034238, 0.033413, 0.032811, 0.032577],
+                        [0.088290, 0.033597, 0.032821, 0.032134, 0.088786],
+                    ],
+                    # Frame 1
+                    [
+                        [0.036286, 0.035269, 0.034632, 0.034021, 0.033435],
+                        [0.035398, 0.034485, 0.033922, 0.033381, 0.033177],
+                        [0.034688, 0.033822, 0.033169, 0.032664, 0.032780],
+                        [0.034024, 0.033234, 0.032533, 0.032005, 0.032388],
+                        [0.033564, 0.032797, 0.032118, 0.031525, 0.032105],
+                    ],
+                    # Frame 2
+                    [
+                        [0.035225, 0.034169, 0.033404, 0.032843, 0.032766],
+                        [0.034383, 0.033487, 0.032908, 0.032415, 0.032650],
+                        [0.033691, 0.032921, 0.032353, 0.031900, 0.032384],
+                        [0.033080, 0.032390, 0.031786, 0.031432, 0.032008],
+                        [0.033099, 0.032373, 0.031737, 0.031479, 0.032054],
+                    ],
+                    # Frame 3
+                    [
+                        [0.034216, 0.033231, 0.032337, 0.031758, 0.032101],
+                        [0.033456, 0.032669, 0.031913, 0.031455, 0.032034],
+                        [0.032788, 0.032140, 0.031618, 0.031413, 0.031977],
+                        [0.032221, 0.031650, 0.031145, 0.031130, 0.031652],
+                        [0.032642, 0.031968, 0.031378, 0.031433, 0.032003],
+                    ],
+                    # Frame 4
+                    [
+                        [0.086207, 0.032335, 0.031499, 0.030832, 0.087498],
+                        [0.032570, 0.031884, 0.031155, 0.030858, 0.031401],
+                        [0.031967, 0.031417, 0.030876, 0.030881, 0.031388],
+                        [0.031602, 0.031103, 0.030696, 0.030960, 0.031455],
+                        [0.090599, 0.031546, 0.031127, 0.031386, 0.083483],
+                    ],
+                ]
+            ]
+        ],
+    ],
+]
+
+
+@skip_if_no_cpp_extention
+class BilateralFilterTestCaseCpuApprox(unittest.TestCase):
+    @parameterized.expand(TEST_CASES)
+    def test_cpu_approx(self, test_case_description, sigmas, input, expected):
+
+        # Params to determine the implementation to test
+        device = torch.device("cpu")
+        fast_approx = True
+
+        # Create input tensor and apply filter
+        input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device)
+        output = BilateralFilter.apply(input_tensor, *sigmas, fast_approx).cpu().numpy()
+
+        # Ensure result are as expected
+        np.testing.assert_allclose(output, expected, atol=1e-5)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/tests/test_bilateral_approx_cuda.py b/tests/test_bilateral_approx_cuda.py
new file mode 100644
--- /dev/null
+++ b/tests/test_bilateral_approx_cuda.py
@@ -0,0 +1,386 @@
+# Copyright 2020 MONAI Consortium
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#     http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+import numpy as np
+import torch
+from parameterized import parameterized
+
+from monai.networks.layers.filtering import BilateralFilter
+from tests.utils import skip_if_no_cpp_extention, skip_if_no_cuda
+
+TEST_CASES = [
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, low spatial sigma, low color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.2),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1.000000, 0.000000, 0.000000, 0.000000, 1.000000]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.000000, 0.000000, 1.000000, 0.000000, 0.000000]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, low spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.880626, 0.306148, 0.158734, 0.164534, 0.754386]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.019010, 0.104507, 0.605634, 0.183721, 0.045619]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, high spatial sigma, low color sigma",
+        # Spatial and Color Sigmas
+        (4, 0.2),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1.000000, 0.000000, 0.000000, 0.000000, 1.000000]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.000000, 0.000000, 1.000000, 0.000000, 0.000000]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.497667, 0.268683, 0.265026, 0.261467, 0.495981]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.149889, 0.148226, 0.367978, 0.144023, 0.141317]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 4 channel, low spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 0],
+                # Channel 1
+                [1, 0, 1, 0, 0],
+                # Channel 2
+                [0, 0, 1, 0, 1],
+                # Channel 3
+                [0, 0, 0, 0, 1],
+            ]
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.988107, 0.061340, 0.001565, 0.000011, 0.000000],
+                # Channel 1
+                [0.988107, 0.061340, 0.998000, 0.000016, 0.000123],
+                # Channel 2
+                [0.000000, 0.000000, 0.996435, 0.000006, 0.999236],
+                # Channel 3
+                [0.000000, 0.000000, 0.000000, 0.000000, 0.999113],
+            ]
+        ],
+    ],
+    [
+        # Case Descirption
+        "2 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    [0.211469, 0.094356, 0.092973, 0.091650, 0.211894],
+                    [0.093755, 0.091753, 0.090524, 0.089343, 0.088384],
+                    [0.091803, 0.089783, 0.088409, 0.087346, 0.086927],
+                    [0.089938, 0.088126, 0.086613, 0.085601, 0.085535],
+                    [0.208359, 0.086535, 0.085179, 0.084210, 0.205858],
+                ]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [
+                    [0.032760, 0.030146, 0.027442, 0.024643, 0.021744],
+                    [0.030955, 0.029416, 0.026574, 0.023629, 0.020841],
+                    [0.028915, 0.027834, 0.115442, 0.022515, 0.020442],
+                    [0.026589, 0.025447, 0.024319, 0.021286, 0.019964],
+                    [0.023913, 0.022704, 0.021510, 0.020388, 0.019379],
+                ]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "2 dimension, 4 channel, high spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 1]],
+                # Channel 1
+                [[1, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 1]],
+                # Channel 2
+                [[0, 0, 1, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 1, 0, 0]],
+                # Channel 3
+                [[0, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 0]],
+            ]
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    [0.557349, 0.011031, 0.001800, 0.011265, 0.000631],
+                    [0.009824, 0.010361, 0.010429, 0.010506, 0.010595],
+                    [0.008709, 0.009252, 0.009688, 0.009714, 0.009744],
+                    [0.007589, 0.008042, 0.008576, 0.008887, 0.008852],
+                    [0.000420, 0.006827, 0.001048, 0.007763, 0.190722],
+                ],
+                # Channel 1
+                [
+                    [0.614072, 0.011045, 0.925766, 0.011287, 0.007548],
+                    [0.009838, 0.010382, 0.010454, 0.010536, 0.010630],
+                    [0.008727, 0.009277, 0.009720, 0.009751, 0.009787],
+                    [0.007611, 0.008071, 0.008613, 0.008932, 0.008904],
+                    [0.027088, 0.006859, 0.950749, 0.007815, 0.230270],
+                ],
+                # Channel 2
+                [
+                    [0.056723, 0.000150, 0.973790, 0.000233, 0.990814],
+                    [0.000151, 0.000214, 0.000257, 0.000307, 0.000364],
+                    [0.000186, 0.000257, 0.000328, 0.000384, 0.000449],
+                    [0.000221, 0.000295, 0.000382, 0.000465, 0.000538],
+                    [0.993884, 0.000333, 0.984743, 0.000532, 0.039548],
+                ],
+                # Channel 3
+                [
+                    [0.000000, 0.000136, 0.049824, 0.000210, 0.983897],
+                    [0.000136, 0.000193, 0.000232, 0.000277, 0.000329],
+                    [0.000168, 0.000232, 0.000297, 0.000347, 0.000405],
+                    [0.000200, 0.000266, 0.000345, 0.000420, 0.000485],
+                    [0.967217, 0.000301, 0.035041, 0.000481, 0.000000],
+                ],
+            ]
+        ],
+    ],
+    [
+        # Case Descirption
+        "3 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    # Frame 0
+                    [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]],
+                    # Frame 1
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 2
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 3
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 4
+                    [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]],
+                ]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    # Frame 0
+                    [
+                        [0.085451, 0.037820, 0.036880, 0.035978, 0.084296],
+                        [0.037939, 0.036953, 0.036155, 0.035385, 0.034640],
+                        [0.037167, 0.036302, 0.035603, 0.034931, 0.034465],
+                        [0.036469, 0.035724, 0.035137, 0.034572, 0.034480],
+                        [0.088942, 0.035193, 0.034682, 0.034266, 0.090568],
+                    ],
+                    # Frame 1
+                    [
+                        [0.037125, 0.035944, 0.035103, 0.033429, 0.033498],
+                        [0.033380, 0.032653, 0.033748, 0.033073, 0.032549],
+                        [0.034834, 0.034001, 0.033500, 0.032902, 0.032560],
+                        [0.033972, 0.033554, 0.033220, 0.032765, 0.032570],
+                        [0.033590, 0.033222, 0.032927, 0.032689, 0.032629],
+                    ],
+                    # Frame 2
+                    [
+                        [0.035635, 0.034468, 0.033551, 0.032818, 0.032302],
+                        [0.034523, 0.032830, 0.032146, 0.031536, 0.031149],
+                        [0.033612, 0.032011, 0.031664, 0.031128, 0.030839],
+                        [0.032801, 0.031668, 0.031529, 0.031198, 0.030978],
+                        [0.032337, 0.031550, 0.031419, 0.031383, 0.031211],
+                    ],
+                    # Frame 3
+                    [
+                        [0.034300, 0.033236, 0.032239, 0.031517, 0.031133],
+                        [0.033357, 0.031842, 0.031035, 0.030471, 0.030126],
+                        [0.032563, 0.031094, 0.030156, 0.029703, 0.029324],
+                        [0.031850, 0.030505, 0.030027, 0.029802, 0.029461],
+                        [0.031555, 0.030121, 0.029943, 0.030000, 0.029700],
+                    ],
+                    # Frame 4
+                    [
+                        [0.083156, 0.032122, 0.031204, 0.030380, 0.080582],
+                        [0.032296, 0.030936, 0.030170, 0.029557, 0.029124],
+                        [0.031617, 0.030293, 0.029377, 0.028886, 0.028431],
+                        [0.031084, 0.029859, 0.028839, 0.028439, 0.027973],
+                        [0.164616, 0.029457, 0.028484, 0.028532, 0.211082],
+                    ],
+                ]
+            ]
+        ],
+    ],
+]
+
+
+@skip_if_no_cuda
+@skip_if_no_cpp_extention
+class BilateralFilterTestCaseCudaApprox(unittest.TestCase):
+    @parameterized.expand(TEST_CASES)
+    def test_cuda_approx(self, test_case_description, sigmas, input, expected):
+
+        # Skip this test
+        if not torch.cuda.is_available():
+            return
+
+        # Params to determine the implementation to test
+        device = torch.device("cuda")
+        fast_approx = True
+
+        # Create input tensor and apply filter
+        input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device)
+        output = BilateralFilter.apply(input_tensor, *sigmas, fast_approx).cpu().numpy()
+
+        # Ensure result are as expected
+        np.testing.assert_allclose(output, expected, atol=1e-2)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/tests/test_bilateral_precise.py b/tests/test_bilateral_precise.py
new file mode 100644
--- /dev/null
+++ b/tests/test_bilateral_precise.py
@@ -0,0 +1,403 @@
+# Copyright 2020 MONAI Consortium
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#     http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+import numpy as np
+import torch
+from parameterized import parameterized
+
+from monai.networks.layers.filtering import BilateralFilter
+from tests.utils import skip_if_no_cpp_extention, skip_if_no_cuda
+
+TEST_CASES = [
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, low spatial sigma, low color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.2),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.999998, 0.000002, 0.000000, 0.000002, 0.999998]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.000000, 0.000001, 0.999995, 0.000001, 0.000000]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, low spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.813183, 0.186817, 0.061890, 0.186817, 0.813183]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.030148, 0.148418, 0.555452, 0.148418, 0.030148]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, high spatial sigma, low color sigma",
+        # Spatial and Color Sigmas
+        (4, 0.2),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.999999, 0.000009, 0.000009, 0.000009, 0.999999]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.000000, 0.000000, 0.999967, 0.000000, 0.000000]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 1]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0, 0, 1, 0, 0]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.839145, 0.572834, 0.562460, 0.572834, 0.839145]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [0.049925, 0.055062, 0.171732, 0.055062, 0.049925]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "1 dimension, 4 channel, low spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (1, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [1, 0, 0, 0, 0],
+                # Channel 1
+                [1, 0, 1, 0, 0],
+                # Channel 2
+                [0, 0, 1, 0, 1],
+                # Channel 3
+                [0, 0, 0, 0, 1],
+            ]
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [0.889742, 0.141296, 0.027504, 0.000000, 0.000000],
+                # Channel 1
+                [0.909856, 0.256817, 0.725970, 0.115520, 0.020114],
+                # Channel 2
+                [0.020114, 0.115520, 0.725970, 0.256817, 0.909856],
+                # Channel 3
+                [0.000000, 0.000000, 0.027504, 0.141296, 0.889742],
+            ]
+        ],
+    ],
+    [
+        # Case Descirption
+        "2 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    [0.688943, 0.374599, 0.368574, 0.374599, 0.688943],
+                    [0.374599, 0.358248, 0.352546, 0.358248, 0.374599],
+                    [0.368574, 0.352546, 0.346955, 0.352546, 0.368574],
+                    [0.374599, 0.358248, 0.352546, 0.358248, 0.374599],
+                    [0.688943, 0.374599, 0.368574, 0.374599, 0.688943],
+                ]
+            ],
+            # Batch 1
+            [
+                # Channel 0
+                [
+                    [0.004266, 0.004687, 0.004836, 0.004687, 0.004266],
+                    [0.004687, 0.005150, 0.005314, 0.005150, 0.004687],
+                    [0.004836, 0.005314, 0.018598, 0.005314, 0.004836],
+                    [0.004687, 0.005150, 0.005314, 0.005150, 0.004687],
+                    [0.004266, 0.004687, 0.004836, 0.004687, 0.004266],
+                ]
+            ],
+        ],
+    ],
+    [
+        # Case Descirption
+        "2 dimension, 4 channel, high spatial sigma, high color sigma",
+        # Spatial and Color Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 1]],
+                # Channel 1
+                [[1, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 1, 0, 1]],
+                # Channel 2
+                [[0, 0, 1, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 1, 0, 0]],
+                # Channel 3
+                [[0, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 0]],
+            ]
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    [0.692549, 0.149979, 0.220063, 0.115840, 0.035799],
+                    [0.148403, 0.133935, 0.123253, 0.116828, 0.114623],
+                    [0.128773, 0.122804, 0.120731, 0.122804, 0.128773],
+                    [0.114623, 0.116828, 0.123253, 0.133935, 0.148403],
+                    [0.035799, 0.115840, 0.220063, 0.149979, 0.692549],
+                ],
+                # Channel 1
+                [
+                    [0.731597, 0.186319, 0.436069, 0.152181, 0.074847],
+                    [0.180049, 0.168217, 0.158453, 0.151110, 0.146269],
+                    [0.159760, 0.156381, 0.155211, 0.156381, 0.159760],
+                    [0.146269, 0.151110, 0.158453, 0.168217, 0.180049],
+                    [0.074847, 0.152181, 0.436068, 0.186319, 0.731597],
+                ],
+                # Channel 2
+                [
+                    [0.074847, 0.152181, 0.436068, 0.186319, 0.731597],
+                    [0.146269, 0.151110, 0.158453, 0.168217, 0.180049],
+                    [0.159760, 0.156381, 0.155211, 0.156381, 0.159760],
+                    [0.180049, 0.168217, 0.158453, 0.151110, 0.146269],
+                    [0.731597, 0.186319, 0.436069, 0.152181, 0.074847],
+                ],
+                # Channel 3
+                [
+                    [0.035799, 0.115840, 0.220063, 0.149979, 0.692549],
+                    [0.114623, 0.116828, 0.123253, 0.133935, 0.148403],
+                    [0.128773, 0.122804, 0.120731, 0.122804, 0.128773],
+                    [0.148403, 0.133935, 0.123253, 0.116828, 0.114623],
+                    [0.692549, 0.149979, 0.220063, 0.115840, 0.035799],
+                ],
+            ]
+        ],
+    ],
+    [
+        # Case Descirption
+        "3 dimension, 1 channel, high spatial sigma, high color sigma",
+        # Sigmas
+        (4, 0.9),
+        # Input
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    # Frame 0
+                    [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]],
+                    # Frame 1
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 2
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 3
+                    [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]],
+                    # Frame 4
+                    [[1, 0, 0, 0, 1], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1, 0, 0, 0, 1]],
+                ]
+            ],
+        ],
+        # Expected
+        [
+            # Batch 0
+            [
+                # Channel 0
+                [
+                    # Frame 0
+                    [
+                        [0.554430, 0.254995, 0.251207, 0.254996, 0.554430],
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                        [0.251207, 0.241082, 0.237534, 0.241082, 0.251207],
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                        [0.554430, 0.254995, 0.251207, 0.254996, 0.554430],
+                    ],
+                    # Frame 1
+                    [
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                        [0.244692, 0.234873, 0.231432, 0.234873, 0.244692],
+                        [0.241082, 0.231431, 0.228049, 0.231432, 0.241082],
+                        [0.244692, 0.234873, 0.231432, 0.234873, 0.244692],
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                    ],
+                    # Frame 2
+                    [
+                        [0.251207, 0.241081, 0.237534, 0.241082, 0.251207],
+                        [0.241082, 0.231431, 0.228049, 0.231432, 0.241082],
+                        [0.237534, 0.228048, 0.224724, 0.228049, 0.237534],
+                        [0.241082, 0.231431, 0.228049, 0.231432, 0.241082],
+                        [0.251207, 0.241081, 0.237534, 0.241082, 0.251207],
+                    ],
+                    # Frame 3
+                    [
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                        [0.244692, 0.234873, 0.231432, 0.234873, 0.244692],
+                        [0.241082, 0.231431, 0.228049, 0.231432, 0.241082],
+                        [0.244692, 0.234873, 0.231432, 0.234873, 0.244692],
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                    ],
+                    # Frame 4
+                    [
+                        [0.554430, 0.254995, 0.251207, 0.254996, 0.554430],
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                        [0.251207, 0.241082, 0.237534, 0.241082, 0.251207],
+                        [0.254996, 0.244691, 0.241082, 0.244692, 0.254996],
+                        [0.554430, 0.254995, 0.251207, 0.254996, 0.554430],
+                    ],
+                ]
+            ]
+        ],
+    ],
+]
+
+
+@skip_if_no_cpp_extention
+class BilateralFilterTestCaseCpuPrecised(unittest.TestCase):
+    @parameterized.expand(TEST_CASES)
+    def test_cpu_precised(self, test_case_description, sigmas, input, expected):
+
+        # Params to determine the implementation to test
+        device = torch.device("cpu")
+        fast_approx = False
+
+        # Create input tensor and apply filter
+        input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device)
+        output = BilateralFilter.apply(input_tensor, *sigmas, fast_approx).cpu().numpy()
+
+        # Ensure result are as expected
+        np.testing.assert_allclose(output, expected, atol=1e-5)
+
+
+@skip_if_no_cuda
+@skip_if_no_cpp_extention
+class BilateralFilterTestCaseCudaPrecised(unittest.TestCase):
+    @parameterized.expand(TEST_CASES)
+    def test_cuda_precised(self, test_case_description, sigmas, input, expected):
+
+        # Skip this test
+        if not torch.cuda.is_available():
+            return
+
+        # Params to determine the implementation to test
+        device = torch.device("cuda")
+        fast_approx = False
+
+        # Create input tensor and apply filter
+        input_tensor = torch.from_numpy(np.array(input)).to(dtype=torch.float, device=device)
+        output = BilateralFilter.apply(input_tensor, *sigmas, fast_approx).cpu().numpy()
+
+        # Ensure result are as expected
+        np.testing.assert_allclose(output, expected, atol=1e-5)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/tests/utils.py b/tests/utils.py
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -28,6 +28,7 @@
 import torch
 import torch.distributed as dist
 
+from monai.config.deviceconfig import USE_COMPILED
 from monai.data import create_test_image_2d, create_test_image_3d
 from monai.utils import ensure_tuple, optional_import, set_determinism
 from monai.utils.module import get_torch_version_tuple
@@ -80,6 +81,13 @@ def __call__(self, obj):
         return unittest.skipIf(self.module_avail, f"Skipping because optional module present: {self.module_name}")(obj)
 
 
+def skip_if_no_cpp_extention(obj):
+    """
+    Skip the unit tests if the cpp extention isnt available
+    """
+    return unittest.skipIf(not USE_COMPILED, "Skipping cpp extention tests")(obj)
+
+
 def skip_if_no_cuda(obj):
     """
     Skip the unit tests if torch.cuda.is_available is False