การค้นหาตำแหน่งที่มีค่าสูงสุดในแรสเตอร์โดยใช้ ArcGIS Desktop?


12

ใช้ ArcGIS 10 ฉันมีแรสเตอร์ที่ฉันต้องการค้นหาพิกเซลที่มีค่าสูงสุดในแรสเตอร์และส่งคืนตำแหน่ง (จุดศูนย์กลางของพิกเซล) เป็นองศาทศนิยม ฉันต้องการวนซ้ำกระบวนการนี้คืนตำแหน่งที่มีค่าสูงสุดเป็นอันดับที่สองของแรสเตอร์จากนั้นจึงเป็นอันดับสามและต่อ ๆ ไปในที่สุดฉันก็จะมีรายการของที่ตั้ง N ที่มีค่าสูงสุดในลำดับตามลำดับ

ฉันคิดว่าสิ่งนี้อาจทำได้ง่ายที่สุดโดยใช้สคริปต์ Python แต่ฉันเปิดรับความคิดอื่น ๆ หากมีวิธีที่ดีกว่า


คุณได้ลองแปลงตารางเป็นจุดแล้วเพิ่มเขตข้อมูล X, Y และการเรียงลำดับ?
Jakub Sisak GeoGraphics

ค่าแรสเตอร์ลอยหรือจำนวนเต็มหรือไม่?
whuber

@Jakub - ไม่ฉันยังไม่ได้ ฉันอาจจะสนใจเพียง 1% ของคะแนนดังนั้นฉันไม่รู้ว่ามันคุ้มค่าที่จะเพิ่ม x, y สำหรับทุกจุดแล้วเรียงลำดับ บางทีถ้าไม่มีตัวเลือกที่มีประสิทธิภาพมากกว่านี้?
MGA

@whuber - ค่าแรสเตอร์เป็นแบบลอย
MGA

@mga มันคุ้มค่าที่จะลอง การแปลงค่อนข้างเร็วและการเพิ่ม XY ยังเป็นเครื่องมือเริ่มต้น การลบบันทึกที่ไม่พึงประสงค์เป็นการดำเนินการตรงไปตรงมาและทั้งหมดสามารถรวมเป็นแบบจำลองเดียว แค่ความคิด
Jakub Sisak GeoGraphics

คำตอบ:


5

หากคุณมีความสุขในการใช้Rมีเป็นแพคเกจที่เรียกว่าแรสเตอร์ คุณสามารถอ่านในแรสเตอร์โดยใช้คำสั่งต่อไปนี้:

install.packages('raster')
library(raster)
test <- raster('F:/myraster')

จากนั้นเมื่อคุณไปดูที่ (โดยพิมพ์test) คุณสามารถดูข้อมูลต่อไปนี้:

class       : RasterLayer 
dimensions  : 494, 427, 210938  (nrow, ncol, ncell)
resolution  : 200, 200  (x, y)
extent      : 1022155, 1107555, 1220237, 1319037  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=23 +lon_0=-96 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs +towgs84=0,0,0 
values      : F:/myraster 
min value   : 0 
max value   : 1 

อาจมีวิธีที่ดีกว่าในการจัดการแรสเตอร์ แต่วิธีหนึ่งในการค้นหาข้อมูลที่คุณต้องการคือการหาค่าสูงสุดและรับตำแหน่งเมทริกซ์แล้วเพิ่มเข้าไปในขอบเขตที่ต่ำกว่า


1
+1 สำหรับการอ้างอิงนี้ เมื่อคุณอ่านแรสเตอร์เข้าไปRแล้วคุณสามารถใช้Rฟังก์ชั่นมาตรฐานหรือgetValuesวิธีการในการเข้าถึงค่าของเซลล์ จากตรงไปตรงมาเพื่อระบุค่าสูงสุดและตำแหน่งของพวกเขา
whuber

1
ขอบคุณคำแนะนำของคุณนี่คือสิ่งที่ฉันได้ทำลงไป การใช้แพ็คเกจแรสเตอร์ใน R นั้นง่ายกว่าเมื่อลองใช้ ArcGIS ฉันยังคงใช้การวิเคราะห์เชิงพื้นที่อื่น ๆ ใน R และมีความสุขมากกับผลลัพธ์ คำแนะนำที่ดี!
MGA

8

คำตอบสามารถทำได้โดยการรวมตารางตัวบ่งชี้ของ 1% สูงสุดของค่ากับกริดของละติจูดและลองจิจูด เคล็ดลับอยู่ในการสร้างตารางตัวบ่งชี้นี้เพราะ ArcGIS (ยัง! หลังจาก 40 ปี!) ไม่มีกระบวนการจัดอันดับข้อมูลแรสเตอร์

ทางออกหนึ่งสำหรับ rasters จุดลอยตัวเป็นซ้ำ แต่เมตตาอย่างรวดเร็ว ให้nเป็นจำนวนเซลล์ข้อมูล กระจายสะสมเชิงประจักษ์ของค่าประกอบด้วยคู่ทั้งหมด (Z, n (z)) ซึ่งZเป็นค่าในตารางและn (z)คือจำนวนของเซลล์ในตารางที่มีค่าน้อยกว่าหรือเท่ากับZ เราได้รับการเชื่อมต่อเส้นโค้ง (-infinity, 0) ถึง (อินฟินิตี้ + n) ออกจากลำดับของจุดเหล่านี้ได้รับคำสั่งจากZ มันกำหนดฟังก์ชั่นfโดยที่ (z, f (z)) อยู่บนเส้นโค้งเสมอ คุณต้องการหาจุด (z0, 0.99 * n) บนเส้นโค้งนี้

ในคำอื่น ๆงานคือการหาศูนย์ของ f (z) - (1-0.01) n * ทำสิ่งนี้กับกิจวัตรประจำศูนย์ใด ๆ (ที่สามารถจัดการกับฟังก์ชั่นโดยพลการ: อันนี้ไม่แตกต่างกัน) สิ่งที่ง่ายที่สุดซึ่งมักจะมีประสิทธิภาพคือการเดาและตรวจสอบ: เริ่มแรกคุณรู้ว่า z0 อยู่ระหว่างค่าต่ำสุด zMin และสูงสุด zMax เดาค่าใด ๆ ที่สมเหตุสมผลระหว่างสองสิ่งนี้อย่างเคร่งครัด หากการเดาต่ำเกินไปให้ตั้ง zMin = z0; มิฉะนั้นตั้ง zMax = z0 ตอนนี้ทำซ้ำ คุณจะเข้าหาโซลูชันอย่างรวดเร็ว คุณอยู่ใกล้พอเมื่อ zMax และ zMin ใกล้พอ เพื่ออนุรักษ์นิยมให้เลือกค่าสุดท้ายของ zMin เป็นวิธีแก้ปัญหา: มันอาจจะได้รับคะแนนพิเศษอีกสองสามอย่างที่คุณสามารถทิ้งได้ในภายหลัง สำหรับวิธีการที่ซับซ้อนยิ่งขึ้นโปรดดูบทที่ 9 ของสูตรตัวเลข (ลิงก์ไปยังเวอร์ชันฟรีที่เก่ากว่า)

เมื่อมองย้อนกลับไปที่อัลกอริทึมนี้คุณจะต้องดำเนินการแรสเตอร์เพียงสองประเภท : (1) เลือกเซลล์ทั้งหมดน้อยกว่าหรือเท่ากับค่าเป้าหมายบางส่วนและ (2) นับจำนวนเซลล์ที่เลือก สิ่งเหล่านี้คือการดำเนินงานที่ง่ายและรวดเร็วที่สุด (2) สามารถรับเป็นจำนวนนับหรือโดยการอ่านหนึ่งระเบียนจากตารางคุณลักษณะของตารางการเลือก


7

ฉันทำสิ่งนี้เมื่อไม่นานมานี้แม้ว่าวิธีแก้ปัญหาของฉันคือการใช้ GDAL (ดังนั้นนี่ไม่ได้เป็นเพียงแค่ ArcGIS) ฉันคิดว่าคุณสามารถรับ NumPy จากแรสเตอร์ใน ArcGIS 10 แต่ฉันไม่รู้แน่ NumPy จัดหาการทำดัชนีอาเรย์อย่างง่ายและมีประสิทธิภาพเช่นargsortและอื่น ๆ ตัวอย่างนี้ไม่ได้จัดการ NODATA หรือแปลงพิกัดจากการฉายเป็น lat / long (แต่นี่ไม่ใช่เรื่องยากที่จะทำกับ osgeo.osr ที่จัดทำโดย GDAL)

import numpy as np
from osgeo import gdal

# Open raster file, and get GeoTransform
rast_src = gdal.Open(rast_fname)
rast_gt = rast_src.GetGeoTransform()

def get_xy(r, c):
    '''Get (x, y) raster centre coordinate at row, column'''
    x0, dx, rx, y0, ry, dy = rast_gt
    return(x0 + r*dx + dx/2.0, y0 + c*dy + dy/2.0)

# Get first raster band
rast_band = rast_src.GetRasterBand(1)

# Retrieve as NumPy array to do the serious work
rast = rast_band.ReadAsArray()

# Sort raster pixels from highest to lowest
sorted_ind = rast.argsort(axis=None)[::-1]

# Show highest top 10 values
for ind in sorted_ind[:10]:
    # Get row, column for index
    r, c = np.unravel_index(ind, rast.shape)
    # Get [projected] X and Y coordinates
    x, y = get_xy(r, c)
    print('[%3i, %3i] (%.3f, %.3f) = %.3f'%
          (r, c, x, y, rast[r, c]))

แสดงสิ่งต่อไปนี้สำหรับไฟล์ทดสอบแรสเตอร์ของฉัน:

[467, 169] (2813700.000, 6353100.000) = 844.538
[467, 168] (2813700.000, 6353200.000) = 841.067
[469, 168] (2813900.000, 6353200.000) = 840.705
[468, 168] (2813800.000, 6353200.000) = 840.192
[470, 167] (2814000.000, 6353300.000) = 837.063
[468, 169] (2813800.000, 6353100.000) = 837.063
[482, 166] (2815200.000, 6353400.000) = 833.038
[469, 167] (2813900.000, 6353300.000) = 832.825
[451, 181] (2812100.000, 6351900.000) = 828.064
[469, 169] (2813900.000, 6353100.000) = 827.514

+1 ขอบคุณที่แบ่งปันสิ่งนี้ ฉันไม่เห็นว่าไม่สามารถจัดการ NoData เป็นข้อ จำกัด : เพียงแปลง NoData ทั้งหมดเป็นค่าลบอย่างมากก่อนที่จะดำเนินการต่อ โปรดทราบด้วยว่าหากการคัดแยกตารางใด ๆเกิดขึ้นคำตอบอาจมีการเปลี่ยนแปลงเนื่องจากการสุ่มตารางใหม่ดังนั้นโดยปกติจะไม่ต้องการให้มีการคัดลอกใหม่โดยอัตโนมัติระหว่างการคำนวณเช่นนี้ แต่พิกัดที่รายงานจะถูกปฏิเสธในภายหลัง ดังนั้นวิธีการแก้ปัญหาของคุณเป็นเรื่องทั่วไปอย่างสมบูรณ์แบบ
whuber

การจัดการ NODATA สามารถดำเนินการได้โดยรับค่าจากแรสเตอร์NODATA = rast_band.GetNoDataValue()ก่อนแล้วจึงใช้ค่า NaN ( rast[rast == NODATA] = np.nan) หรือโดยใช้อาร์เรย์ที่สวมหน้ากาก ( rast = np.ma.array(rast, mask=(rast == NODATA))) เคล็ดลับที่ซับซ้อนมากขึ้นคือการargsortลบค่า NODATA ออกจากการวิเคราะห์หรือเพียงแค่ข้ามผ่านค่า for-loop ถ้าพวกเขาเป็น NaN / masked
Mike T
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.