问题描述
将彩色图像转换为NTSC的灰度图像进行高斯滤波,采用σ=1,2,3,5。任
选一种像素填补方案。对于σ=1 下的结果,与直接调用相关函数的结果进行比较(可以简单计算差值图像)。然后,任选两幅图像,比较其他参数条件不变的情况下像素复制和补零下滤波结果在边界上的差别。
代码实现
导库
import numpy as np
import warnings
import cv2
灰度转换函数
def rgb1gray(f, method='NTSC'):
if method == 'average':
g = (f[:,:,0]+f[:,:,1]+f[:,:,2]) / 3
g = g.clip(0, 1)
return g
elif method == 'NTSC':
g = 0.2989*f[:, :, 0] + 0.5870*f[:, :, 1] + 0.1140*f[:, :, 2]
g = g.clip(0, 1)
return g
else:
raise Exception("输入格式有误")
高斯滤波核生成函数
高斯滤波核函数 w = gaussKernel(sig,m),其中 sig 对应于高斯函数定义中的σ,w的大小为 m×m。请注意,这里如果 m 没有提供,需要进行计算确定。如果 m 已提供但过小,应给出警告信息提示。w 要求归一化,即全部元素加起来和为 1。
def gaussKernel(sig=None,m=0):
#抛出异常
if sig==None:
raise Exception("输入格式有误")
else:
if m == 0:
#m未给出,自己计算
m = int(sig * 2 * 3 + 1)
print('计算的m',m)
elif m< sig*1*3+1:
#警告提示
warnings.warn('m太小')
w = np.zeros((m, m), dtype=np.float)
middle_m = m//2
#生成高斯核
for x in range(-middle_m, - middle_m + m):
for y in range(-middle_m, - middle_m + m):
w[y + middle_m, x + middle_m] = np.exp(-(x ** 2 + y ** 2) / (2 * (sig ** 2)))
w /= (sig * np.sqrt(2 * np.pi))
#归一化
w /= w.sum()
return w
归一化函数
#归一化
def normalization(data):
_range = np.max(data) - np.min(data)
return (data - np.min(data)) / _range
高斯滤波函数
#滤波
def twodConv(f, w, method='zero'):
x, y = w.shape
fh, fw = f.shape
nh = fh + x - 1
nw = fw + y - 1
add_h = int(x) // 2
add_w = int(y) // 2
n = np.zeros((nh, nw))
g = np.zeros((fh, fw))
n[add_h:nh - add_h, add_w:nw - add_w] = f
if method == 'replicate':
n[0:add_h,add_w:nw-add_w] = f[0,:]
n[nh-add_h:,add_w:nw-add_w] = f[-1,:]
for i in range(add_w):
n[:,i] = n[:,add_w]
n[:,nw-1-i] = n[:,nw-1-add_w]
for i in range(fh):
for j in range(fw):
g[i,j] = np.sum(n[i:i+x,j:j+y] * w)
g = g.clip(0,1)
return g
if method == 'zero':
for i in range(fh):
for j in range(fw):
g[i,j] = np.sum(n[i:i+x,j:j+y] * w)
g = g.clip(0,1)
return g
主函数
if __name__ == '__main__':
sig = [1, 2, 3, 5]
# 图片导入
f1= cv2.imread("cameraman.tif",cv2.IMREAD_GRAYSCALE)
f2 = cv2.imread("einstein.tif",cv2.IMREAD_GRAYSCALE)
f3 = cv2.imread("mandril_color.tif")
f4 = cv2.imread("lena512color.tiff")
#彩色图转灰度图
f3 = rgb1gray.rgb1gray(normalization(f3))
f4 = rgb1gray.rgb1gray(normalization(f4))
for i in sig:
w = gaussKernel.gaussKernel(i)
g1 = twodConv(normalization(f1), w, method='replicate')
g2 = twodConv(normalization(f2), w, method='replicate')
g3 = twodConv(f3, w, method='replicate')
g4 = twodConv(f4, w, method='replicate')
cv2.imshow('sig='+str(i)+',cameraman', g1)
cv2.imshow('sig='+str(i)+',einstein', g2)
cv2.imshow('sig='+str(i)+',mandril_gray', g3)
cv2.imshow('sig='+str(i)+',lena512gray', g4)
#sig==1时,,与直接调用相关函数的结果进行比较
w = gaussKernel.gaussKernel(1)
g11 = twodConv(normalization(f1), w, method='replicate')
g12 = twodConv(normalization(f2), w, method='replicate')
g13 = twodConv(f3, w, method='replicate')
g14 = twodConv(f4, w, method='replicate')
F = [f1,f2,f3,f4]
G = [g11,g12,g13,g14]
OG = []
C = []
#opencv 方法
for i in F:
og = cv2.GaussianBlur(i,(7,7),1,borderType=cv2.BORDER_REPLICATE)
og = normalization(og)
OG.append(og)
OG = np.array(OG)
G = np.array(G)
C = np.abs(OG-G)
for i in range(4):
cv2.imshow(str(i)+',OpenCV', OG[i])
cv2.imshow( str(i) + ',diff', C[i])
#对比像素复制和补零下滤波结果在边界上的差别
for i in sig:
w = gaussKernel.gaussKernel(i)
g1 = twodConv(normalization(f1), w, method='replicate')
g2 = twodConv(normalization(f2), w, method='replicate')
g3 = twodConv(normalization(f1), w)
g4 = twodConv(normalization(f2), w)
# cv2.imshow('sig='+str(i)+',cameraman_r', g1)
# cv2.imshow('sig='+str(i)+',einstein_r', g2)
cv2.imshow('sig='+str(i)+',cameraman_z', g3)
cv2.imshow('sig='+str(i)+',einstein_z', g4)
cv2.imshow('sig=' + str(i) + ',cameraman_diff', np.abs(g3-g1))
cv2.imshow('sig=' + str(i) + ',einstein_diff', np.abs(g4-g2))
cv2.waitKey(0)
cv2.destroyAllWindows()
结果展示