英文:
Why is my Speckle (Lee Filter) adding noise instead of reducing noise?
问题
I researched the lee filter according to this: https://pro.arcgis.com/en/pro-app/3.0/help/analysis/raster-functions/speckle-function.htm.
I want it to reduce noise, but it is adding instead.
I have this python function to apply the lee filter to an image:
from scipy.ndimage.filters import uniform_filter
from scipy.ndimage.measurements import variance
def leeFilter(img, size):
img_mean = uniform_filter(img, (size, size))
img_sqr_mean = uniform_filter(img**2, (size, size))
img_variance = img_sqr_mean - img_mean**2
overall_variance = np.var(img)
img_weights = img_variance / (img_variance + overall_variance)
img_output = img_mean + img_weights * (img - img_mean)
return img_output
Then, I'm applying it to my image as such:
currImg = cv2.imread(os.path.join(currPath,f'{i}.png'))
# Get red, green and blue channels
red = currImg[:,:,0]
green = currImg[:,:,1]
blue = currImg[:,:,2]
# Apply the filter
red = lee_filter(red,15)
green = lee_filter(green,15)
blue = lee_filter(blue,15)
# merge channels
currImg[:,:,0] = red
currImg[:,:,1] = green
currImg[:,:,2] = blue
cv2.imwrite(os.path.join(newPath,f'{i}.png'),currImg)
The problem is that using a window size of 15, it looks like it is adding and not lowering the noise of the images. Below is a comparison with the before and after images.
英文:
I researched the lee filter according to this:
https://pro.arcgis.com/en/pro-app/3.0/help/analysis/raster-functions/speckle-function.htm.
I want it to reduce noise, but it is adding instead.
I have this python function to apply the lee filter to an image:
from scipy.ndimage.filters import uniform_filter
from scipy.ndimage.measurements import variance
def leeFilter(img, size):
img_mean = uniform_filter(img, (size, size))
img_sqr_mean = uniform_filter(img**2, (size, size))
img_variance = img_sqr_mean - img_mean**2
overall_variance = np.var(img)
img_weights = img_variance / (img_variance + overall_variance)
img_output = img_mean + img_weights * (img - img_mean)
return img_output
Then, I'm applying it to my image as such:
currImg = cv2.imread(os.path.join(currPath,f'{i}.png'))
# Get red, green and blue channels
red = currImg[:,:,0]
green = currImg[:,:,1]
blue = currImg[:,:,2]
# Apply the filter
red = lee_filter(red,15)
green = lee_filter(green,15)
blue = lee_filter(blue,15)
# merge channels
currImg[:,:,0] = red
currImg[:,:,1] = green
currImg[:,:,2] = blue
cv2.imwrite(os.path.join(newPath,f'{i}.png'),currImg)
The problem is that using a window size of 15, it looks like it is adding and not lowering the noise of the images. Below is a comparison with the before and after images.
答案1
得分: 2
Cris关于估计噪音水平是正确的,但主要问题是算术溢出 - 将计算应用于uint8
元素后的结果。
我们可以在lee_filter
之前将输入转换为float32
,并在lee_filter
之后将输出转换回uint8
。
代码示例:
import cv2
import numpy as np
from scipy.ndimage.filters import uniform_filter
from scipy.ndimage.measurements import variance
def lee_filter(img, size):
img_mean = uniform_filter(img, (size, size))
img_sqr_mean = uniform_filter(img**2, (size, size))
img_variance = img_sqr_mean - img_mean**2
overall_variance = np.var(img)
img_weights = img_variance / (img_variance + overall_variance)
img_output = img_mean + img_weights * (img - img_mean)
return img_output
currImg = cv2.imread('before.png')
# 获取红色、绿色和蓝色通道
red = currImg[:,:,0].astype(np.float32) # 将数据类型从np.uint8转换为np.float32
green = currImg[:,:,1].astype(np.float32)
blue = currImg[:,:,2].astype(np.float32)
# 应用滤波器
red = lee_filter(red, 15)
green = lee_filter(green, 15)
blue = lee_filter(blue, 15)
# 合并通道
currImg[:,:,0] = red
currImg[:,:,1] = green
currImg[:,:,2] = blue
currImg = currImg.round().clip(0, 255).astype(np.uint8) # 将数据从np.float32转换为np.uint8,四舍五入并剪切至0到255
cv2.imwrite('after.png', currImg)
英文:
Cris is right about the estimated noise level, but the main issue is arithmetic overflow - result of applying the computations to uint8
elements.
We may convert the input to float32
before lee_filter
, and convert the output back to uint8
after lee_filter
.
Code sample:
import cv2
import numpy as np
from scipy.ndimage.filters import uniform_filter
from scipy.ndimage.measurements import variance
def lee_filter(img, size):
img_mean = uniform_filter(img, (size, size))
img_sqr_mean = uniform_filter(img**2, (size, size))
img_variance = img_sqr_mean - img_mean**2
overall_variance = np.var(img)
img_weights = img_variance / (img_variance + overall_variance)
img_output = img_mean + img_weights * (img - img_mean)
return img_output
currImg = cv2.imread('before.png')
# Get red, green and blue channels
red = currImg[:,:,0].astype(np.float32) # Convert dtype from np.uint8 to np.float32
green = currImg[:,:,1].astype(np.float32)
blue = currImg[:,:,2].astype(np.float32)
# Apply the filter
red = lee_filter(red, 15)
green = lee_filter(green, 15)
blue = lee_filter(blue, 15)
# merge channels
currImg[:,:,0] = red
currImg[:,:,1] = green
currImg[:,:,2] = blue
currImg = currImg.round().clip(0, 255).astype(np.uint8) # Convert from np.float32 to np.uint8 with rounding and clipping
cv2.imwrite('after.png', currImg)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论