2017-07-31 63 views
0

私はscipyを使って循環フィルターを作成するためのコードスニペットを見つけました。私はスキマージでもっと良いものがあることを知っていますが、私はこの中で起こっていることに興味があります。Pythonで循環フィルターをコーディングする

from scipy.ndimage.filters import generic_filter as gf 

# Define physical shape of filter mask 
def circular_filter(image_data, radius): 
    kernel = np.zeros((2*radius+1, 2*radius+1)) 
    y, x = np.ogrid[-radius:radius+1, -radius:radius+1] 
    mask = x**2 + y**2 <= radius**2 
    kernel[mask] = 1     
    filtered_image = gf(image_data, np.median, footprint = kernel) 
    return filtered_image 

しかし、私は何が起こっているかを完全に理解していません。特に、正確に何を行うか

 y, x = np.ogrid[-radius:radius+1, -radius:radius+1] 
    mask = x**2 + y**2 <= radius**2 
    kernel[mask] = 1 

do?

私は以前の質問の1つの回答としてこれを掲載しましたが、回答がありませんでしたので、新しい質問として投稿しています。

答えて

1

詳細にコードを見てみる:

kernel = np.zeros((2*radius+1, 2*radius+1)) 
y, x = np.ogrid[-radius:radius+1, -radius:radius+1] 
mask = x**2 + y**2 <= radius**2 
kernel[mask] = 1     

最初のライン:いずれかの側の中心点と

kernel = np.zeros((2*radius+1, 2*radius+1)) 

がゼロの2次元配列を作成し、「半径」ポイント。半径= 2の場合は、あなたが得るでしょう:

# __r__ +1 __r__ 
[ 0, 0, 0, 0, 0, ] #\ 
[ 0, 0, 0, 0, 0, ] #_} r 
[ 0, 0, 0, 0, 0, ] # +1 
[ 0, 0, 0, 0, 0, ] #\ 
[ 0, 0, 0, 0, 0, ] #_} r 

次に、あなたはnumpy.ogridによって作成されたオープンメッシュグリッドから2つの配列を取得します。メッシュグリッドは、そのセルの位置で特定のセルのx座標またはy座標を保持する「並列」配列または行列を格納することを含むnumpyの「トリック」です。

例えば、y -meshグリッドは次のようになります。

[ 0, 0, 0, 0, 0, ] 
[ 1, 1, 1, 1, 1, ] 
[ 2, 2, 2, 2, 2, ] 
[ 3, 3, 3, 3, 3, ] 
[ 4, 4, 4, 4, 4, ] 

そしてx -meshグリッドは次のようになります。あなたがそれらを見れば

[ 0, 1, 2, 3, 4, ] 
[ 0, 1, 2, 3, 4, ] 
[ 0, 1, 2, 3, 4, ] 
[ 0, 1, 2, 3, 4, ] 
[ 0, 1, 2, 3, 4, ] 

、あなたを」 Y_grid[x][y] == yX_grid[x][y] == xは非常に便利なので、それをサポートするnumpy関数が複数あることに気づくでしょう。 ;-)

オープンメッシュグリッドは、「1次元」のみを有することを除いて、閉じたものと似ています。つまり、(例えば)5x5アレイのペアの代わりに、1x5アレイと5x1アレイが得られます。それはogridの機能です - 開いている2つのグリッドを返します。値は(除外された半径+ 1を意味する)Pythonのルールによれば、+ 1を半径と-radiusからのものである:

y, x = np.ogrid[-radius:radius+1, -radius:radius+1] 

そこでYは、例えばから格納numpyのアレイある-2..2 (両端を含む)であり、xは-2.2(両端を含む)の配列である。次のステップでは、ブール値マスクを作成します。つまり、ブール値でいっぱいの配列です。ご存じのように、numpy配列で操作すると、別のnumpy配列が得られます。そう定数式で二つの配列が関与する別の配列を生成する:

mask = x**2 + y**2 <= radius**2 

マスクの値は、一つの色が「真」であり、他の色が「Falseの2色ビットマップ、になるだろう。 "ビットマップには、円またはディスクが描かれます。 (<=の関係のため、xとyには0..4ではなく-2..2が含まれていることに注意してください。)

最後に、あなたはマスクが「真」であるときは常にものにゼロを設定し、ゼロのkernel配列()上のオーバーレイとしてマスキングアレイを用いてintにBoolean型から変換する:

kernel[mask] = 1 

この時点で、カーネルは次のようになります:

# __r__ +1 __r__ 
[ 0, 0, 1, 0, 0, ] #\ 
[ 0, 1, 1, 1, 0, ] #_} r 
[ 1, 1, 1, 1, 1, ] # +1 
[ 0, 1, 1, 1, 0, ] #\ 
[ 0, 0, 1, 0, 0, ] #_} r 
0

私はSciPyに慣れていませんが、基本的な概念を説明しようとしています。

この機能全体の目的は、フィルタを適用して元の画像を変更することです。この行で

 kernel = np.zeros((2*radius+1, 2*radius+1)) 

、のコピー:このフィルタは、

はのは、異なるラインを介して行こうなど、画像のコントラストを変更、または特殊効果を追加することから、多くのことを行うことができます画像データが作成されているが、すべてのデータがゼロである(したがって、ゼロ関数が使用されている)。これは後でマスクをその上に適用できるようにするためのものです。

 y, x = np.ogrid[-radius:radius+1, -radius:radius+1] 

これは、「メッシュグリッド」または多次元グリッドと呼ばれるものを作成しています。これは、円形のマスクを作成することです。グラフ上のように、x軸とy軸は等間隔にスケーリングされていますが、ここでもmeshgridでは同じことが必要です。 この場合のxおよびy変数には、軸のスケーリングとして使用される均等な間隔の値が格納されます。

 mask = x**2 + y**2 <= radius**2 

ここでは、「マスク」が作成されています。マスクは、元のデータを変更しないように、フィルタから保護される画像内の領域として機能します。 Pythagoreanの不等式(ここでは円ではなく円盤であることが重要である)でxとyの変数がどのように使用されているかに注目してください。これにより、指定された半径のマスクがマスクと見なされます。マスク変数には、元のデータ値を変更しない場合の座標(x、y)がすべて含まれるようになりました。

 kernel[mask] = 1 

ここで、以前に作成されたイメージのコピーにマスクが適用されます。現在、画像の完全なコピー(すなわち同じ寸法)があるが、元のデータが変更されるのを「保護する」ディスク状の「マスク」がある。これは、ディスクがカバーするすべての点が1に設定されている理由です。また、kernelmaskの寸法がどのように一致するかに注意してください。どちらも多次元です。最初の行で行われたように、イメージ・コピーの残りの値はゼロに設定されます。

 filtered_image = gf(image_data, np.median, footprint = kernel) 

これは最終的なものであり、すべてをつなぎ合わせたものです。 image_dataに格納されている元のデータがあり、kernelがあります。これは、マスクを適用したイメージコピーで、データを変更しない場所を示しています。両方ともパラメータとして実際のフィルタ関数gf(汎用フィルタを表します)に渡され、出力は新しいフィルタ処理された画像になります。

これはイメージフィルタリングの中核概念であり、詳細を知りたい場合は、基本的な信号処理の概念を学ぶことから始めてください。信号処理コースは、これらの概念がどのように機能するかの数学をカバーしますが、実際に抽象的な数学で説明されるのは、この概念が数多くの異なる例に適用できるためです。

+0

マスクは画像内で変更されない領域を識別すると言います。しかし、画像を変更するフィルターのポイントではありませんか?それとも、元の画像そのものではなく、画像のコピーであると言っていますか?それはフィルタによって変更されていますか? – Jim421616

+0

マスクは画像内で変更されない領域を識別します。それを保護するために顔のマスクのように、マスクは元のデータが変更されるのを「保護」しています。これにより、画像の他の部分はフィルタリングされたままになります。イメージのマスクされた部分は、 'kernel' meshgridに1の座標で示されます。露出部分は0の座標を持ちます。 –

+0

ああ、私は0と1をマスキングしていました!私の間違い。ありがとう:) – Jim421616