ラスタピクセルを値でバッファする方法は?


28

左側のピクセルは、ツリーの位置とそれに関連するクラウン半径(つまり、2〜5の範囲のピクセル値)を表します。これらのラスターピクセルをクラウン半径値でバッファリングしたいと思います。右の画像はラスタ処理方法のみを使用して達成たいものです。

近隣設定は固定値ですが、可変サイズのクラウン半径は考慮されませんが、最初はArcGISで円形の焦点和を使用することを考えます。

値でピクセルを「バッファリング」するのに良い方法は何ですか?

ここに画像の説明を入力してください


2
ラスタをポイントに変換してから、フィールドごとにバッファしてから、ラスタに再び変換しようとしましたか?

2
この非局所性は、計算の実行方法に固有の制限があることを示しているため、これは非局所操作であることを認識するのに役立ちます。たとえば、入力の単一の孤立したピクセルが大きな値に変更される場合、出力はほぼどこでも根本的に変化します。したがって、入力値の制限を知っている場合は、それらを共有してください。ソリューションを改善できる可能性があるためです。たとえば、すべての入力値は常にセット{2,3,4}に含まれますか?
whuber

@Dan Pattersonこれが、右の画像を思いついた方法です。ただし、ベクトル演算を完全に回避し、それらの手順を回避しようとしています。
アーロン

2
@whuberこのデータセットは、冠の直径が変化する樹木を表します。それを考えると、樹冠の半径の測定値は1-10から現実的に変化する可能性があります。また、バッファー出力は、クラウンが存在しない場合は0のみ、クラウンが存在する場合は1のみである必要があることも追加する必要があります。
アーロン

1
はい、ありがとう。値3のポイントの3バッファー、値4のポイントの4バッファー、および値5のポイントの5バッファーを結合して、出力例を作成したようです(忘れたようです)値2のポイントを処理します。)そのプロセスはあなたの質問に答えるだけでなく、(私は信じています)Spatial Analystで利用可能なツールを使用した最も簡単なソリューションです。
whuber

回答:


14

以下はand をPython 2.7使用した純粋なラスターソリューションです。numpyscipy

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt

#create tree location matrix with values indicating crown radius
A = np.zeros((120,320))
A[60,40] = 1
A[60,80] = 2
A[60,120] = 3
A[60,160] = 4
A[60,200] = 5
A[60,240] = 6
A[60,280] = 7

#plot tree locations
fig = plt.figure()
plt.imshow(A, interpolation='none')
plt.colorbar()

#find unique values
unique_vals = np.unique(A)
unique_vals = unique_vals[unique_vals > 0]

# create circular kernel
def createKernel(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
    return kernel

#apply binary dilation sequentially to each unique crown radius value 
C = np.zeros(A.shape).astype(bool)   
for k, radius in enumerate(unique_vals):  
    B = ndimage.morphology.binary_dilation(A == unique_vals[k], structure=createKernel(radius))
    C = C | B #combine masks

#plot resulting mask   
fig = plt.figure()
plt.imshow(C, interpolation='none')
plt.show()

入力: ここに画像の説明を入力してください

出力: ここに画像の説明を入力してください


1
膨張アプローチの+1!ニアポイントでも機能します。
アントニオファルチャーノ

これは、その古いジェットカラースキームがひどいものだった理由の素晴らしい例です。これはviridisを使用することでより明確になります。
naught101

8

ベクトルベースのアプローチ

このタスクは、3つのステップで実行できます。

注:バッファフィールドを使用すると、各クラウン半径値のバッファの計算が回避されます。


ラスターベースのアプローチ

ベクトルベースのソリューションを回避するため、この問題は、最も近い隣人に基づいた一種のセルオートマトンを使用することを提案します。すべての黒ピクセルがゼロであり、ピクセルが二乗され、サイズが1に等しい(または、適切にスケーリングされている)と仮定すると、採用するルールは非常に単純です。

  1. ピクセル値(VALUE)が1より大きい場合、その値になりVALUE-1、周囲のピクセルを考慮します。それらの値がより少ない場合にはVALUE-1、これらのピクセル生まれ成長とそれらの値になるがVALUE-1。それ以外の場合、これらのピクセルは存続し、変更されません。
  2. の場合VALUE<=1、何もしません(ピクセルは死んでいます!)。

これらのルールは、すべてのピクセルが死んでいるまで、すなわちその値が0または1そうに等しい適用する必要がN-1回、Nあなたが入力ラスタを持っている最大値です。このアプローチは、少しのPythonとnumpyを使用して非常に簡単に実装できます。


1
afalcianoの回答に感謝します。この方法は、右側の画像を作成する方法であり、ベクトルアプローチを使用しています。
アーロン

1
オーケーアーロン、これはラスターベースのアプローチです。お役に立てれば。
アントニオファルチャーノ14

7

別のオプションは、各ピクセル値に対して個別のラスタを作成することです。この場合、条件付きで4つのラスタを作成します。次に、ラスターの値に対応するピクセル数でラスターを展開します(値リストを繰り返し処理することにより)。最後に、ラスターを(代数的または空間的に)結合して、樹冠用の1つのバイナリラスターを作成します。


1
このアイデアは正しいものです。詳細を改善できます。(1)選択すると、指定されたクラウン半径の木のバイナリ(0,1)インジケータが作成されます。(2)指定された半径の円形近傍を使用したその選択の焦点和は、FFTを使用して高速に計算されます。(3)焦点和を(点ごとに)加算し、それを0と比較すると、目的のバッファーが得られます。
whuber

7

バッファーのサイズを定義するためにピクセルの値を使用する機会がないため、これをラスターで行うのは難しい質問です。したがって、すでに述べたように、各値に対して焦点フィルターを実行する必要があります。

これは3つのフィルター(これより少ないものは見つかりませんでした)でそれを行うための可能な答えです。

1)編集:ユークリッド割り当て(これは、小さな木の近くのバッファーをカットするため、問題を完全には解決しませんが、最初のソリューションのアーティファクトよりも優れています)。

2)各ピクセルのユークリッド距離

3)条件ステートメントを含むラスター計算機(マップ代数)

Con("allocation_result" > ("distance_result" / pixel_size) , 1 , 0)

半径の観点からニーズに応じて条件を調整できることに注意してください(中心ピクセルの有無にかかわらず)


+1これは創造的なアプローチです。このアプローチを使用してスケールアップすることが実現可能かどうかをテストします。
アーロン

2
ユークリッド距離アプローチは、最も近いツリーまでの距離のみを計算するため、機能しません。これは、クラウンがポイントをカバーするツリーまでの距離とは限りません。
whuber

2

ArcGISの展開ツールを使用してみませんか?

import arcpy
from arcpy.sa import *

raster_in  = r'c:\test.tif'
raster_out = r'c:\test_out.tif'

outExpand1 = Expand(raster_in, 2, 2)
outExpand2 = Expand(outExpand1, 3, 3)
outExpand3 = Expand(outExpand3, 4, 4)
outExpand4 = Expand(outExpand4, 5, 5)

outExpand4.save(raster_out)

重複する場合:最新のexpandコマンドは前のものをカバーします。


2

ピクセル位置がある場合は、半径と中点円アルゴリズム(ブレゼンハムアルゴリズムの変形)が手がかりになります。IMOでは、このアプローチからポリゴンを簡単に作成できます。これをPythonで実装するのは簡単だと思います。この一連のポリゴンを結合すると、カバー領域が得られます。


私はそれが問題ではないことを知っていますが、グラフィックプリミティブとスキャンラインポリゴンの塗りつぶしについてもっと知りたいですか?サークルについては非常に簡単です。凸状の組合せは流行語であるので、....オン
huckfinn

基本的なラスター操作を使用してこれをどのように適用しますか?
whuber

ラスタ空間でこれを処理しようとする場合、円のポイントを決定し、yまたはxでそれらをソートし、直線(スキャンライン)で空間を埋めて、円を埋めます。三角形のアプローチでは、三角形の扇形の近似によって円を構築し、三角形を塗りつぶそうとする場合、ポイントが内側か外側か(凸の組み合わせ)であるかどうかをテストする必要があります。そして、「GIS」の手法では、ポリゴン(時計回りのポリゴン)を構築し、ユニオンを作成することが3番目(IMOが最も高価なもの)です。
huckfinn 14

明確にするために:そして、「GIS」アプローチでは、結合、交差、タッチなどの代数演算を行います。3番目のIMOは最も計算上の高価なものです。
huckfinn 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.