Python 查找GeoTiff图像中每个像素的纬度/经度坐标

Python 查找GeoTiff图像中每个像素的纬度/经度坐标,python,geolocation,tiff,gdal,geotiff,Python,Geolocation,Tiff,Gdal,Geotiff,我目前有一个来自GeoTiff文件的171 x 171图像(尽管在其他情况下,我可能有更大的图像)。我的目标是获取图像中的每个像素并转换为纬度/经度对 我已经能够基于此StackOverflow post将图像的角点转换为纬度/经度对:。这篇文章很有帮助,因为我的原始坐标在UTM 15区 但是,我现在想将图像的所有像素转换为纬度、经度对,并将结果存储在相同维度的numpy数组中。因此,输出将是一个numpy数组,它是171 x 171 x 2,numpy数组的每个元素都是(经度、纬度)对的元组

我目前有一个来自GeoTiff文件的171 x 171图像(尽管在其他情况下,我可能有更大的图像)。我的目标是获取图像中的每个像素并转换为纬度/经度对

我已经能够基于此StackOverflow post将图像的角点转换为纬度/经度对:。这篇文章很有帮助,因为我的原始坐标在UTM 15区

但是,我现在想将图像的所有像素转换为纬度、经度对,并将结果存储在相同维度的numpy数组中。因此,输出将是一个numpy数组,它是171 x 171 x 2,numpy数组的每个元素都是(经度、纬度)对的元组

我在这方面看到的最相关的帖子是。然而,这篇文章建议在每个像素上创建一个for循环,并将其转换为纬度和经度。有没有更有效的方法

为了给我的实际用例提供更多的上下文,我的最终目标是我有一组卫星图像(例如,在本例中,每个图像是171 x 171)。我正在尝试创建一个建筑分割模型。现在,我正在尝试通过在每个图像上创建一个遮罩来生成标记的数据点,该遮罩将像素标记为A1(如果它对应于建筑),否则为0。首先,我使用的是MicrosoftUS Building Footprint数据:他们发布了检测到的建筑物多边形(由纬度、经度定义)的GeoJSON文件。我想这样做的方式是:

  • 找到我的图像中每个像素的纬度和经度。因此,我将得到171 x 171分。把这个放到一个GeoSeries中
  • 将点(在GeoSeries中)与Microsoft US Building Footprints数据相交(使用GeoPandas intersects:)
  • 如果该点与Microsoft US Building Footprint数据中的任何多边形相交,则标记为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')