高斯滤波后组合各种图像通道产生白色图像
Combining various image channels after gaussian filtering produces white image
我正在尝试为尺寸为 (256, 320, 4) 的图像实现高斯滤波器。
我首先为此生成了一个高斯内核,然后在 4 个通道中的每个通道上分别执行卷积,即在所有 256*320 灰度图像上。执行此操作后,我希望将图像组合成彩色图像。
但是,当我这样做时,它似乎没有按预期工作。期望看到原始图像的模糊版本,其模糊程度取决于 sigma 的值。但是,当我 运行 代码时,我只是得到 一个白色图像 ,没有任何模糊。
from PIL import Image
image = imageio.imread('graf_small.png')
print(image.shape)
def gaussian_filter(image, s):
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
channels = image.shape[2]
final_output = np.ndarray((image.shape[0],image.shape[1], image.shape[2]))
for i in range(4):
channels = image.shape[2]
im = np.ndarray((image.shape[0],image.shape[1]))
print(channels)
im[:,:] = image[:,:,i]
# generate a (2k+1)x(2k+1) gaussian kernel with mean=0 and sigma = s
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
# Cross Correlation
# Gather Shapes of Kernel + Image + Padding
xKernShape = kernel.shape[0]
yKernShape = kernel.shape[1]
xImgShape = im.shape[0]
yImgShape = im.shape[1]
strides= 1
padding= 6
# Shape of Output Convolution
xOutput = int(((xImgShape - xKernShape + 2 * padding) / strides) + 1)
yOutput = int(((yImgShape - yKernShape + 2 * padding) / strides) + 1)
output = np.zeros((xOutput, yOutput))
# Apply Equal Padding to All Sides
if padding != 0:
imagePadded = np.zeros((im.shape[0] + padding*2, im.shape[1] + padding*2))
imagePadded[int(padding):int(-1 * padding), int(padding):int(-1 * padding)] = im
#print(imagePadded)
else:
imagePadded = image
# Iterate through image
for y in range(image.shape[1]):
# Exit Convolution
if y > image.shape[1] - yKernShape:
break
# Only Convolve if y has gone down by the specified Strides
if y % strides == 0:
for x in range(image.shape[0]):
# Go to next row once kernel is out of bounds
if x > image.shape[0] - xKernShape:
break
try:
# Only Convolve if x has moved by the specified Strides
if x % strides == 0:
output[x, y] = (kernel * imagePadded[x: x + xKernShape, y: y + yKernShape]).sum()
except:
break
final_output[:,:,i] = output[:,:]
final_output =np.dstack((final_output[:,:,0],final_output[:,:,1],final_output[:,:,2],final_output[:,:,3]))
#print(merged.shape)
return final_output
为了测试函数,调用了一个辅助函数>
def plot_multiple(images, titles, colormap='gray', max_columns=np.inf, share_axes=True):
"""Plot multiple images as subplots on a grid."""
assert len(images) == len(titles)
n_images = len(images)
n_cols = min(max_columns, n_images)
n_rows = int(np.ceil(n_images / n_cols))
fig, axes = plt.subplots(
n_rows, n_cols, figsize=(n_cols * 4, n_rows * 4),
squeeze=False, sharex=share_axes, sharey=share_axes)
axes = axes.flat
# Hide subplots without content
for ax in axes[n_images:]:
ax.axis('off')
if not isinstance(colormap, (list,tuple)):
colormaps = [colormap]*n_images
else:
colormaps = colormap
for ax, image, title, cmap in zip(axes, images, titles, colormaps):
ax.imshow(image, cmap=cmap)
ax.set_title(title)
fig.tight_layout()
image = imageio.imread('graf_small.png')
sigmas = [2]
blurred_images = [gaussian_filter(image, s) for s in sigmas]
titles = [f'sigma={s}' for s in sigmas]
plot_multiple(blurred_images, titles)
似乎所有问题都是您在 float64
中获取图像,但 matplot
需要 uint8
才能显示它。
imageio
将其作为正确的图像保存在文件中,但带有警告 "Lossy conversion from float64 to uint8"
这两个问题都可以解决转换为 uint8
return final_output.astype(np.uint8)
几乎没有小改动的完整工作代码
- 我删除了 dstack
- 我需要
size = output.shape[:2]
和 final_output[:size[0],:size[1],i] = output[:,:]
import imageio
import numpy as np
import matplotlib.pyplot as plt
def gaussian_filter(image, s):
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
channels = image.shape[2]
print('channels:', channels)
final_output = np.ndarray((image.shape[0],image.shape[1], image.shape[2]))
for i in range(channels):
im = image[:,:,i]
# generate a (2k+1)x(2k+1) gaussian kernel with mean=0 and sigma = s
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
# Cross Correlation
# Gather Shapes of Kernel + Image + Padding
xKernShape = kernel.shape[0]
yKernShape = kernel.shape[1]
xImgShape = im.shape[0]
yImgShape = im.shape[1]
strides= 1
padding= 6
# Shape of Output Convolution
xOutput = int(((xImgShape - xKernShape + 2 * padding) / strides) + 1)
yOutput = int(((yImgShape - yKernShape + 2 * padding) / strides) + 1)
output = np.zeros((xOutput, yOutput))
# Apply Equal Padding to All Sides
if padding != 0:
imagePadded = np.zeros((im.shape[0] + padding*2, im.shape[1] + padding*2))
imagePadded[int(padding):int(-1 * padding), int(padding):int(-1 * padding)] = im
#print(imagePadded)
else:
imagePadded = image
# Iterate through image
for y in range(image.shape[1]):
# Exit Convolution
if y > image.shape[1] - yKernShape:
break
# Only Convolve if y has gone down by the specified Strides
if y % strides == 0:
for x in range(image.shape[0]):
# Go to next row once kernel is out of bounds
if x > image.shape[0] - xKernShape:
break
try:
# Only Convolve if x has moved by the specified Strides
if x % strides == 0:
output[x, y] = (kernel * imagePadded[x: x + xKernShape, y: y + yKernShape]).sum()
except:
break
size = output.shape[:2]
final_output[:size[0],:size[1],i] = output[:,:]
return final_output.astype(np.uint8)
def plot_multiple(images, titles, colormap='gray', max_columns=np.inf, share_axes=True):
"""Plot multiple images as subplots on a grid."""
assert len(images) == len(titles)
n_images = len(images)
n_cols = min(max_columns, n_images)
n_rows = int(np.ceil(n_images / n_cols))
fig, axes = plt.subplots(
n_rows, n_cols, figsize=(n_cols * 4, n_rows * 4),
squeeze=False, sharex=share_axes, sharey=share_axes)
axes = axes.flat
# Hide subplots without content
for ax in axes[n_images:]:
ax.axis('off')
if not isinstance(colormap, (list,tuple)):
colormaps = [colormap]*n_images
else:
colormaps = colormap
for ax, image, title, cmap in zip(axes, images, titles, colormaps):
ax.imshow(image, cmap=cmap)
ax.set_title(title)
fig.tight_layout()
plt.show()
# --- main --
image = imageio.imread('test/lenna.png')
print('shape:', image.shape)
sigmas = [2, 3, 5]
blurred_images = [gaussian_filter(image, s) for s in sigmas]
titles = [f'sigma={s}' for s in sigmas]
plot_multiple(blurred_images, titles)
for number, image in enumerate(blurred_images, 1):
imageio.imsave(f'output-{number}.png', image)
来自维基百科的原始图片Lenna
结果:
我正在尝试为尺寸为 (256, 320, 4) 的图像实现高斯滤波器。
我首先为此生成了一个高斯内核,然后在 4 个通道中的每个通道上分别执行卷积,即在所有 256*320 灰度图像上。执行此操作后,我希望将图像组合成彩色图像。
但是,当我这样做时,它似乎没有按预期工作。期望看到原始图像的模糊版本,其模糊程度取决于 sigma 的值。但是,当我 运行 代码时,我只是得到 一个白色图像 ,没有任何模糊。
from PIL import Image
image = imageio.imread('graf_small.png')
print(image.shape)
def gaussian_filter(image, s):
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
channels = image.shape[2]
final_output = np.ndarray((image.shape[0],image.shape[1], image.shape[2]))
for i in range(4):
channels = image.shape[2]
im = np.ndarray((image.shape[0],image.shape[1]))
print(channels)
im[:,:] = image[:,:,i]
# generate a (2k+1)x(2k+1) gaussian kernel with mean=0 and sigma = s
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
# Cross Correlation
# Gather Shapes of Kernel + Image + Padding
xKernShape = kernel.shape[0]
yKernShape = kernel.shape[1]
xImgShape = im.shape[0]
yImgShape = im.shape[1]
strides= 1
padding= 6
# Shape of Output Convolution
xOutput = int(((xImgShape - xKernShape + 2 * padding) / strides) + 1)
yOutput = int(((yImgShape - yKernShape + 2 * padding) / strides) + 1)
output = np.zeros((xOutput, yOutput))
# Apply Equal Padding to All Sides
if padding != 0:
imagePadded = np.zeros((im.shape[0] + padding*2, im.shape[1] + padding*2))
imagePadded[int(padding):int(-1 * padding), int(padding):int(-1 * padding)] = im
#print(imagePadded)
else:
imagePadded = image
# Iterate through image
for y in range(image.shape[1]):
# Exit Convolution
if y > image.shape[1] - yKernShape:
break
# Only Convolve if y has gone down by the specified Strides
if y % strides == 0:
for x in range(image.shape[0]):
# Go to next row once kernel is out of bounds
if x > image.shape[0] - xKernShape:
break
try:
# Only Convolve if x has moved by the specified Strides
if x % strides == 0:
output[x, y] = (kernel * imagePadded[x: x + xKernShape, y: y + yKernShape]).sum()
except:
break
final_output[:,:,i] = output[:,:]
final_output =np.dstack((final_output[:,:,0],final_output[:,:,1],final_output[:,:,2],final_output[:,:,3]))
#print(merged.shape)
return final_output
为了测试函数,调用了一个辅助函数>
def plot_multiple(images, titles, colormap='gray', max_columns=np.inf, share_axes=True):
"""Plot multiple images as subplots on a grid."""
assert len(images) == len(titles)
n_images = len(images)
n_cols = min(max_columns, n_images)
n_rows = int(np.ceil(n_images / n_cols))
fig, axes = plt.subplots(
n_rows, n_cols, figsize=(n_cols * 4, n_rows * 4),
squeeze=False, sharex=share_axes, sharey=share_axes)
axes = axes.flat
# Hide subplots without content
for ax in axes[n_images:]:
ax.axis('off')
if not isinstance(colormap, (list,tuple)):
colormaps = [colormap]*n_images
else:
colormaps = colormap
for ax, image, title, cmap in zip(axes, images, titles, colormaps):
ax.imshow(image, cmap=cmap)
ax.set_title(title)
fig.tight_layout()
image = imageio.imread('graf_small.png')
sigmas = [2]
blurred_images = [gaussian_filter(image, s) for s in sigmas]
titles = [f'sigma={s}' for s in sigmas]
plot_multiple(blurred_images, titles)
似乎所有问题都是您在 float64
中获取图像,但 matplot
需要 uint8
才能显示它。
imageio
将其作为正确的图像保存在文件中,但带有警告 "Lossy conversion from float64 to uint8"
这两个问题都可以解决转换为 uint8
return final_output.astype(np.uint8)
几乎没有小改动的完整工作代码
- 我删除了 dstack
- 我需要
size = output.shape[:2]
和final_output[:size[0],:size[1],i] = output[:,:]
import imageio
import numpy as np
import matplotlib.pyplot as plt
def gaussian_filter(image, s):
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
channels = image.shape[2]
print('channels:', channels)
final_output = np.ndarray((image.shape[0],image.shape[1], image.shape[2]))
for i in range(channels):
im = image[:,:,i]
# generate a (2k+1)x(2k+1) gaussian kernel with mean=0 and sigma = s
probs = [np.exp(-z*z/(2*s*s))/np.sqrt(2*np.pi*s*s) for z in range(-3*s,3*s+1)]
kernel = np.outer(probs, probs)
# Cross Correlation
# Gather Shapes of Kernel + Image + Padding
xKernShape = kernel.shape[0]
yKernShape = kernel.shape[1]
xImgShape = im.shape[0]
yImgShape = im.shape[1]
strides= 1
padding= 6
# Shape of Output Convolution
xOutput = int(((xImgShape - xKernShape + 2 * padding) / strides) + 1)
yOutput = int(((yImgShape - yKernShape + 2 * padding) / strides) + 1)
output = np.zeros((xOutput, yOutput))
# Apply Equal Padding to All Sides
if padding != 0:
imagePadded = np.zeros((im.shape[0] + padding*2, im.shape[1] + padding*2))
imagePadded[int(padding):int(-1 * padding), int(padding):int(-1 * padding)] = im
#print(imagePadded)
else:
imagePadded = image
# Iterate through image
for y in range(image.shape[1]):
# Exit Convolution
if y > image.shape[1] - yKernShape:
break
# Only Convolve if y has gone down by the specified Strides
if y % strides == 0:
for x in range(image.shape[0]):
# Go to next row once kernel is out of bounds
if x > image.shape[0] - xKernShape:
break
try:
# Only Convolve if x has moved by the specified Strides
if x % strides == 0:
output[x, y] = (kernel * imagePadded[x: x + xKernShape, y: y + yKernShape]).sum()
except:
break
size = output.shape[:2]
final_output[:size[0],:size[1],i] = output[:,:]
return final_output.astype(np.uint8)
def plot_multiple(images, titles, colormap='gray', max_columns=np.inf, share_axes=True):
"""Plot multiple images as subplots on a grid."""
assert len(images) == len(titles)
n_images = len(images)
n_cols = min(max_columns, n_images)
n_rows = int(np.ceil(n_images / n_cols))
fig, axes = plt.subplots(
n_rows, n_cols, figsize=(n_cols * 4, n_rows * 4),
squeeze=False, sharex=share_axes, sharey=share_axes)
axes = axes.flat
# Hide subplots without content
for ax in axes[n_images:]:
ax.axis('off')
if not isinstance(colormap, (list,tuple)):
colormaps = [colormap]*n_images
else:
colormaps = colormap
for ax, image, title, cmap in zip(axes, images, titles, colormaps):
ax.imshow(image, cmap=cmap)
ax.set_title(title)
fig.tight_layout()
plt.show()
# --- main --
image = imageio.imread('test/lenna.png')
print('shape:', image.shape)
sigmas = [2, 3, 5]
blurred_images = [gaussian_filter(image, s) for s in sigmas]
titles = [f'sigma={s}' for s in sigmas]
plot_multiple(blurred_images, titles)
for number, image in enumerate(blurred_images, 1):
imageio.imsave(f'output-{number}.png', image)
来自维基百科的原始图片Lenna
结果: