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

imageJ模糊半径与OpenCV高斯模糊sigma的关系,opencv,imagej,Opencv,Imagej,我正在尝试使用高斯滤波器和imageJ软件模糊图像中的ROI 我在imageJ中获得了所需的模糊半径为9的结果 现在我尝试编写相应的 OpenCV C++应用程序>代码>来执行与 Image J < /C> >相同的操作。< /P> openCV中的Gaussian Blur签名如下: C++:void GaussianBlur(输入阵列src、输出阵列dst、大小ksize、双sigmaX、双sigmaY=0、int borderType=BORDER\u默认值) 与ImageJ模糊半径9相对

我正在尝试使用
高斯滤波器
imageJ
软件模糊图像中的
ROI

我在
imageJ
中获得了所需的
模糊半径为9
的结果

现在我尝试编写相应的<代码> OpenCV C++应用程序>代码>来执行与<代码> Image J < /C> >相同的操作。< /P>

openCV
中的
Gaussian Blur
签名如下:

C++:void GaussianBlur(输入阵列src、输出阵列dst、大小ksize、双sigmaX、双sigmaY=0、int borderType=BORDER\u默认值)

ImageJ模糊半径9
相对应的
sigmaX
sigmaY
是什么

我尝试了许多资源,例如:


但是我在使用OpenCV时没有得到相同的结果。你能详细说明一下结果是如何“不一样”的吗

ImageJ中的模糊半径定义为“‘半径’是指衰减到exp(-0.5)~61%的半径,即高斯的标准偏差σ”(来自ImageJ文档:) 我认为没有理由不在OpenCV中以同样的方式实现它

然而,我也观察到ImageJ和OpenCV高斯模糊之间的这些差异。 虽然目前我还没有办法使它们完全相同,但我设法使它们更接近,并且在实施过程中可以看到一个潜在的差异和一个肯定的差异:

内核大小(电位差): 你知道内核大小和高斯半径是两个不同的东西吗?内核大小是应用于图像的内核大小(3*3、5*5等),但在该内核中,可以存在任意半径的高斯分布。然而,通常选择核大小,使得在核边界上,高斯函数衰减到约为零

也就是说,ImageJ会根据您选择的半径自动为您选择内核,以满足“高斯衰减为零的边界”条件。如果将sigma设置为所需半径,并将ksize设置为零,则OpenCV函数也会执行此操作。问题是“他们用同样的方式做吗?”

ImageJ对此的实现比您想象的要复杂:“在ImageJ中,实际使用的内核大小取决于精度 需要:当sigma=1时,对于16位和浮点图像,内核为9像素 宽(对于2D图像为9x9),但对于8位或RGB图像为 只有7像素宽,因为如果 只有256个不同的值。对于较大的sigma值,情况更为复杂:对于sigma>=8,首先对数据进行缩小,然后应用高斯模糊,然后使用插值对原始数据点数量进行放大。缩小和插值算法专为获得最佳精度而设计。”,etc等(来自“ImageJ论坛”,我不能发布链接,因为我没有足够的声誉,但只要谷歌这句话,如果你想要的来源)

我不知道OpenCV是否进行了这样的操作,或者它是否以不同的方式计算内核大小,从而得出不同的结果。(在谷歌上找不到)

边界(当然不同):您可能知道,高斯滤波器会对图像中的每个像素进行过滤,并根据其相邻像素计算该像素的新值。但是,如果高斯核比它们与图像边界的距离更宽,那么靠近边界的像素呢?算法是如何处理的?通过仔细检查我的图像,我发现OCV实现和IJ实现之间的主要区别在于边界像素

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

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

但是,OpenCV允许您选择其他选项,而OpenCV调用中名为
BORDER\u default
的默认选项是
BORDER\u REFLECT\u 101
()(至少我认为它是,它是使用边框的另一种方法的默认边框,因此我认为它也是高斯函数的默认边框)<代码>边框_反映_101某种“镜像”边框(gfedcb | abcdefgh,请参见链接)

要更接近ImageJ(aaaaaa | abcdefgh),请使用
BORDER\u DEFAULT=BORDER\u REPLICATE
。这样,我可以在两个实现之间获得更接近的结果(虽然不完全相同,但如果我找到更多线索,我将继续调查并编辑我的答案)

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