Bagaimana cara buffer piksel raster berdasarkan nilainya?

28

Pixel di sebelah kiri mewakili lokasi pohon dan jari-jari mahkota terkait (yaitu nilai piksel mulai dari 2 - 5). Saya ingin buffer piksel raster ini dengan nilai radius mahkota mereka. Gambar di sebelah kanan adalah apa yang saya harap dapat capai dengan hanya menggunakan metode pemrosesan raster .

Saya awalnya akan berpikir untuk menggunakan jumlah fokus melingkar di ArcGIS, meskipun pengaturan lingkungan adalah nilai tetap, yang tidak akan memperhitungkan jari-jari mahkota ukuran variabel.

Apa metode yang baik untuk "buffer" piksel berdasarkan nilainya?

masukkan deskripsi gambar di sini

Harun
sumber
2
Apakah Anda mencoba mengonversi raster ke poin, lalu buffer berdasarkan bidang lalu dikonversi kembali ke raster?
2
Ini membantu untuk menyadari bahwa ini adalah operasi non-lokal , karena non-lokal menunjukkan ada batas yang melekat pada bagaimana perhitungan dapat dilakukan. Misalnya, output Anda akan berubah secara radikal hampir di mana-mana jika hanya satu piksel yang terisolasi di input berubah menjadi nilai yang besar. Dengan demikian, jika Anda mengetahui batasan pada nilai input, maka silakan bagikan, karena hal itu dapat menghasilkan solusi yang lebih baik. Misalnya, apakah semua nilai input Anda selalu berada di set {2,3,4}?
whuber
@Dan Patterson Begitulah cara saya menghasilkan gambar di sebelah kanan. Namun, saya mencoba untuk menghindari operasi vektor sekaligus dan menghindari langkah-langkah itu.
Aaron
2
@whuber Dataset ini mewakili pohon dengan diameter mahkota variabel. Mengingat bahwa, pengukuran radius mahkota pohon secara realistis dapat bervariasi dari 1-10. Saya juga harus menambahkan bahwa output buffer hanya perlu 0 untuk tidak adanya mahkota dan 1 untuk kehadiran mahkota.
Aaron
1
Ok terima kasih. Sepertinya Anda membuat contoh output dengan menyatukan 3-buffer poin dengan nilai 3, 4-buffer poin dengan nilai 4, dan 5-buffer poin dengan nilai 5. (Anda sepertinya sudah lupa untuk memproses poin dengan nilai 2.) Proses itu tidak hanya menjawab pertanyaan Anda, tetapi (saya percaya) itu adalah solusi paling sederhana menggunakan alat yang tersedia di Spatial Analyst.
whuber

Jawaban:

14

Berikut ini adalah solusi raster murni dalam Python 2.7menggunakan numpydan scipy:

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()

Memasukkan: masukkan deskripsi gambar di sini

Keluaran: masukkan deskripsi gambar di sini

jatobat
sumber
1
+1 untuk pendekatan pelebaran! Ia bekerja dengan titik dekat juga.
Antonio Falciano
Ini adalah contoh yang bagus tentang mengapa colourcheme jet tua itu mengerikan. Ini terlihat lebih jelas dengan viridis.
naught101
8

Pendekatan berbasis vektor

Tugas ini dapat dilakukan dalam tiga langkah:

Catatan: menggunakan bidang buffer menghindari penghitungan buffer untuk setiap nilai radius mahkota.


Pendekatan berbasis raster

Menghindari solusi berbasis vektor, masalah ini menyarankan untuk menggunakan semacam Cellular Automata berdasarkan tetangga terdekat. Dengan asumsi bahwa semua piksel hitam adalah nol, piksel tersebut dikuadratkan dan ukurannya sama dengan 1 (atau, jika tidak, diskalakan dengan tepat), aturan untuk mengadopsi sangat sederhana:

  1. Jika nilai piksel ( VALUE) lebih besar dari 1, nilainya menjadi VALUE-1dan kemudian mempertimbangkan piksel sekitarnya. Jika nilainya kurang dari VALUE-1, piksel ini lahir atau tumbuh dan nilainya menjadi VALUE-1. Jika tidak, piksel ini bertahan dan dibiarkan tidak berubah.
  2. Jika VALUE<=1, jangan lakukan apa pun (pikselnya mati!).

Aturan-aturan ini harus diterapkan sampai semua piksel mati, yaitu nilainya sama dengan 0 atau 1. Jadi N-1kali, di mana Nnilai maksimum yang Anda miliki di input raster. Pendekatan ini dapat dengan mudah diimplementasikan dengan sedikit Python dan numpy.

Antonio Falciano
sumber
1
Terima kasih atas tanggapannya afalciano. Metode ini adalah bagaimana saya membuat gambar ke kanan dan menggunakan pendekatan vektor - yang saya coba hindari.
Aaron
1
Ok Aaron, ini pendekatan berbasis raster sekarang. Semoga ini membantu.
Antonio Falciano
7

Pilihan lain adalah membuat raster terpisah untuk setiap nilai piksel, dalam hal ini raster 4, dengan syarat. Kemudian perluas raster dengan jumlah piksel yang sesuai dengan nilai raster (dengan kemungkinan iterasi pada daftar nilai). Terakhir, bergabunglah dengan raster (baik aljabar atau spasial), untuk membuat satu raster biner untuk mahkota pohon.

HDunn
sumber
1
Ide ini benar. Rinciannya dapat ditingkatkan: (1) seleksi menciptakan indikator biner (0,1) dari pohon-pohon dari radius mahkota yang diberikan. (2) Jumlah fokus dari pemilihan itu - menggunakan lingkungan melingkar dari radius yang diberikan - cepat untuk dihitung menggunakan FFT. (3) Menambahkan jumlah fokus (searah) dan membandingkannya dengan 0 memberikan buffer yang diinginkan.
whuber
7

Ini adalah pertanyaan yang menantang untuk melakukan ini dalam raster karena Anda tidak memiliki kesempatan untuk menggunakan nilai piksel untuk menentukan ukuran buffer. Karena itu, Anda perlu melakukan focal filter untuk setiap nilai, seperti yang sudah Anda katakan.

Berikut ini adalah jawaban yang mungkin untuk melakukannya dengan hanya 3 filter (saya tidak dapat menemukan lebih sedikit), tetapi tidak sempurna seperti yang disebutkan oleh Whuber: buffer Anda akan terpotong ketika pohon berdekatan satu sama lain.

1) EDIT: Alokasi Euclidian (ini tidak sepenuhnya menyelesaikan masalah, karena memotong buffer di sekitar pohon yang lebih kecil, tetapi lebih baik daripada artefak dari solusi pertama saya).

2) jarak euclidian di sekitar setiap piksel

3) kalkulator raster (aljabar peta) dengan pernyataan kondisional

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

Perhatikan bahwa Anda dapat menyesuaikan kondisi tergantung pada kebutuhan Anda dalam hal jari-jari (dengan atau tanpa piksel tengah)

radouxju
sumber
+1 Ini adalah pendekatan kreatif. Saya akan menguji untuk melihat apakah layak untuk meningkatkan menggunakan pendekatan ini.
Aaron
2
Pendekatan jarak Euclidean tidak akan berhasil, karena hanya menghitung jarak ke pohon terdekat , yang belum tentu jarak ke pohon yang mahkotanya menutupi titik.
whuber
2

Bertanya-tanya mengapa Anda tidak menggunakan alat memperluas 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)

Jika tumpang tindih: expandperintah terbaru akan mencakup yang sebelumnya.

Tuan Che
sumber
2

Jika Anda memiliki posisi piksel, jari-jari dan algoritma lingkaran Midpoint (varian dari Bresenham Alg.) Memberi Anda petunjuk. IMO mudah untuk membuat poligon dari pendekatan ini dan saya pikir mudah untuk mengimplementasikannya dengan Python. Gabungan dari set poligon ini memberi Anda area penutup.

huckfinn
sumber
Saya tahu ini bukan masalah pertanyaan, tetapi, apakah Anda ingin tahu lebih banyak tentang primitif grafis dan memindai garis poligon isi? Untuk cirles itu sangat mudah. Kombinasi cembung adalah kata kunci dan sebagainya ....
huckfinn
Bagaimana ini diterapkan menggunakan operasi raster dasar?
whuber
Jika Anda mencoba menangani ini di ruang raster, tentukan titik lingkaran, mengurutkannya dengan y atau x dan mengisi ruang dengan garis lurus (garis pindai) sedang dalam perjalanan untuk mengisi lingkaran. Dalam pendekatan segitiga, jika Anda membangun lingkaran dengan perkiraan sektor tringular dan mencoba mengisi segitiga Anda perlu tes jika titik di dalam atau di luar (kombinasi cembung) dan sebaliknya. Dan di appoach "SIG", membangun poligon (poligon berorientasi jam bijaksana) dan membuat serikat adalah yang ketiga (IMO yang paling mahal secara komputasi).
huckfinn
Untuk menjadi jelas: Dan dalam pendekatan "GIS" ... buat operasi aljebrarik seperti penyatuan, persimpangan, sentuh .... adalah IMO ketiga yang paling mahal secara komputasi.
huckfinn