2013-02-08 15 views
14

入力された画像を滑らかにする簡単な関数を書こうとしたかったのです。私はImageとnumpyのライブラリを使ってこれをしようとしていました。私は畳み込みマスクを使用することがこの問題のアプローチであると考えていました。numpyはコンボルブ関数を組み込んでいます。Pythonの画像スムージング

numpy.convolveを使ってイメージを滑らかにするにはどうすればよいですか?

+2

'scipy.signal.convolve2d' – wim

答えて

16

ニース質問! tcaswell投稿は素晴らしい提案ですが、あなたはscipyがあなたのためにすべての仕事をしているので、このように多くは学ばないでしょう!あなたの質問は、あなたがを試してみたかったので、という関数を試してみました。私はあなたに手作業でやってもらうために少し粗くて基本的な方法を示します。あなた自身のアイデアや努力でそれを改善することができます!

注:カーネルの形状や大きさが異なると異なる結果が得られますが、ガウスは通常の方法ですが、他のものを試してみてください(余弦、三角形など)。私はちょうどその場でこれを作った、それは一種のピラミッド形のものだと思う。あなたは、例えば、2D畳み込みを、おそらく必要があります

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

+0

' scipy.signals.convolve2d'と 'scipy.ndimage.convolve'の間に本当の違いがあるかどうか知っていますか?どちらもわずかに異なる引数で同じことをするようです。 – tacaswell

+0

私は後者が高次元に一般化されていると思います、前者は2次元配列に指定されています。カラーチャンネルをお互いに塗りつぶしたくないので、画像に3Dカーネルを使用するのは奇妙です。 – wim

+0

申し訳ありませんが、愚かな質問私は私の答えに 'convolveは高次元に行く..... .....それは寝る時間だと思うとコメントした後。 – tacaswell

16

scipyのモジュールであるndimageを見たいと思っています。これは、関数として多数のフィルタ がすべて設定されており、任意のカーネルをコンボリューションするための素敵なラッパーです。例えば、

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

は、あなたが任意のカーネルを畳み込むしたい場合は、これらの機能のクロス

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

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

を言う2.

のシグマとガウスであなたのイメージを

を畳み込みますより高い次元でも良いので、ほぼ同じコードを使用して(カーネルの次元を拡大するだけで)、より高い次元のデータを滑らかにすることができます。

modecvalのパラメータは、イメージの端にあるピクセルで畳み込みがどのように処理されるかを制御します(エッジのピクセルの場合、カーネルが見る必要がある領域の半分が存在しないため、あなたのイメージを埋め込むためのもの)。 numpyのは、2D FFTを持っているので

1)あなたはフーリエ変換と組み合わせた畳み込み定理を変換し使用することができます:あなたはscipyのダウンロードを使用しない場合

4

は、次の3つのオプションがあります。

2)分離可能なカーネルを使うことができます。次に、x方向とy方向の2つの1D畳み込みを行います。結果は2D畳み込みとして生じる。

3)小さなカーネル、たとえば3x3を使用している場合は、畳み込みを乗算と合計として書き出すだけで十分です。これは面倒なように聞こえるが、それほど悪くはない。

scipyを使用したい場合は、tcaswellが示唆するようにngimageを使用できます。 scipyにもconvolve2dがあります。