暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

使用 Python 批量获取遥感影像的质心点坐标并对应影像

狗头Rser 2021-09-25
1140


前    言

 自己也没想到一篇 GIS 前沿的转载给这个很小的公众号带来了很大的流量,不过这个公众号是个个人公众号,也就是记载自己所学,所踩到的坑,遇到代码忘掉了或者不会配环境了的话可以回来找,没什么其他的心思自己写着玩罢了...既作个代码仓库,又做个个人心情的输出地,

获取质心点坐标其实很简单,就是

(x + RasterXSize * x_pixel_resolution/2 , y +RasterYSize * y_pixel_resolution/2)

复制

读出一张图片的,然后再用个 os.listdir(image_dir)
 做个批量就好了。

from osgeo import gdal
import os
import csv

#initialize
image_dir = './my_dir/'
image_files = os.listdir(image_dir)
image_files.sort(key=lambda x:int(x[:-4]))

with open('test.csv','w',encoding='utf-8',newline='') as f:
writer = csv.writer(f)
writer.writerow(["file_name","x_mid","y_mid"])
#读取影像
for file in image_files:

image_file = os.path.join(image_dir,file)

in_ds = gdal.Open(image_file)
in_ds_trans = in_ds.GetGeoTransform()

#宽度和分辨率
width = in_ds.RasterXSize
height = in_ds.RasterYSize
width_pixel = in_ds_trans[1]
height_pixel = in_ds_trans[5]

#计算中心点的坐标
x_left_top = in_ds_trans[0]
y_left_top = in_ds_trans[3]

x_mid = x_left_top + width/2 * width_pixel
y_mid = y_left_top + height/2 * height_pixel

row_info = [file,x_mid,y_mid]
writer.writerow(row_info)
del in_ds

复制

  上面的代码都是老生常谈了,就是先试验出一张图片的,然后再做个批量,不会的话用下调试的功能看看变量怎么变就好了。写出了一个 csv 文件。 

这是自己的研究数据当然不会轻易暴露位置...嘿嘿嘿~,然后就得到了质心点的 x,y 坐标。

  由于我在 ArcGIS 做了些小操作,也有一张表,里面有某个属性以及质心点的 x,y 坐标,但是我不知道图片名是那一张,所以我就需要返回索引,但是如果直接用 list.index(),可能会出现多个索引值而只能返回一个的情况,此外,这是个二维度匹配,需要两个同时满足才能够找到相应的图片名。 

我的需求其实就是匹配二维度的值,并且返回一个唯一值,网上搜了半天没找到好的解释,想起了前几天在看李沐老师的课写代码的时候看到 python 的 zip
函数,就会生成键对,于是就想了个办法用来暴力求解。

import pandas as pd
import numpy as np
import csv
f = open('find_file.csv','w',encoding='utf-8',newline='')
csv_writer = csv.writer(f)
data = pd.read_csv('./随便取名就好了.csv',header=None)
data1 = pd.read_csv('./取名开心就好了.csv',header = None)

#省略表头 读取 attribute
net_x = data.iloc[:,2][1:len(data)]
net_y = data.iloc[:,3][1:len(data)]
completeness = data.iloc[:,6][1:len(data)]

Name = data1.iloc[:,0][1:len(data1)]
x = data1.iloc[:,1][1:len(data1)]
y = data1.iloc[:,2][1:len(data1)]

#x_mid_data 表示的是要找的点
#转 list 并且转成 float 类型
net_x = list(net_x)
net_x_data = [float(data) for data in net_x]
net_y = list(net_y)
net_y_data = [float(data) for data in net_y]
completeness = list(completeness)
completeness_data = [float(data) for data in atttibute]

# 要找的图片
Name = list(Name)
x = list(x)
y = list(y)

x_data = [float(data) for data in x]
y_data = [float(data) for data in y]


# 代表的是 test.csv,图片计算出来的点
# x_data[i] 代表的是计算出来的质心点

for i in range(len(net_x)):
for index,xy in enumerate(zip(x_data,y_data)):
if abs(xy[0] -net_x_data[i])<1 and abs(xy[1] - net_y_data[i])<1:
write_info = [xy[0],xy[1],Name[index],attribute[i]]
csv_writer.writerow(write_info)

&emsp;&emsp;思路其实很简单,就是用 ArcGIS 的生成的表里面的质心去搜索另外一张表,如果找到的话就返回它的 `index`,所以外层循环就是 ArcGIS 的表里面搜索出的质心(x,y),然后在另一个表内搜索相应的位置,返回坐标。


```python
a = [1,2,3]
b = [2,3,4]
c = zip(a,b)
print(list(c))
d = [1,2,3]
e = [2,3,4]

for i in range(3):
for index,xy in enumerate(zip(a,b)):
if a[i] == xy[0] and b[i] == xy[1]:
print(f'坐标对应的索引是{index}')
```

output:
[(1, 2), (2, 3), (3, 4)]
坐标对应的索引是0
坐标对应的索引是1
坐标对应的索引是2

复制
看上面的例子,先用 panda 读取一些文章,然后取出里面的值,zip 就是压缩,形成一个对,然后输入一对值去匹配,返回索引值所以我的代码也就是输入 ArcGIS 表里的坐标,然后去图片计算出来的质心点的表去搜索索引,找到图片名称,并且读入 Attribute,形成一个 list ,然后写出这一行,最后就形成了一个 csv,对应有图片名,质心坐标,以及相应的 Attribute。(plus: zip 如果想要看值,需要转 list 去看)。
当然,在索引的时候不一定需要完全相等,也可以设定一个阈值,像我的影像 512 * 0.3m ,每张图片都会有 150 米左右的坐标偏移,所以可以设大一点的阈值。而且,QGIS 也是用 Python 的引擎,下影像的时候保留的位数平常是看不到的,就会有精度的差异,一般来说用 gdal 才能读出精确的坐标(我自己吃过QGIS 直接选影像范围重新下的亏,就是说你看到的和实际代码的精度会差很多)...


数据都是我随便填的,总得有点保密吧,我也没想到为啥 GIS 前沿的文章给我带来了那么大的流量,俺就是个在鄂州活的快意潇洒的一个技术死磕运动宅...


文章转载自狗头Rser,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论