ピクセル補間(ビニング?)アルゴリズムを作成しようとしています(たとえば、4つのピクセルを取り、それらの平均を取り、その平均を新しいピクセルとして生成したい)。「分割」プロセスを高速化するためのストライド トリックに成功しましたが、実際の計算は非常に遅いです。256x512 の 16 ビット グレースケール イメージの場合、私のマシンでは平均化コードが 7 秒かかります。データセットに応じて、2k から 20k の画像を処理する必要があります。目的は、画像のノイズを少なくすることです (提案された方法で解像度が低下することは承知していますが、これは私の目的にとって悪いことではないかもしれません)。
import numpy as np
from numpy.lib.stride_tricks import as_strided
from scipy.misc import imread
import matplotlib.pyplot as pl
import time
def sliding_window(arr, footprint):
""" Construct a sliding window view of the array"""
t0 = time.time()
arr = np.asarray(arr)
footprint = int(footprint)
if arr.ndim != 2:
raise ValueError("need 2-D input")
if not (footprint > 0):
raise ValueError("need a positive window size")
shape = (arr.shape[0] - footprint + 1,
arr.shape[1] - footprint + 1, footprint, footprint)
if shape[0] <= 0:
shape = (1, shape[1], arr.shape[0], shape[3])
if shape[1] <= 0:
shape = (shape[0], 1, shape[2], arr.shape[1])
strides = (arr.shape[1]*arr.itemsize, arr.itemsize,
arr.shape[1]*arr.itemsize, arr.itemsize)
t1 = time.time()
total = t1-t0
print "strides"
print total
return as_strided(arr, shape=shape, strides=strides)
def binning(w,footprint):
#the averaging block
#prelocate memory
binned = np.zeros(w.shape[0]*w.shape[1]).reshape(w.shape[0],w.shape[1])
#print w
t2 = time.time()
for i in xrange(w.shape[0]):
for j in xrange(w.shape[1]):
binned[i,j] = w[i,j].sum()/(footprint*footprint + 0.0)
t3 = time.time()
tot = t3-t2
print tot
return binned
Output:
5.60283660889e-05
7.00565886497
私が望むのと同じことをする組み込み/最適化された関数はありますか、それともC拡張(または他の何か)を試してみるべきですか?
ここでは関数が最も重要だと思うので、完全を期すためにコードの追加部分を以下に示します。画像のプロットが遅いですが、改善する方法があると思います。
for i in range(2000):
arr = imread("./png/frame_" + str("%05d" % (i + 1) ) + ".png").astype(np.float64)
w = sliding_window(arr,footprint)
binned = binning(w,footprint)
pl.imshow(binned,interpolation = "nearest")
pl.gray()
pl.savefig("binned_" + str(i) + ".png")
enter code here
私が探しているのは補間と呼ばれるものです。私は、これを行うように私にアドバイスした人が使用した用語を使用しました. おそらくそれが、ヒストグラム関連のものを見つけていた理由です!
median_filter とは別に、scipy.ndimage から generic_filter を試しましたが、必要な結果が得られませんでした (畳み込みのような「有効な」モードはありませんでした。つまり、カーネルを移動するときに配列の境界を超えることに依存していました)。コードレビューで質問しましたが、この質問にはstackoverflowの方が適しているようです。