线性模糊图像
Linear-Blurring an Image
我试图通过将每个像素映射到它右侧(在同一行中)的 N 个像素的平均值来模糊图像。我的迭代解决方案产生了良好的输出,但我的线性代数解决方案产生了糟糕的输出。
通过测试,我相信我的内核矩阵是正确的;而且,我知道最后 N 行不会变得模糊,但现在没问题。我将不胜感激任何提示或解决方案。
迭代求解输出(好),线性代数输出(差)
原图;这是失败的线性代数代码:
def blur(orig_img):
# turn image-mat into a vector
flattened_img = orig_img.flatten()
L = flattened_img.shape[0]
N = 3
# kernel
kernel = np.zeros((L, L))
for r, row in enumerate(kernel[0:-N]):
row[r:r+N] = [round(1/N, 3)]*N
print(kernel)
# blurr the img
print('starting blurring')
blurred_img = np.matmul(kernel, flattened_img)
blurred_img = blurred_img.reshape(orig_img.shape)
return blurred_img
我建模的方程是这样的:
一种选择可能是只使用内核和卷积?
例如,如果我们像这样加载灰度图像:
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
from scipy import ndimage
# load a hackinsh grayscale image
image = np.asarray(Image.open('cup.jpg')).mean(axis=2)
plt.imshow(image)
plt.title('Gray scale image')
plt.show()
现在可以使用内核和卷积了。例如,要创建一个仅过滤一行的过滤器,并将中心像素的值计算为左右像素之间的差异,可以执行以下操作:
# Create a kernel that takes the difference between neighbors horizontal pixes
k = np.array([[-1,0,1]])
plt.subplot(121)
plt.title('Kernel')
plt.imshow(k)
plt.subplot(122)
plt.title('Output')
plt.imshow(ndimage.convolve(image, k, mode='constant', cval=0.0))
plt.show()
因此,可以通过创建适当的内核将每个像素映射到其右侧 N 个像素的平均值来模糊图像。
# Create a kernel that takes the average of N pixels to the right
n=10
k = np.zeros(n*2);k[n:]=1/n
k = k[np.newaxis,...]
plt.subplot(121)
plt.title('Kernel')
plt.imshow(k)
plt.subplot(122)
plt.title('Output')
plt.imshow(ndimage.convolve(image, k, mode='constant', cval=0.0))
plt.show()
问题是在显示输出图像时 cv2.imshow()
的使用不正确。它期望浮点像素值在 [0, 1] 中;这是在下面的代码中完成的(靠近底部):
def blur(orig_img):
flattened_img = orig_img.flatten()
L = flattened_img.shape[0]
N = int(round(0.1 * orig_img.shape[0], 0))
# mask (A)
mask = np.zeros((L, L))
for r, row in enumerate(mask[0:-N]):
row[r:r+N] = [round(1/N, 2)]*N
# blurred img = A * flattened_img
print('starting blurring')
blurred_img = np.matmul(mask, flattened_img)
blurred_img = blurred_img.reshape(orig_img.shape)
cv2.imwrite('blurred_img.png', blurred_img)
# normalize img to [0,1]
blurred_img = (
blurred_img - blurred_img.min()) / (blurred_img.max()-blurred_img.min())
return blurred_img
修改后的输出
感谢@CrisLuengo 找出问题。
我试图通过将每个像素映射到它右侧(在同一行中)的 N 个像素的平均值来模糊图像。我的迭代解决方案产生了良好的输出,但我的线性代数解决方案产生了糟糕的输出。
通过测试,我相信我的内核矩阵是正确的;而且,我知道最后 N 行不会变得模糊,但现在没问题。我将不胜感激任何提示或解决方案。
迭代求解输出(好),线性代数输出(差)
原图;这是失败的线性代数代码:
def blur(orig_img):
# turn image-mat into a vector
flattened_img = orig_img.flatten()
L = flattened_img.shape[0]
N = 3
# kernel
kernel = np.zeros((L, L))
for r, row in enumerate(kernel[0:-N]):
row[r:r+N] = [round(1/N, 3)]*N
print(kernel)
# blurr the img
print('starting blurring')
blurred_img = np.matmul(kernel, flattened_img)
blurred_img = blurred_img.reshape(orig_img.shape)
return blurred_img
我建模的方程是这样的:
一种选择可能是只使用内核和卷积?
例如,如果我们像这样加载灰度图像:
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
from scipy import ndimage
# load a hackinsh grayscale image
image = np.asarray(Image.open('cup.jpg')).mean(axis=2)
plt.imshow(image)
plt.title('Gray scale image')
plt.show()
现在可以使用内核和卷积了。例如,要创建一个仅过滤一行的过滤器,并将中心像素的值计算为左右像素之间的差异,可以执行以下操作:
# Create a kernel that takes the difference between neighbors horizontal pixes
k = np.array([[-1,0,1]])
plt.subplot(121)
plt.title('Kernel')
plt.imshow(k)
plt.subplot(122)
plt.title('Output')
plt.imshow(ndimage.convolve(image, k, mode='constant', cval=0.0))
plt.show()
因此,可以通过创建适当的内核将每个像素映射到其右侧 N 个像素的平均值来模糊图像。
# Create a kernel that takes the average of N pixels to the right
n=10
k = np.zeros(n*2);k[n:]=1/n
k = k[np.newaxis,...]
plt.subplot(121)
plt.title('Kernel')
plt.imshow(k)
plt.subplot(122)
plt.title('Output')
plt.imshow(ndimage.convolve(image, k, mode='constant', cval=0.0))
plt.show()
问题是在显示输出图像时 cv2.imshow()
的使用不正确。它期望浮点像素值在 [0, 1] 中;这是在下面的代码中完成的(靠近底部):
def blur(orig_img):
flattened_img = orig_img.flatten()
L = flattened_img.shape[0]
N = int(round(0.1 * orig_img.shape[0], 0))
# mask (A)
mask = np.zeros((L, L))
for r, row in enumerate(mask[0:-N]):
row[r:r+N] = [round(1/N, 2)]*N
# blurred img = A * flattened_img
print('starting blurring')
blurred_img = np.matmul(mask, flattened_img)
blurred_img = blurred_img.reshape(orig_img.shape)
cv2.imwrite('blurred_img.png', blurred_img)
# normalize img to [0,1]
blurred_img = (
blurred_img - blurred_img.min()) / (blurred_img.max()-blurred_img.min())
return blurred_img
修改后的输出
感谢@CrisLuengo 找出问题。