Python中的图像平滑

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14765891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:22:03  来源:igfitidea点击:

Image smoothing in Python

pythonnumpyimage-processingsmoothing

提问by Nick

I wanted to try to write a simple function to smooth an inputted image. I was trying to do this using the Image and numpy libraries. I was thinking that using a convolution mask would be an approach to this problem and I know numpy has a convolve function build in.

我想尝试编写一个简单的函数来平滑输入的图像。我试图使用 Image 和 numpy 库来做到这一点。我在想使用卷积掩码是解决这个问题的一种方法,我知道 numpy 内置了一个卷积函数。

How can I use the numpy.convolveto smooth an image?

如何使用numpy.convolve平滑图像?

采纳答案by wim

Nice question! tcaswellpost here is a great suggestion, but you will not learn much this way because scipy is doing all the work for you! Since your question said you wanted to try and write the function, I will show you a bit more crude and basic kind of way to do it all manually in the hope that you will better understand the maths behind convolution etc, and then you can improve it with your own ideas and efforts!

好问题! tcaswellpost here 是一个很好的建议,但您不会以这种方式学到很多东西,因为 scipy 会为您完成所有工作!由于您的问题是说您想尝试编写函数,因此我将向您展示一些更粗略和基本的手动完成所有操作的方法,希望您能更好地理解卷积等背后的数学原理,然后您可以改进用你自己的想法和努力吧!

Note: You will get different results with different shapes/sizes of kernels, a Gaussian is the usual way but you can try out some other ones for fun (cosine, triangle, etc!). I just made up this one on the spot, I think it's a kind of pyramid shaped one.

注意:使用不同形状/大小的内核会得到不同的结果,高斯是常用的方法,但您可以尝试其他一些有趣的方法(余弦、三角形等!)。我只是现场制作了这个,我认为它是一种金字塔形的。

import scipy.signal
import numpy as np
import matplotlib.pyplot as plt

im = plt.imread('example.jpg')
im /= 255.   # normalise to 0-1, it's easier to work in float space

# make some kind of kernel, there are many ways to do this...
t = 1 - np.abs(np.linspace(-1, 1, 21))
kernel = t.reshape(21, 1) * t.reshape(1, 21)
kernel /= kernel.sum()   # kernel should sum to 1!  :) 

# convolve 2d the kernel with each channel
r = scipy.signal.convolve2d(im[:,:,0], kernel, mode='same')
g = scipy.signal.convolve2d(im[:,:,1], kernel, mode='same')
b = scipy.signal.convolve2d(im[:,:,2], kernel, mode='same')

# stack the channels back into a 8-bit colour depth image and plot it
im_out = np.dstack([r, g, b])
im_out = (im_out * 255).astype(np.uint8) 

plt.subplot(2,1,1)
plt.imshow(im)
plt.subplot(2,1,2)
plt.imshow(im_out)
plt.show()

enter image description here

在此处输入图片说明

回答by tacaswell

You want to look at ndimage, which is a module in scipy. It has a number of filters all set up as functions, and nice wrappers for convolving arbitrary kernels.

你要看看ndimage,这是scipy. 它有许多过滤器都设置为函数,以及用于卷积任意内核的漂亮包装器。

For example,

例如,

img_gaus = ndimage.filters.gaussian_filter(img, 2, mode='nearest')

convolves your image with a guassian with sigma of 2.

用 sigma 为 2 的 guassian 卷积您的图像。

If you want to convolve an arbitrary kernel, say a cross

如果要对任意内核进行卷积,请说一个交叉

k = np.array([[0, 1, 0],
              [1, 1, 1],
              [0, 1, 0]])

img2 = ndimage.convolve(img, k, mode='constant')

These functions are also good for higher dimensions, so you could use almost identical code (just scaling up the dimension of your kernel) to smooth data in higher dimensions.

这些函数也适用于更高维度,因此您可以使用几乎相同的代码(只是扩展内核的维度)来平滑更高维度的数据。

The modeand cvalparameters control how the convolutions deals with pixels at the edge of your image (for a pixel on the edge, half of the area that the kernel needs to look at does not exist, so you need to pick something to pad your image out with).

modecval参数控制与像素的回旋交易在图像的边缘(上边缘的像素,面积,内核需要看不存在,所以你需要捡东西垫你的形象出来的一半和)。

回答by tom10

If you don't want to use scipy, you have three options:

如果你不想使用 scipy,你有三个选择:

1) you can use the convolution theorem combined with Fourier transforms since numpy has a 2D FFT.

1)您可以将卷积定理与傅立叶变换结合使用,因为 numpy 具有 2D FFT。

2) you can use a separable kernel and then you can do two 1D convolutions on flattened arrays, one in the x-direction and the other in the y-direction (ravel the transpose), and this will give the same result as the 2D convolution.

2)您可以使用可分离的内核,然后您可以在扁平阵列上进行两个一维卷积,一个在 x 方向上,另一个在 y 方向上(解开转置),这将给出与 2D 相同的结果卷积。

3) if you have a small kernel, say, 3x3, it's easy enough just to write out the convolution as multiplications and sums. This sounds like a hassle but it's not so bad.

3) 如果您有一个小内核,例如 3x3,那么只需将卷积写出乘法和求和就足够容易了。这听起来很麻烦,但还不错。

If you do want to use scipy, you can use ngimage, as tcaswell suggests. scipy also has convolve2d.

如果你确实想使用 scipy,你可以使用 ngimage,正如 tcaswell 所建议的那样。scipy 也有 convolve2d。