import numpy as np
import cv2
import time
def my_get_Gaussian2D_mask(msize, sigma=1):
y, x = np.mgrid[-(msize // 2):(msize // 2) + 1,
-(msize // 2):(msize // 2) + 1]
gaus2D = 1 / (2 * np.pi * sigma**2) * \
np.exp(-(( x**2 + y**2 )/(2 * sigma**2)))
gaus2D /= np.sum(gaus2D)
return gaus2D
def my_normalize(src):
dst = src.copy()
dst *= 255
dst = np.clip(dst, 0, 255)
return dst.astype(np.uint8)
def my_padding(src, pad_shape):
(h, w) = src.shape
(p_h, p_w) = pad_shape
pad_img = np.zeros((h+2*p_h, w+2*p_w))
pad_img[p_h:p_h+h, p_w:p_w+w] = src
return pad_img
def my_filtering(src, mask):
(h, w) = src.shape
(m_h, m_w) = mask.shape
pad_img = my_padding(src, (m_h//2, m_w//2))
dst = np.zeros((h, w))
for row in range(h):
for col in range(w):
val = np.sum(pad_img[row:row + m_h, col:col + m_w] * mask)
dst[row, col] = val
return dst
def add_gaus_noise(src, mean=0, sigma=0.1):
#src : 0 ~ 255, dst : 0 ~ 1
dst = src/255
h, w, c = dst.shape
noise = np.random.normal(mean, sigma, size=(h, w, c))
dst += noise
return my_normalize(dst)
def my_bilateral(src, msize, sigma, sigma_r):
(h, w) = src.shape
m_s = msize // 2
img_pad = my_padding(src, pad_shape=(m_s, m_s))
dst = np.zeros((h, w))
y, x = np.mgrid[-m_s:m_s + 1, -m_s:m_s + 1]
for i in range(h):
print('\r%d / %d ...' %(i,h), end="")
for j in range(w):
k = y + i
l = x + j
mask = np.exp( -(((i - k)**2) / (2 * sigma**2)) -(((j-l)**2) / (2 * sigma**2)) ) * np.exp( -(((img_pad[i+m_s, j+m_s] - img_pad[k+m_s, l+m_s])**2)/(2*sigma_r**2)) )
mask = mask/mask.sum()
dst[i, j] = np.sum(img_pad[i:i + msize, j:j + msize] * mask)
return dst
def my_median_filtering(src, msize):
h, w = src.shape
dst = np.zeros((h, w))
for row in range(h):
for col in range(w):
r_start = np.clip(row - msize // 2, 0, h)
r_end = np.clip(row + msize // 2, 0, h)
c_start = np.clip(col - msize // 2, 0, w)
c_end = np.clip(col + msize // 2, 0, w)
mask = src[r_start:r_end, c_start:c_end]
dst[row, col] = np.median(mask)
return dst.astype(np.uint8)
if __name__ == '__main__':
src = cv2.imread('canoe.png')
np.random.seed(seed=100)
noise_image = add_gaus_noise(src, mean=0, sigma=0.1)
src_noise = noise_image.astype(np.float32)
##apple
rgb_bilateral_dst = np.zeros_like(src)
rgb_gaussian_dst = np.zeros_like(src)
rgb_median_dst = np.zeros_like(src)
for i in range(3):
rgb_bilateral_dst[:, :, i] = my_bilateral(src_noise[:, :, i], msize=5, sigma=10, sigma_r=0.1)
rgb_gaussian_dst[:, :, i] = my_filtering(src_noise[:, :, i], my_get_Gaussian2D_mask(5, sigma=1))
rgb_median_dst[:, :, i] = my_median_filtering(src_noise[:, :, i], msize=5)
yuv_img = cv2.cvtColor(src_noise, cv2.COLOR_BGR2YUV)
yuv_bilateral_dst = np.zeros_like(yuv_img)
yuv_gaussian_dst = np.zeros_like(yuv_img)
yuv_median_dst = np.zeros_like(yuv_img)
for i in range(3):
yuv_bilateral_dst[:, :, i] = my_bilateral(yuv_img[:, :, i], msize=5, sigma=10, sigma_r=0.1)
yuv_gaussian_dst[:, :, i] = my_filtering(yuv_img[:, :, i], my_get_Gaussian2D_mask(5, sigma=1))
yuv_median_dst[:, :, i] = my_median_filtering(yuv_img[:, :, i], msize=5)
rgb_bilateral_dst = my_normalize(rgb_bilateral_dst)
rgb_gaussian_dst = my_normalize(rgb_gaussian_dst)
rgb_median_dst = my_normalize(rgb_median_dst)
yuv_bilateral_dst = cv2.cvtColor(my_normalize(yuv_bilateral_dst), cv2.COLOR_YUV2BGR)
yuv_gaussian_dst = cv2.cvtColor(my_normalize(yuv_gaussian_dst), cv2.COLOR_YUV2BGR)
yuv_median_dst = cv2.cvtColor(my_normalize(yuv_median_dst), cv2.COLOR_YUV2BGR)
#banana
cv2.imshow('original.png', src)
cv2.imshow('RGB bilateral', rgb_bilateral_dst)
cv2.imshow('RGB gaussian', rgb_gaussian_dst)
cv2.imshow('RGB median', rgb_median_dst)
cv2.imshow('YUV bilateral', cv2.cvtColor(yuv_bilateral_dst, cv2.COLOR_YUV2BGR))
cv2.imshow('YUV gaussian', cv2.cvtColor(yuv_gaussian_dst, cv2.COLOR_YUV2BGR))
cv2.imshow('YUV median', cv2.cvtColor(yuv_median_dst, cv2.COLOR_YUV2BGR))
cv2.waitKey()
cv2.destroyAllWindows()
正在打印的图像应该不会与原始图像有太大差异,但它出来的时候很奇怪。从评论应用到香蕉,我写了代码。我认为这是错误的,因为输入图像的颜色和输出图像的颜色不匹配。if函数上面的其他函数都是完整的代码,没有任何问题。我很感激你对我写的代码的帮助。
output image
original image
1条答案
按热度按时间f87krz0w1#
颜色变化的主要原因与算术溢出有关。
uint8
dtype的OpenCV有效像素范围为[0,255]。float32
dtype的OpenCV有效像素范围为[0,1]。我们最好在开始时将输入转换为
float32
和范围[0,1],应用过滤器,并在最后转换回范围[0,255]中的uint8
。方法
my_normalize
缩放255并转换为uint8
-我们必须确保my_normalize
的输入图像在范围[0,1]内是float32
(或float64
)。也存在YUV到BGR转换被执行两次的情况。
更新代码:
输出图像(截图):