gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 04:01:28 26 4
gpt4 key购买 nike

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

我已经能够根据这篇 StackOverflow 帖子将图像的角点转换为纬度/经度对:Obtain Latitude and Longitude from a GeoTIFF File。这篇文章很有帮助,因为我的原始坐标位于 UTM Zone 15。

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

我看到的最相关的帖子是 https://scriptndebug.wordpress.com/2014/11/24/latitudelongitude-of-each-pixel-using-python-and-gdal/ 。然而,该帖子建议在每个像素上创建一个 for 循环并转换为纬度、经度。有没有更有效的方法?

只是为了提供更多关于我的实际用例的上下文,我的最终目标是我有一堆卫星图像(例如,在这种情况下,每张图像都是 171 x 171)。我正在尝试创建一个建筑分割模型。现在,我正在尝试通过在每个图像上创建一个掩码来生成标记数据点,如果它对应于建筑物,则将像素标记为 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. 如果 Point 与 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')

关于python - 查找 GeoTiff 图像中每个像素的纬度/经度坐标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63004971/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com