使用filter2D(OpenCV)执行Sobel操作符时,平方引入了大量噪声

使用filter2D(OpenCV)执行Sobel操作符时,平方引入了大量噪声,opencv,computer-vision,sobel,Opencv,Computer Vision,Sobel,我正在尝试手动实现sobel运算符 出于某种原因,操作符的水平和垂直分量似乎有很好的效果,但组合图像有很多噪声 我注意到,当我做(imgv**2)**0.5这样的事情时,也会引入大量的噪声,即使在理想情况下,我应该得到大致相同的图像 有人知道这里发生了什么吗?我应该以不同的方式组合图像吗 以下是我用python编写的代码: import cv2 import numpy as np sobelX = np.array([[1,0,-1],[2,0,-2],[1,0,-1]]) sobelY =

我正在尝试手动实现sobel运算符

出于某种原因,操作符的水平和垂直分量似乎有很好的效果,但组合图像有很多噪声

我注意到,当我做(imgv**2)**0.5这样的事情时,也会引入大量的噪声,即使在理想情况下,我应该得到大致相同的图像

有人知道这里发生了什么吗?我应该以不同的方式组合图像吗

以下是我用python编写的代码:

import cv2
import numpy as np

sobelX = np.array([[1,0,-1],[2,0,-2],[1,0,-1]])
sobelY = sobelX.T

imgoriginal = cv2.imread("building.bmp") 

imgv = cv2.filter2D(imgoriginal, -1, sobelY)
imgh = cv2.filter2D(imgoriginal, -1, sobelX)
imgboth = (imgv**2 + img**2)**0.5
这是输出:


更新:一种更好的方法

#!/usr/bin/python3
# 2017.12.22 21:48:22 CST

import cv2
import numpy as np

## parameters
sobelX = np.array([[1,0,-1],[2,0,-2],[1,0,-1]])
sobelY = sobelX.T
ddepth = cv2.CV_16S

## calc gx and gy
#img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.GaussianBlur(img, (3,3), 0)
gx = cv2.filter2D(img, ddepth, sobelX)
gy = cv2.filter2D(img, ddepth, sobelY)

## calc gridxy 
gxabs = cv2.convertScaleAbs(gx)
gyabs = cv2.convertScaleAbs(gy)
grad = cv2.addWeighted(gxabs, 0.5, gyabs, 0.5, 0)

cv2.imwrite("result.png", grad)


原始答案:

是的,在numpy中对opencv图像进行数学运算时,这让我很困扰。图像数据类型默认为np.uint8。因此,如果您不更改感知,则在执行数学运算时,它可能会溢出/下溢

试试这个:

import cv2
import numpy as np

sobelX = np.array([[1,0,-1],[2,0,-2],[1,0,-1]])
sobelY = sobelX.T

img = cv2.imread("cat.png")

## Change the color space
#img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

imgv = cv2.filter2D(img, -1, sobelY)
imgh = cv2.filter2D(img, -1, sobelX)

## Change the percision first, then do math operation
imghv = (np.float32(imgv)**2 + np.float32(img)**2)**0.5
#imghv = (np.float32(imgv)**2 + np.float32(img)**2)**0.5

## Normalize and change the percision
## Use cv2.convertScaleAbs() to convert value into the right range [0, 255]
imghv = imghv/imghv.max()*255
imghv = cv2.convertScaleAbs(imghv) 

## Display
res = np.hstack((imgh, imgv, imghv))
cv2.imshow("Sobel", res)
cv2.waitKey()
cv2.destroyAllWindows()


更新:一种更好的方法

#!/usr/bin/python3
# 2017.12.22 21:48:22 CST

import cv2
import numpy as np

## parameters
sobelX = np.array([[1,0,-1],[2,0,-2],[1,0,-1]])
sobelY = sobelX.T
ddepth = cv2.CV_16S

## calc gx and gy
#img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.GaussianBlur(img, (3,3), 0)
gx = cv2.filter2D(img, ddepth, sobelX)
gy = cv2.filter2D(img, ddepth, sobelY)

## calc gridxy 
gxabs = cv2.convertScaleAbs(gx)
gyabs = cv2.convertScaleAbs(gy)
grad = cv2.addWeighted(gxabs, 0.5, gyabs, 0.5, 0)

cv2.imwrite("result.png", grad)


原始答案:

是的,在numpy中对opencv图像进行数学运算时,这让我很困扰。图像数据类型默认为np.uint8。因此,如果您不更改感知,则在执行数学运算时,它可能会溢出/下溢

试试这个:

import cv2
import numpy as np

sobelX = np.array([[1,0,-1],[2,0,-2],[1,0,-1]])
sobelY = sobelX.T

img = cv2.imread("cat.png")

## Change the color space
#img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

imgv = cv2.filter2D(img, -1, sobelY)
imgh = cv2.filter2D(img, -1, sobelX)

## Change the percision first, then do math operation
imghv = (np.float32(imgv)**2 + np.float32(img)**2)**0.5
#imghv = (np.float32(imgv)**2 + np.float32(img)**2)**0.5

## Normalize and change the percision
## Use cv2.convertScaleAbs() to convert value into the right range [0, 255]
imghv = imghv/imghv.max()*255
imghv = cv2.convertScaleAbs(imghv) 

## Display
res = np.hstack((imgh, imgv, imghv))
cv2.imshow("Sobel", res)
cv2.waitKey()
cv2.destroyAllWindows()