imageJ模糊半径与OpenCV高斯模糊sigma之间的关系

时间:2016-10-26 04:57:04

标签: opencv imagej

我正在尝试使用ROIGaussian filter软件模糊图像中的imageJ

我在blur radius as 9中获得了imageJ所需的结果。

现在我正在尝试编写相应的OpenCV C++ application来执行与imageJ相同的操作。

Gaussian Blur中的openCV签名如下:

C++: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

sigmaX对应的sigmaYImageJ blur radius of 9是什么?

我尝试了很多资源,例如: Blur Radius

但我与OpenCV没有得到相同的结果。

1 个答案:

答案 0 :(得分:0)

请您详细说明结果如何"不一样" ?

ImageJ中的模糊半径定义为"' Radius'表示衰减半径为exp(-0.5)~61%,即高斯的标准偏差西格玛" (来自ImageJ文档:https://imagej.nih.gov/ij/developer/api/ij/plugin/filter/GaussianBlur.html#GaussianBlur--) 我认为没有理由不在OpenCV中以相同的方式实现它。

然而,我也观察到ImageJ和OpenCV高斯模糊之间的这些差异。 虽然目前我没有解决办法使这些绝对相同,但我设法让它们更接近,并且可以看到一个潜在的差异和一个差异,以确保实施:

内核大小(潜在差异): 你知道内核大小和高斯半径是两个不同的东西吗?内核大小是应用于图像的内核的大小(3 * 3,5 * 5等),但是在这个内核中,任何半径的高斯都可以存在。然而,内核大小经常被选中,使得在内核边界上,高斯函数已经衰减到大约零。

话虽如此,ImageJ会根据您选择的半径自动为您选择内核,以便在边界上实现高斯衰减为零#34;条件。如果您将sigma设置为所需的半径并将ksize设置为零,则OpenCV函数也会执行此操作。问题是"他们都以同样的方式做到了吗?"。

ImageJ的实现比你想象的更棘手:"在ImageJ中,实际使用的内核大小取决于准确性 需要:使用sigma = 1,对于16位和浮点图像,内核为9像素 宽(对于2D图像给出9x9),但对于8位或RGB图像是 只有7像素宽,因为如果不需要非常高的精度 只有256个不同的值。对于较大的sigma值,情况更复杂:对于sigma> = 8,首先缩小数据,然后应用高斯模糊,并使用插值来放大到原始数据点数。降尺度和插值算法是专门为最高精度设计的。"等等(来自" ImageJ论坛",我不能发布链接,因为我没有足够的声誉,但只要谷歌这个引用,如果你想要源)

我不知道OpenCV是否执行此类操作,或者它是否以不同方式计算内核大小,从而产生不同的结果。 (无法通过Google找到它。)

边框(确定不同):您可能知道,高斯滤镜会遍历图像中的每个像素,并根据其邻居计算此像素的新值。但是接近边界的像素呢,高斯核比距离图像边界的距离宽?算法如何处理它?通过更仔细地检查我的图像,我发现OCV实现和IJ之间的主要区别在于边界像素。

事实证明,ImageJ和OpenCV处理这些像素的方式不同:

ImageJ高斯,"与ImageJ中的所有卷积运算一样,它假设图像外像素的值等于最近的边缘像素。" (来自与上面相同的ImageJ文档)。

但是,OpenCV允许您选择其他选项,而OpenCV调用中名为BORDER_DEFAULT的默认选项为BORDER_REFLECT_101http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_core/py_basic_ops/py_basic_ops.html)(至少我认为是,它是使用边框的另一种方法的默认边框,所以我认为它也是高斯的默认边框)。 BORDER_REFLECT_101种"镜像"边界(gfedcb | abcdefgh,见链接)。

要靠近ImageJ(aaaaaaaa | abcdefgh),请使用BORDER_DEFAULT=BORDER_REPLICATE。有了这个,我在两个实现之间得到了更接近的结果(尽管不完全相同,如果我找到更多线索,我将继续调查和编辑我的答案)。

[注意:我使用的是Python2.7(不是C ++)和OpenCV 3,但我认为它不会对这个问题产生影响]