我正在使用卷积来计算图像中的梯度。为此,我使用了以Python实现的OpenCV的cv2.filter2D()函数。我还编码了一个(缓慢的)实现,该实现只是对所有像素进行迭代。输入图像img是使用cv2.cvtColor()从RGB转换为YUV并使用OpenCV函数cv2.split()分割的.JPG图像。我的代码摘要(仅针对一个颜色通道进行计算)为:

imgYUV = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
clr1, clr2, cl3 = cv2.split(imgYUV)
(iH,iW) = clr1.shape[:2]
pad=1
paddedImg = cv2.copyMakeBorder(clr1,pad,pad,pad,pad,cv2.BORDER_REPLICATE)
outputMyImplementation = np.zeros((iH,iW), dtype='int32')
kernel = np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
for y in np.arange(pad, iH+pad):
    for x in np.arange(pad, iW+pad):
        roi = paddedImg[y-pad:y+pad+1, x-pad:x+pad+1]
        k = (roi*kernel).sum()
        outputMyImplementation[y-pad,x-pad] = k
outputCV2 = cv2.filter2D(clr1,-1,kernel)
但是,filter2D似乎会修剪输入图像中的负值:
  • 使用filter2D()的最大值:66
  • 使用我的Implementation()的最大值:66
  • 使用filter2D()的最小值:0
  • 使用我的Implementation()的最小值:-146

  • 使用翻转的内核kernel = np.array([[1,2,1],[0,0,0],[-1,-2,-1]]),结果为:
  • 使用filter2D()的最大值:146
  • 使用我的Implementation()的最大值:146
  • 使用filter2D()的最小值:0
  • 使用我的Implementation()的最小值:-66

  • 显然,负值被抑制。 cv2.filter2D()中的所有默认设置都适合我,这就是为什么我使用最少参数的原因。该文档没有提及这种行为,并且多个论坛建议不应压低负值。有人知道为什么会发生这种情况,以及如何解决吗?通过汇总内核及其翻转变量的结果,我有一种解决方法,但是对于一个简单的问题,这似乎是一个不好的解决方案。
    版本信息:
  • openCV版本4.4.0.44
  • numpy版本1.19.2
  • python版本3.8.5
  • 最佳答案

    解决方案在于输出的深度。通过将其设置为-1,输入图像的深度将用于输出。由于输入图像很可能是uchar,因此饱和度为0。可以通过使用以下命令将输出类型设置为cv2.CV_64F来解决饱和度为零的问题。outputCV2 = cv2.filter2D(img, cv2.CV_64F, kernel)为了获得与outputMyImplementation完全相同的答案,必须将内核翻转180度。但是,当查看绝对值时,这不是必需的,并且可以按所示方式使用代码。

    关于python - 解决cv2::filter2D()中负值的抑制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64318479/

    10-12 18:41