简体   繁体   English

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

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

I currently have a 171 x 171 image from a GeoTiff file (although in other cases, I might have much bigger images).我目前有一个来自 GeoTiff 文件的 171 x 171 图像(尽管在其他情况下,我可能有更大的图像)。 My goal is to take each pixel in the image and convert to latitude/longitude pair.我的目标是获取图像中的每个像素并转换为纬度/经度对。

I am already able to convert the corners of the image to latitude/longitude pair based on this StackOverflow post: Obtain Latitude and Longitude from a GeoTIFF File .我已经能够根据这个 StackOverflow 帖子将图像的角转换为纬度/经度对: 从 GeoTIFF 文件中获取纬度和经度 This post was helpful since my original coordinates were in UTM Zone 15.这篇文章很有帮助,因为我的原始坐标位于 UTM 15 区。

However, I now want to convert all of the pixels of the image to latitude, longitude pair and store the results in a numpy array of the same dimension.但是,我现在想将图像的所有像素转换为纬度、经度对,并将结果存储在相同维度的 numpy 数组中。 So the output would be a numpy array that is 171 x 171 x 2 with each element of the numpy array being a tuple of the (longitude, latitude) pair.因此,output 将是一个 numpy 数组,其大小为 171 x 171 x 2,其中 numpy 数组的每个元素是一对(经度、经度)。

The most relevant post I've seen on this is https://scriptndebug.wordpress.com/2014/11/24/latitudelongitude-of-each-pixel-using-python-and-gdal/ .我看到的最相关的帖子是https://scriptndebug.wordpress.com/2014/11/24/latitudelongitude-of-each-pixel-using-python-and-gdal/ However, that post suggests to essentially create a for loop over each pixel and convert to latitude, longitude.但是,该帖子建议实质上在每个像素上创建一个 for 循环并转换为纬度、经度。 Is there a way that is more efficient?有没有更高效的方法?

Just to give more context on my actual use case, my end goal is I have a bunch of satellite imagery (for example in this case, each image is 171 x 171).只是为了给我的实际用例提供更多背景信息,我的最终目标是我有一堆卫星图像(例如,在这种情况下,每个图像都是 171 x 171)。 I am trying to create a building segmentation model.我正在尝试创建一个建筑分段 model。 Right now, I am trying to produce labeled data points by creating a mask on each image that labels a pixel a 1 if it corresponds to a building, else 0. To start, I'm using the Microsoft US Building Footprint data: https://github.com/microsoft/USBuildingFootprints where they've released GeoJSON files of polygons (defined by latitude, longitude) of buildings they've detected.现在,我正在尝试通过在每个图像上创建一个掩码来生成标记的数据点,如果它对应于建筑物,则将像素标记为 1,否则为 0。首先,我使用 Microsoft US Building Footprint 数据: https: //github.com/microsoft/USBuildingFootprints ,他们发布了他们检测到的建筑物的多边形(由纬度、经度定义)的 GeoJSON 文件。 The way I'm thinking about doing this is:我正在考虑这样做的方式是:

  1. Find the latitude, longitude of each pixel in my image.找到我图像中每个像素的纬度、经度。 Thus, I will have 171 x 171 Points.因此,我将有 171 x 171 点。 Put this in a GeoSeries把它放在一个 GeoSeries
  2. Intersect the Points (in a GeoSeries) with the Microsoft US Building Footprints data (using GeoPandas intersects: https://geopandas.org/reference.html#geopandas.GeoSeries.intersects )将点(在 GeoSeries 中)与 Microsoft US Building Footprints 数据相交(使用 GeoPandas 相交: https://geopandas.org/reference.html#geopandas.GeoSeries.intersects
  3. If the Point intersects with any Polygons in the Microsoft US Building Footprint data, then label 1, else 0.如果点与 Microsoft US Building Footprint 数据中的任何多边形相交,则 label 为 1,否则为 0。

Right now I'm on step (1), that is, efficiently find the latitude/longitude coordinate of each pixel in the image.现在我在步骤(1),即有效地找到图像中每个像素的纬度/经度坐标。

Unfortunately, I couldn't find a better solution (yet) than looping over all the pixels.不幸的是,我找不到比遍历所有像素更好的解决方案。 Here's my solution so far:到目前为止,这是我的解决方案:

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

Those were my helper functions.这些是我的辅助功能。 Because this would take a long time, in find_image_pixel_lat_lon_coord I saved the results into a dictionary image_coordinates_dict which I wrote to a pickle file to save results.因为这需要很长时间,所以在find_image_pixel_lat_lon_coord中,我将结果保存到字典image_coordinates_dict中,我将其写入 pickle 文件以保存结果。

Then the way I would use this is:然后我会使用它的方式是:

# 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.

相关问题 了解 GeoTIFF 图像中特定像素值的地理坐标(经度和纬度) - Know the geographic coordinates (longitude and latitude) of a particular pixel value in a GeoTIFF image 根据Geotiff图像计算纬度和经度 - calculate latitude and longitude from a geotiff image 使用纬度经度坐标从卫星图像中获取最近的像素值 - Get nearest pixel value from satellite image using latitude longitude coordinates 将纬度和经度写入Geotiff文件 - Write Latitude and Longitude to Geotiff file 从纬度/经度坐标计算像素值(使用matplotlib底图) - Calculate pixel values from latitude/longitude coordinates (using matplotlib Basemap) 从 GeoTIFF 文件中获取纬度和经度 - Obtain Latitude and Longitude from a GeoTIFF File 查找图像中红色像素的坐标 - Find the coordinates of red pixel in an image 如何使用 python 获取 eumetsat 图像像素的纬度和经度? - How to get latitude and longitude for a pixel of a eumetsat image using python? 使用 python 和 gdal 从 lat/long 点 in.geotiff 查找像素坐标 - Find pixel coordinates from lat/long point in .geotiff using python and gdal 使用python和gdal从.geotiff中的像素点查找纬度/经度坐标 - Find lat/long coordinates from pixel point in .geotiff using python and gdal
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM