【Python】批量提取图片经纬度并写入csv文件

news2024/9/24 19:20:06

需求

无人机图片中往往包含经纬度信息,需要一个脚本批量将文件夹中包含经纬度信息的图片提取出来,保存成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)

设定图片文件夹路径,运行之后,可以得到输出结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/56862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】二叉树的基本操作与遍历(C语言)

目录 定义 满二叉树 完全二叉树 性质 应用 计算二叉树结点个数 计算叶子结点的个数 第 k 层结点的个数 查找值为x的节点 遍历 前序遍历 中序遍历 后序遍历 层序遍历 判断是否为完全二叉树 定义 🦄二叉树是由树发展过来的,即度最大为2的树&…

stm32 笔记 PWM及HAL库应用

stm32 PWM原理 STM32 使用一个定时器作为 PWM 输出,在上图中,ARR 即为重装载值。在计数器的值大于CRRx的值并且小于 ARR 之间,即区分高低电平。输出在图中分别有 ① 和 ② 两种情况. 分别为: ①CRR 和 ARR 区间为低电平。 ②CR…

【pen200-lab】10.11.1.222

pen200-lab 学习笔记 【pen200-lab】10.11.1.222 🔥系列专栏:pen200-lab 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月27日🌴 🍭作…

Vue框架学习(第十三课)Vuex状态管理中的store和state属性

学习官网文档:开始 | Vuex (vuejs.org) 第一部分:查图观色思考为什么?下面的一张图中的数据如何实现组件与组件之间的数据共享呢? 如何去实现下面的方案呢能让数据得到共享 这一张图告诉你们答案 这样如何实现组件与组件之间的通信呀 Vuex五个核心的基本…

FANUC机器人程序设计

一.注意事项 1.FANUC机器人所有者、操作者必须对自己的安全负责。FANUC不对机器使用的安全问题负责。FANUC提醒用户在使用FANUC机器人时必须使用安全设备,必须遵守安全条款。 2.FANUC机器人程序的设计者、机器人系统的设计和调试者、安装者必须熟悉FAN…

408 考研《操作系统》第一章第一节:操作系统的概念和特征

文章目录教程:1. 操作系统的概念、功能和目标1.1 大家熟悉的操作系统1.2 操作系统的概念1.3 操作系统的功能和目标1.3.1 操作系统的功能和目标——作为系统资源的管理者1.3.2 操作系统的功能和目标——作为用户和计算机硬件之间的接口1.3.3 操作系统的功能和目标——…

【三维目标检测】CenterPoint(二)

CenterPoint数据和源码配置调试过程请参考上一篇博文:https://blog.csdn.net/suiyingy/article/details/128002709。本文主要详细介绍CenterPoint网络结构及其运行中间状态。 1 CenterPoint模型总体过程 CenterPoint模型的整体结构如下图所示,由最初的一…

50 jhat 中 java.lang.String 的实例占用空间为什么是 28 bytes ?

前言 此问题是 多个 classloader 加载的同类限定名的Class 在 jhat 中显示不全d 同一时期发现的问题 大致的情况是 看到了 jhat 中统计的各个 oop 的占用空间 似乎是不太能够对的上 比如 java.lang.String, 在 64bit vm 上面 开启了 UseCompressedOops 之后, 应该是占用 …

Gram矩阵+Gram矩阵和协方差矩阵的关系

目录Gram矩阵简介协方差矩阵Gram矩阵 和 协方差矩阵的关系Gram Matrix代码Gram矩阵简介 gram矩阵是计算每个通道 i 的feature map与每个通道 j 的feature map 的内积 gram matrix的每个值可以说是代表 i 通道的feature map和 j 通道的 feature map的互相关程度。 参考博客 GAT…

小程序开发---02认识宿主环境

小程序依赖于微信提供宿主环境 小程序可以借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能,如:微信扫码,微信支付,微信登录,定理定位,etc…等 小程序宿主环境包含以下内容&#xf…

关闭不同型号的 ESP 芯片的 ROM Code 上电启动日志的流程

【说明】 芯片 ROM Code 上电启动日志,不会对应用固件产生任何影响。通过 ROM Code 上电日志能够判断芯片启动模式是处于什么状态。若关闭此日志打印,当芯片进入下载模式或进入 Flash 启动模式等都不会有任何日志提示,不利于检查芯片状态&am…

操作系统学习笔记(V):设备管理

目录 1 设备 1.1 设备的概念 1.2 设备的分类 2 I/O控制器 2.1 I/O控制器 1.定义 2.功能 3.组成 2.2 I/O控制方式 1.程序直接控制方式 2.中断驱动方式 3.DMA方式 4.通道控制方式 5.对比 2.3 I/O软件层次结构 1.用户层软件 2.设备独立性软件 3.设备驱动程序 4…

Windows ssh免密访问Linux服务器

文章目录1.在Windows上生成公钥和私钥2.将公钥中的内容复制到linux服务器3.确认linux服务器开启了允许SSH免密登录4.确认免密登录配置成功ssh提供了安全的身份认证的策略,在免密登录之前,首先需要一对公钥和私钥。客户端拿着私钥,服务端拿着公…

【计算机网络】超详细——华为eNSP的安装教程

网络工程师小白或初次接触计算机网络的学生,网络相关的书本学习起来枯燥乏味,这时需要仿真模拟器来加深对网络知识的理解。目前提供网络仿真平台有cisco、华为等,若您英语基础薄弱建议选华为,英语阅读能力较强的直接上cisco的模拟…

redis我记不住的那些命令(五)

背景:我记不住那么多命令,又是Linux命令,又是Git命令,又是kubernetes的命令,又是maven命令,又是redis命令。所谓好记性不如烂笔头,记下来吧。 一、set集合 集合的特点是 无序且各不相同的元素…

SpringSecurity(二十二)--OAuth2:实现资源服务器(下)通过redis和缓存实现TokenStore

一、前言 本章将在前面几章基础上进行讲解,所以大家最好尽量先去看一下前几章的内容再来跟进会好很多。那么本章我们将通过redis和本地缓存Caffeine对JdbcTokenStore进行重写,并且讲解资源服务器配置的新方案,使得我们可以不用在资源服务器又…

[附源码]计算机毕业设计springboot校园疫情防范管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

LeetCode 337. 打家劫舍 III(C++)*

该题也是使用动态规划的思路,主要考虑根节点的最大金额和左右子节点的关系,其中分为两种情况:有该结点有没有偷钱,其次要遵守不报警原则。可得到状态转移方程: f为根节点被选中的最大,g为根节点没被选中的最…

Day17-购物车页面-结算-动态计算已勾选商品的数据和选中状态

1.动态渲染已勾选商品的总数量 我的操作: 1》在 store/cart.js 模块中,定义一个名称为 checkedCount 的 getters,用来统计已勾选商品的总数量: 2》在 my-settle 组件中,通过 mapGetters 辅助函数,将需要的…

[附源码]Python计算机毕业设计Django健身房信息管理

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…