GDAL và Python: Làm thế nào để có tọa độ cho tất cả các ô có giá trị cụ thể?


12

Tôi đã có một Lưới nhị phân Arc / Info --- cụ thể, một raster tích lũy dòng ArcGIS --- và tôi muốn xác định tất cả các ô có một giá trị cụ thể (hoặc trong một phạm vi giá trị). Cuối cùng, tôi muốn một shapefile các điểm đại diện cho các ô này.

Tôi có thể sử dụng QGIS để mở hdr.adf và nhận được kết quả này, quy trình làm việc là:

  • QGIS> Trình đơn raster> Máy tính raster (đánh dấu tất cả các điểm bằng giá trị đích)
  • QGIS> Menu raster> Đa giác
  • QGIS> Menu Vector> menu con Hình học> Nhân đa giác
  • Chỉnh sửa các centroid để xóa các polyroid không mong muốn (những người = 0)

Cách tiếp cận này "thực hiện công việc", nhưng nó không hấp dẫn tôi vì nó tạo ra 2 tệp tôi phải xóa, sau đó tôi phải xóa (các) bản ghi không mong muốn khỏi shapefile của centroid (tức là = 0).

Một câu hỏi hiện có tiếp cận chủ đề này, nhưng nó phù hợp với ArcGIS / ArcPy và tôi muốn ở lại trong không gian FOSS.

Có ai có công thức / tập lệnh GDAL / Python hiện có để thẩm vấn các giá trị ô của raster không và khi tìm thấy giá trị đích --- hoặc giá trị trong phạm vi đích ---, một bản ghi sẽ được thêm vào shapefile? Điều này không chỉ tránh tương tác UI mà còn tạo ra kết quả rõ ràng trong một lần chạy.

Tôi đã bắn nó bằng cách làm việc với một trong những bài thuyết trình của Chris Garrard , nhưng công việc raster không phải trong nhà xe của tôi và tôi không muốn làm lộn xộn câu hỏi với mã yếu của mình.

Nếu ai muốn có bộ dữ liệu chính xác để chơi, tôi đặt nó ở đây dưới dạng .zip .


[Chỉnh sửa ghi chú] Để lại điều này cho hậu thế. Xem trao đổi bình luận với om_henners. Về cơ bản, các giá trị x / y (hàng / cột) đã được lật. Câu trả lời ban đầu có dòng này:

(y_index, x_index) = np.nonzero(a == 1000)

đảo ngược, như thế này:

(x_index, y_index) = np.nonzero(a == 1000)

Khi lần đầu tiên tôi gặp vấn đề được minh họa trong ảnh chụp màn hình, tôi tự hỏi liệu tôi có triển khai hình học không chính xác không và tôi đã thử nghiệm bằng cách lật các giá trị tọa độ x / y trong dòng này:

point.SetPoint(0, x, y)

..như..

point.SetPoint(0, y, x)

Tuy nhiên điều đó đã không làm việc. Và tôi đã không nghĩ sẽ thử lật các giá trị trong biểu thức Numpy của om_henners, tin sai rằng việc lật chúng ở một trong hai dòng là tương đương. Tôi nghĩ rằng vấn đề thực sự liên quan đến các giá trị x_sizey_size, tương ứng 30-30, được áp dụng khi các chỉ số hàng và cột được sử dụng để tính tọa độ điểm cho các ô.

[Chỉnh sửa gốc]

@om_henners, tôi đang thử giải pháp của bạn, phối hợp với một vài người nhận để tạo các shapefile điểm bằng cách sử dụng ogr ( invisibleroads.com , Chris Garrard ), nhưng tôi gặp vấn đề khi các điểm xuất hiện như thể được phản ánh qua một dòng xuyên qua 315/135 độ.

Điểm màu xanh nhạt : được tạo bởi phương pháp QGIS của tôi , ở trên

Điểm màu tím : được tạo bởi mã py GDAL / OGR , bên dưới

nhập mô tả hình ảnh ở đây


[Đã giải quyết]

Mã Python này thực hiện giải pháp hoàn chỉnh theo đề xuất của @om_henners. Tôi đã thử nó và nó hoạt động. Cảm ơn người đàn ông!


from osgeo import gdal
import numpy as np
import osgeo.ogr
import osgeo.osr

path = "D:/GIS/greeneCty/Greene_DEM/GreeneDEM30m/flowacc_gree/hdr.adf"
print "\nOpening: " + path + "\n"

r = gdal.Open(path)
band = r.GetRasterBand(1)

(upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = r.GetGeoTransform()

a = band.ReadAsArray().astype(np.float)

# This evaluation makes x/y arrays for all cell values in a range.
# I knew how many points I should get for ==1000 and wanted to test it.
(y_index, x_index) = np.nonzero((a > 999) & (a < 1001))

# This evaluation makes x/y arrays for all cells having the fixed value, 1000.
#(y_index, x_index) = np.nonzero(a == 1000)

# DEBUG: take a look at the arrays..
#print repr((y_index, x_index))

# Init the shapefile stuff..
srs = osgeo.osr.SpatialReference()
#srs.ImportFromProj4('+proj=utm +zone=15 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
srs.ImportFromWkt(r.GetProjection())

driver = osgeo.ogr.GetDriverByName('ESRI Shapefile')
shapeData = driver.CreateDataSource('D:/GIS/01_tutorials/flow_acc/ogr_pts.shp')

layer = shapeData.CreateLayer('ogr_pts', srs, osgeo.ogr.wkbPoint)
layerDefinition = layer.GetLayerDefn()

# Iterate over the Numpy points..
i = 0
for x_coord in x_index:
    x = x_index[i] * x_size + upper_left_x + (x_size / 2) #add half the cell size
    y = y_index[i] * y_size + upper_left_y + (y_size / 2) #to centre the point

    # DEBUG: take a look at the coords..
    #print "Coords: " + str(x) + ", " + str(y)

    point = osgeo.ogr.Geometry(osgeo.ogr.wkbPoint)
    point.SetPoint(0, x, y)

    feature = osgeo.ogr.Feature(layerDefinition)
    feature.SetGeometry(point)
    feature.SetFID(i)

    layer.CreateFeature(feature)

    i += 1

shapeData.Destroy()

print "done! " + str(i) + " points found!"

1
Mẹo nhanh cho mã của bạn: bạn có thể sử dụng phép chiếu raster làm phép chiếu shapefile của mình với srs.ImportFromWkt(r.GetProjection())(thay vì phải tạo phép chiếu từ chuỗi proj đã biết).
om_henners

Mã của bạn thực hiện mọi thứ tôi đang tìm kiếm ngoại trừ nó không bao gồm giá trị ô raster vì bạn đã viết bộ lọc gọn gàng của mình để chỉ bao gồm các giá trị = 1000. Bạn có thể chỉ cho tôi đúng hướng để đưa các giá trị ô raster vào đầu ra? Cảm ơn!
Brent Edwards

Câu trả lời:


18

Trong GDAL, bạn có thể nhập raster dưới dạng một mảng numpy.

from osgeo import gdal
import numpy as np

r = gdal.Open("path/to/raster")
band = r.GetRasterBand(1) #bands start at one
a = band.ReadAsArray().astype(np.float)

Sau đó, sử dụng numpy là một vấn đề đơn giản để có được các chỉ mục của một mảng khớp với biểu thức boolan:

(y_index, x_index) = np.nonzero(a > threshold)
#To demonstate this compare a.shape to band.XSize and band.YSize

Từ biểu đồ địa lý raster, chúng ta có thể nhận được thông tin như tọa độ x và y phía trên bên trái và kích thước ô.

(upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = r.GetGeoTransform()

Các ô trên bên trái tương ứng với a[0, 0]. Kích thước Y sẽ luôn âm, vì vậy bằng cách sử dụng các chỉ số x và y, bạn có thể tính tọa độ của từng ô dựa trên các chỉ mục.

x_coords = x_index * x_size + upper_left_x + (x_size / 2) #add half the cell size
y_coords = y_index * y_size + upper_left_y + (y_size / 2) #to centre the point

Từ đây, một vấn đề đủ đơn giản để tạo ra một shapefile bằng OGR. Đối với một số mã mẫu, hãy xem câu hỏi này để biết cách tạo bộ dữ liệu mới với thông tin điểm.


Hey fella, tôi có một vấn đề nhỏ khi thực hiện điều này. Tôi đã cập nhật câu hỏi để bao gồm mã tôi đang sử dụng và ghi lại những gì tôi nhận được. Về cơ bản, mã .py đang tạo ra một hình ảnh phản chiếu (vị trí điểm) về cách tiếp cận của QGIS đang tạo ra. Các điểm trong quá trình cấy ghép của tôi nằm ngoài giới hạn raster, vì vậy vấn đề phải nằm ở mã của tôi. : = Tôi hy vọng bạn có thể làm sáng tỏ. Cảm ơn!
elrobis

Xin lỗi về điều đó - hoàn toàn xấu của tôi. Khi bạn nhập raster trong GDAL, các hàng là hướng y và các cột là hướng x. Tôi đã cập nhật mã ở trên, nhưng mẹo là lấy các chỉ mục với(y_index, x_index) = np.nonzero(a > threshold)
om_henners

1
Ngoài ra, chỉ trong trường hợp, lưu ý thêm một nửa kích thước ô vào tọa độ theo cả hai hướng để căn giữa điểm trong ô.
om_henners

Đúng đó là vấn đề. Khi tôi lần đầu tiên gặp phải lỗi đó (như thể hiện trong phần chụp màn hình), tôi đã tự hỏi liệu tôi đã triển khai hình học điểm không chính xác chưa, vì vậy tôi đã thử lật x / y thành y / x khi tôi thực hiện .shp--- chỉ có điều đó không làm việc, cũng không ở đâu gần. Tôi đã không bị sốc vì giá trị x là hàng trăm nghìn và y là hàng triệu, vì vậy nó khiến tôi khá bối rối. Tôi đã không nghĩ sẽ thử lật chúng lại với biểu thức Numpy. Cảm ơn rất nhiều vì sự giúp đỡ của bạn, điều này thật tuyệt. Chính xác những gì tôi muốn. :)
elrobis

4

Tại sao không sử dụng hộp công cụ Sexante trong QGIS? Nó giống như Model Builder cho ArcGIS. Bằng cách đó, bạn có thể xâu chuỗi các hoạt động và coi nó như một hoạt động. Bạn có thể tự động xóa các tệp trung gian và xóa các bản ghi không mong muốn nếu tôi không nhầm.


1

Có thể hữu ích khi nhập dữ liệu vào postgis (có hỗ trợ raster) và sử dụng các chức năng ở đó. Hướng dẫn này có thể có các yếu tố bạn cần.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.