我正在做一些关于在Python中卷积图像的事情,为了速度,我选择了opencv 2.4.9。
Opencv提供了一种名为 filter2D 的方法来执行此操作,这里是其文档:http://docs.opencv.org/modules/imgproc/doc/filtering.html?highlight=filter2d#filter2d
在文档中,它说:
用内核包含图像。
但我怀疑(由别的东西引起)所以我做了一些实验:
首先,我使用numpy制作一个普通的3x3矩阵 a :
[[ 1., 5., 0.], [ 7., 2., 9.], [ 2., 3., 4.]]
然后,我将2x2矩阵 b 作为内核:
>>> b
[[ 1., 2.], [ 3., 4.]]
最后,为了清楚地看到卷积和关联之间的区别,请将 b 旋转180度并 b 看起来像:
[[ 4., 3.], [ 2., 1.]]
现在,所有的前期工作都已完成。我们可以开始实验了。
步骤1.使用 scipy.ndimage.convolve :ndconv = ndimage.convolve(a, b, mode = 'constant')
和 ndconv :
[[ 35., 33., 18.], [ 41., 45., 44.], [ 17., 24., 16.]]
卷积操作将 b 旋转180度,并使用 b < < / em>的。所以ndconv [0] [0] = 4 * 1 + 3 * 5 + 2 * 7 + 1 * 2 = 35,ndconv [2] [2] = 4 * 4 + 3 * 0 + 2 * 0 + 1 * 0 = 16
此结果正确。
步骤2.使用 scipy.ndimage.correlate :ndcorr = ndimage.correlate(a, b, mode = 'constant')
和 ndcorr :
[[ 4., 23., 15.], [ 30., 40., 47.], [ 22., 29., 45.]]
根据相关性的定义, ndcorr [0] [0] = 1 * 0 + 2 * 0 + 3 * 0 + 4 * 1 = 4因为边界将扩展 0 。
(有人可能会因为扩展与conv和corr之间的差异而感到困惑。 似乎卷入在向右和向下方向展开图片,而关联在方向左上方。)
但这不是重点。
步骤3.使用 cv2.filter2D :cvfilter = cv2.filter2D(a, -1, b)
和 cvfilter :
[[ 35., 34., 35.], [ 41., 40., 47.], [ 33., 29., 45.]]
如果我们忽略边界情况,我们会发现 cv2.filter2D 所做的实际上是一个相关而不是卷积!我该怎么说呢?
因为 cvfilter [1..2] [1..2] == ndcorr [1..2] [1..2] 。
任何人都可以告诉 cv2.filter2D 的真实情况吗?非常感谢。
答案 0 :(得分:7)
如果您在OpenCV documentation:
的说明中进一步了解该函数确实计算了相关性,而不是卷积:
也就是说,内核不会在锚点周围镜像。如果您需要真正的卷积,请使用
flip()
翻转内核并将新锚设置为(kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1)
。
答案 1 :(得分:1)
嗯,我觉得OpenCV也是如此。如果你想根据数字图像处理理论进行真正的卷积,你应该在应用cv2.filter2D
之前手动反转内核。