Numpy を使用した画像処理、具体的には実行中の標準偏差ストレッチの実行に取り組んでいます。これは X 列を読み取り、Std を見つけます。パーセンテージの線形ストレッチを実行します。次に、列の次の「グループ」に反復し、同じ操作を実行します。入力画像は 1 GB、32 ビット、シングル バンド ラスターであり、処理に非常に長い時間 (数時間) かかります。以下はコードです。
おそらくボトルネックが発生している場所である 3 つの入れ子になった for ループがあることに気付きました。「ボックス」で画像を処理する場合、つまり、[500,500] の配列をロードし、画像処理時間を繰り返すのは非常に短いです。残念ながら、カメラのエラーにより、バンディングを避けるために非常に長いストリップ (52,000 x 4) (y,x) で反復する必要があります。
これをスピードアップするための提案は大歓迎です:
def box(dataset, outdataset, sampleSize, n):
quiet = 0
sample = sampleSize
#iterate over all of the bands
for j in xrange(1, dataset.RasterCount + 1): #1 based counter
band = dataset.GetRasterBand(j)
NDV = band.GetNoDataValue()
print "Processing band: " + str(j)
#define the interval at which blocks are created
intervalY = int(band.YSize/1)
intervalX = int(band.XSize/2000) #to be changed to sampleSize when working
#iterate through the rows
scanBlockCounter = 0
for i in xrange(0,band.YSize,intervalY):
#If the next i is going to fail due to the edge of the image/array
if i + (intervalY*2) < band.YSize:
numberRows = intervalY
else:
numberRows = band.YSize - i
for h in xrange(0,band.XSize, intervalX):
if h + (intervalX*2) < band.XSize:
numberColumns = intervalX
else:
numberColumns = band.XSize - h
scanBlock = band.ReadAsArray(h,i,numberColumns, numberRows).astype(numpy.float)
standardDeviation = numpy.std(scanBlock)
mean = numpy.mean(scanBlock)
newMin = mean - (standardDeviation * n)
newMax = mean + (standardDeviation * n)
outputBlock = ((scanBlock - newMin)/(newMax-newMin))*255
outRaster = outdataset.GetRasterBand(j).WriteArray(outputBlock,h,i)#array, xOffset, yOffset
scanBlockCounter = scanBlockCounter + 1
#print str(scanBlockCounter) + ": " + str(scanBlock.shape) + str(h)+ ", " + str(intervalX)
if numberColumns == band.XSize - h:
break
#update progress line
if not quiet:
gdal.TermProgress_nocb( (float(h+1) / band.YSize) )
ここに更新があります:プロファイルモジュールを使用せずに、コードの小さなセクションを関数にラップしたくなかったので、print ステートメントと exit ステートメントを組み合わせて使用して、どの行が最も時間がかかっているかについて大まかなアイデアを得ました。幸いなことに(そして、私がどれほど幸運だったかを理解しています)、1行ですべてが引き下げられました。
outRaster = outdataset.GetRasterBand(j).WriteArray(outputBlock,h,i)#array, xOffset, yOffset
出力ファイルを開いて配列を書き出すとき、GDALは非常に非効率的であるようです。これを念頭に置いて、変更した配列「outBlock」を Python リストに追加し、チャンクを書き出すことにしました。変更したセグメントは次のとおりです。
outputBlock が変更されました...
#Add the array to a list (tuple)
outputArrayList.append(outputBlock)
#Check the interval counter and if it is "time" write out the array
if len(outputArrayList) >= (intervalX * writeSize) or finisher == 1:
#Convert the tuple to a numpy array. Here we horizontally stack the tuple of arrays.
stacked = numpy.hstack(outputArrayList)
#Write out the array
outRaster = outdataset.GetRasterBand(j).WriteArray(stacked,xOffset,i)#array, xOffset, yOffset
xOffset = xOffset + (intervalX*(intervalX * writeSize))
#Cleanup to conserve memory
outputArrayList = list()
stacked = None
finisher=0
フィニッシャーは、エッジを処理する単純なフラグです。リストから配列を作成する方法を理解するのに少し時間がかかりました。その中で、numpy.array を使用すると 3 次元配列が作成され (理由を説明したい人はいますか?)、write array には 2 次元配列が必要です。合計処理時間は、2 分弱から 5 分までさまざまです。時間の範囲が存在する理由は何ですか?
投稿してくださった皆様、本当にありがとうございました!次のステップは、実際に Numpy に取り掛かり、追加の最適化のためのベクトル化について学習することです。