需求
无人机图片中往往包含经纬度信息,需要一个脚本批量将文件夹中包含经纬度信息的图片提取出来,保存成csv文件。
经纬度格式解读
默认情况下,图片采用的WGS84经纬度,默认格式采用的是度分秒格式,另一种格式是十进制格式。
度分秒格式和十进制格式之间的转换规则如下,图源:https://www.jb51.net/article/238397.htm
- 十进制换度分秒
- 度分秒换十进制
程序代码
获取单张图片经纬度
这里采用exifread库来提取图片的经纬度,同时,对于不包含经纬度的图片,无法直接进行提取,因此先用try–except的方式来进行试探:
def get_single_gps(img):
with open(img, 'rb') as f:
# 直接读取度分秒格式的经纬度数据
contents = exifread.process_file(f)
try:
longitude = contents["GPS GPSLongitude"].values
has_longitude = True
except:
has_longitude = False
if not has_longitude:
return '', ''
else:
longitude = contents["GPS GPSLongitude"].values
latitude = contents["GPS GPSLatitude"].values
# 度分秒转换成十进制数据
longitude_f = longitude[0].num / longitude[0].den + (longitude[1].num / longitude[1].den / 60) + (
longitude[2].num / longitude[2].den / 3600)
latitude_f = latitude[0].num / latitude[0].den + (latitude[1].num / latitude[1].den / 60) + (
latitude[2].num / latitude[2].den / 3600)
return longitude_f, latitude_f
批量获取图片经纬度
实现单张之后,批量实现加个循环即可:
def get_gps(img_path):
img_name = []
logitude_list = []
latitude_list = []
for single_img in os.listdir(img_path):
img_name.append(single_img)
longitude, latitude = get_single_gps(img_path + '/' + single_img)
logitude_list.append(longitude)
latitude_list.append(latitude)
return img_name, logitude_list, latitude_list
数据写入csv文件
首先需要创建一个csv文件,设定文件的表头:
def create_csv(root):
header = ['img_path', 'Longitude', 'Latitude']
with open(root + '/gps.csv', 'w', encoding='utf-8-sig', newline="") as f:
writer = csv.writer(f)
writer.writerow(header)
然后写入数据:
def write_csv(root, result_list):
for i in result_list:
with open(root + '/gps.csv', 'a', encoding='utf-8-sig', newline="") as f:
writer = csv.writer(f)
writer.writerow(i)
注意这里采用utf-8-sig
编码,这是为了防止中文信息输入显示为乱码。
完整示例代码
import os
import exifread
import csv
def get_single_gps(img):
with open(img, 'rb') as f:
# 直接读取度分秒格式的经纬度数据
contents = exifread.process_file(f)
try:
longitude = contents["GPS GPSLongitude"].values
has_longitude = True
except:
has_longitude = False
if not has_longitude:
return '', ''
else:
longitude = contents["GPS GPSLongitude"].values
latitude = contents["GPS GPSLatitude"].values
# 度分秒转换成十进制数据
longitude_f = longitude[0].num / longitude[0].den + (longitude[1].num / longitude[1].den / 60) + (
longitude[2].num / longitude[2].den / 3600)
latitude_f = latitude[0].num / latitude[0].den + (latitude[1].num / latitude[1].den / 60) + (
latitude[2].num / latitude[2].den / 3600)
return longitude_f, latitude_f
def get_gps(img_path):
img_name = []
logitude_list = []
latitude_list = []
for single_img in os.listdir(img_path):
img_name.append(single_img)
longitude, latitude = get_single_gps(img_path + '/' + single_img)
logitude_list.append(longitude)
latitude_list.append(latitude)
return img_name, logitude_list, latitude_list
def create_csv(root):
header = ['img_path', 'Longitude', 'Latitude']
with open(root + '/gps.csv', 'w', encoding='utf-8-sig', newline="") as f:
writer = csv.writer(f)
writer.writerow(header)
def write_csv(root, result_list):
for i in result_list:
with open(root + '/gps.csv', 'a', encoding='utf-8-sig', newline="") as f:
writer = csv.writer(f)
writer.writerow(i)
def main(img):
root = os.getcwd()
create_csv(root)
img_name, logitude_list, latitude_list = get_gps(img)
index = range(len(img_name))
row_list = [[img_name[i], logitude_list[i], logitude_list[i]] for i in index]
write_csv(root, row_list)
if __name__ == '__main__':
img = 'E:/Xdu_data/ceshi'
main(img)
设定图片文件夹路径,运行之后,可以得到输出结果: