簡體   English   中英

查找 GeoTiff 圖像中每個像素的緯度/經度坐標

[英]Find Latitude/Longitude Coordinates of Every Pixel in a GeoTiff Image

我目前有一個來自 GeoTiff 文件的 171 x 171 圖像(盡管在其他情況下,我可能有更大的圖像)。 我的目標是獲取圖像中的每個像素並轉換為緯度/經度對。

我已經能夠根據這個 StackOverflow 帖子將圖像的角轉換為緯度/經度對: 從 GeoTIFF 文件中獲取緯度和經度 這篇文章很有幫助,因為我的原始坐標位於 UTM 15 區。

但是,我現在想將圖像的所有像素轉換為緯度、經度對,並將結果存儲在相同維度的 numpy 數組中。 因此,output 將是一個 numpy 數組,其大小為 171 x 171 x 2,其中 numpy 數組的每個元素是一對(經度、經度)。

我看到的最相關的帖子是https://scriptndebug.wordpress.com/2014/11/24/latitudelongitude-of-each-pixel-using-python-and-gdal/ 但是,該帖子建議實質上在每個像素上創建一個 for 循環並轉換為緯度、經度。 有沒有更高效的方法?

只是為了給我的實際用例提供更多背景信息,我的最終目標是我有一堆衛星圖像(例如,在這種情況下,每個圖像都是 171 x 171)。 我正在嘗試創建一個建築分段 model。 現在,我正在嘗試通過在每個圖像上創建一個掩碼來生成標記的數據點,如果它對應於建築物,則將像素標記為 1,否則為 0。首先,我使用 Microsoft US Building Footprint 數據: https: //github.com/microsoft/USBuildingFootprints ,他們發布了他們檢測到的建築物的多邊形(由緯度、經度定義)的 GeoJSON 文件。 我正在考慮這樣做的方式是:

  1. 找到我圖像中每個像素的緯度、經度。 因此,我將有 171 x 171 點。 把它放在一個 GeoSeries
  2. 將點(在 GeoSeries 中)與 Microsoft US Building Footprints 數據相交(使用 GeoPandas 相交: https://geopandas.org/reference.html#geopandas.GeoSeries.intersects
  3. 如果點與 Microsoft US Building Footprint 數據中的任何多邊形相交,則 label 為 1,否則為 0。

現在我在步驟(1),即有效地找到圖像中每個像素的緯度/經度坐標。

不幸的是,我找不到比遍歷所有像素更好的解決方案。 到目前為止,這是我的解決方案:

import glob
import os
import pickle
import sys

import gdal
import geopandas as gpd
import matplotlib
import matplotlib.pyplot as plt
from numba import jit
import numpy as np
from osgeo import osr
import PIL
from PIL import Image, TiffImagePlugin
from shapely.geometry import Point, Polygon, box
import torch


def pixel2coord(img_path, x, y):
    """
    Returns latitude/longitude coordinates from pixel x, y coords

    Keyword Args:
      img_path: Text, path to tif image
      x: Pixel x coordinates. For example, if numpy array, this is the column index
      y: Pixel y coordinates. For example, if numpy array, this is the row index
    """
    # Open tif file
    ds = gdal.Open(img_path)

    old_cs = osr.SpatialReference()
    old_cs.ImportFromWkt(ds.GetProjectionRef())

    # create the new coordinate system
    # In this case, we'll use WGS 84
    # This is necessary becuase Planet Imagery is default in UTM (Zone 15). So we want to convert to latitude/longitude
    wgs84_wkt = """
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.01745329251994328,
            AUTHORITY["EPSG","9122"]],
        AUTHORITY["EPSG","4326"]]"""
    new_cs = osr.SpatialReference()
    new_cs.ImportFromWkt(wgs84_wkt)

    # create a transform object to convert between coordinate systems
    transform = osr.CoordinateTransformation(old_cs,new_cs) 
    
    gt = ds.GetGeoTransform()

    # GDAL affine transform parameters, According to gdal documentation xoff/yoff are image left corner, a/e are pixel wight/height and b/d is rotation and is zero if image is north up. 
    xoff, a, b, yoff, d, e = gt

    xp = a * x + b * y + xoff
    yp = d * x + e * y + yoff

    lat_lon = transform.TransformPoint(xp, yp) 

    xp = lat_lon[0]
    yp = lat_lon[1]
    
    return (xp, yp)


def find_img_coordinates(img_array, image_filename):
    img_coordinates = np.zeros((img_array.shape[0], img_array.shape[1], 2)).tolist()
    for row in range(0, img_array.shape[0]):
        for col in range(0, img_array.shape[1]): 
            img_coordinates[row][col] = Point(pixel2coord(img_path=image_filename, x=col, y=row))
    return img_coordinates


def find_image_pixel_lat_lon_coord(image_filenames, output_filename):
    """
    Find latitude, longitude coordinates for each pixel in the image

    Keyword Args:
      image_filenames: A list of paths to tif images
      output_filename: A string specifying the output filename of a pickle file to store results

    Returns image_coordinates_dict whose keys are filenames and values are an array of the same shape as the image with each element being the latitude/longitude coordinates.
    """
    image_coordinates_dict = {}
    for image_filename in image_filenames:
        print('Processing {}'.format(image_filename))
        img = Image.open(image_filename)
        img_array = np.array(img)
        img_coordinates = find_img_coordinates(img_array=img_array, image_filename=image_filename)
        image_coordinates_dict[image_filename] = img_coordinates
        with open(os.path.join(DATA_DIR, 'interim', output_filename + '.pkl'), 'wb') as f:
            pickle.dump(image_coordinates_dict, f)
    return image_coordinates_dict

這些是我的輔助功能。 因為這需要很長時間,所以在find_image_pixel_lat_lon_coord中,我將結果保存到字典image_coordinates_dict中,我將其寫入 pickle 文件以保存結果。

然后我會使用它的方式是:

# Create a list with all tif imagery
image_filenames = glob.glob(os.path.join(image_path_dir, '*.tif'))

image_coordinates_dict = find_image_pixel_lat_lon_coord(image_filenames, output_filename='image_coordinates')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM