0から1の範囲の値を持つ画像があります。私がやりたいのは単純な平均化です。
しかし、より具体的には、画像の境界にあるセルについて、画像の範囲内にある近隣/カーネルのその部分のピクセルの平均を計算したいと思います。実際、これは、合計を除算するピクセル数である「平均式」の分母を適応させるために要約されます。
以下に示すようにscipy.ndimage.generic_filter
、でこれを行うことができましたが、これは時間効率にはほど遠いです。
def fnc(buffer, count):
n = float(sum(buffer < 2.0))
sum = sum(buffer) - ((count - b) * 2.0)
return (sum / n)
avg = scipy.ndimage.generic_filter(image, fnc, footprint = kernel, \
mode = 'constant', cval = 2.0, \
extra_keywords = {'count': countkernel})
詳細
kernel
=正方形の配列(1で表される円)- それ以降、ゼロではなく2でパディングすると、パディングされた領域のゼロと実際のラスターのゼロを適切に分離できませんでした。
countkernel
=の1の数kernel
n
=image
2の値で識別されるパディングされた領域のセルを除外することにより、その中にあるセルの数sum
元の近隣の合計から(パディングされたセルの数* 2.0)を引くことによって修正します
更新
1)NaNでパディングすると、計算が約30%増加します。
def fnc(buffer):
return (numpy.nansum(buffer) / numpy.sum([~numpy.isnan(buffer)]))
avg = scipy.ndimage.generic_filter(image, fnc, footprint = kernel, \
mode = 'constant', cval = float(numpy.nan)
2)Yves Daoustによって提案されたソリューション(受け入れられた回答)を適用すると、処理時間が最小限に抑えられます。
def fnc(buffer):
return numpy.sum(buffer)
sumbigimage = scipy.ndimage.generic_filter(image, fnc, \
footprint = kernel, \
mode = 'constant', \
cval = 0.0)
summask = scipy.ndimage.generic_filter(mask, fnc, \
footprint = kernel, \
mode = 'constant', \
cval = 0.0)
avg = sumbigimage / summask
3)Yvesのヒントに基づいて、実際にはマスクを適用している追加のバイナリイメージを使用するために、マスクされた配列の原理に出くわしました。そのため、マスクされた配列は画像とマスク配列を「ブレンド」するため、1つの配列のみを処理する必要があります。
マスク配列の詳細:前回の更新で行ったように、内側の部分(元の画像の範囲)を1で埋め、外側の部分(境界線)を0で埋める代わりに、その逆を行う必要があります。マスクされた配列の1は「無効」を意味し、0は「有効」を意味します。
このコードは、アップデート2)で提供されたコードよりもさらに50%高速です。
maskedimg = numpy.ma.masked_array(imgarray, mask = maskarray)
def fnc(buffer):
return numpy.mean(buffer)
avg = scipy.ndimage.generic_filter(maskedimg, fnc, footprint = kernel, \
mode = 'constant', cval = 0.0)
->ここで自分を正さなければなりません!
いくつかの計算を実行した後scipy.ndimage.<filters>
、フィルター操作中にマスクが考慮されないという意味でmasked_arraysを処理できないように見えたため、検証中に誤解されたに違いありません。ここやここ
のように、他の何人かの人々もこれについて言及。
画像の力...
- 灰色:処理される画像の範囲
- 白:パッド入りの領域(私の場合は2.0で埋められています)
- 赤い色合い:カーネルの範囲
- 濃い赤:効果的な隣人
- 明るい赤:無視される近隣の一部
計算のパフォーマンスを向上させるために、このかなり実用的なコードをどのように変更できますか?
よろしくお願いします!