首页 > 其他分享 >(slam工具)2 从照片读取GNSS信息

(slam工具)2 从照片读取GNSS信息

时间:2024-06-17 22:22:51浏览次数:6  
标签:读取 EXIF tags drone GNSS slam dji GPS gps

   

代码仓库

https://github.com/Dongvdong/v1_1_slam_tool

 

主要有两个库

1正常的库 获取经纬度 但是无法获取云台和飞机姿态

2 2进制模式读取可以获取更多信息,但是读取的高度有精度损失。

# -*- coding: utf-8 -*-
# conda activate py37gaosi  # 服务器
# activate py38  # 笔记本

import os
import numpy as np

#改进检测地区
import os
import exifread
import re
import sys
import requests
import json


# 遍历文件夹及子文件夹中的所有图片,逐个文件读取exif信息
'''
def get_pic_GPS(pic_dir):
    items = os.listdir(pic_dir)
    for item in items:
        path = os.path.join(pic_dir, item)
        if os.path.isdir(path):
            get_pic_GPS(path)
        else:
            imageread(path)
'''


def convert_altitude_to_decimal(altitude):
    #print(altitude)
    try:
        # 可能会抛出异常的代码
        a, b = altitude.strip().split('/')
        #print(f"a:{a},b:{b}")
        return float(a)/float(b)
    except ValueError as e:
        #print(f"不存在‘/’")
        #print(altitude)
        # 这里可以继续执行其他代码
        return float(altitude)

        
# 将经纬度转换为小数形式
def convert_to_decimal(*gps):
    # 度
    if '/' in gps[0]:
        deg = gps[0].split('/')
        if deg[0] == '0' or deg[1] == '0':
            gps_d = 0
        else:
            gps_d = float(deg[0]) / float(deg[1])
    else:
        gps_d = float(gps[0])
    # 分
    if '/' in gps[1]:
        minu = gps[1].split('/')
        if minu[0] == '0' or minu[1] == '0':
            gps_m = 0
        else:
            gps_m = (float(minu[0]) / float(minu[1])) / 60
    else:
        gps_m = float(gps[1]) / 60
    # 秒
    if '/' in gps[2]:
        sec = gps[2].split('/')
        if sec[0] == '0' or sec[1] == '0':
            gps_s = 0
        else:
            gps_s = (float(sec[0]) / float(sec[1])) / 3600
    else:
        gps_s = float(gps[2]) / 3600

    decimal_gps = gps_d + gps_m + gps_s
    # 如果是南半球或是西半球
    if gps[3] == 'W' or gps[3] == 'S' or gps[3] == "83" or gps[3] == "87":
        return str(decimal_gps * -1)
    else:
        return str(decimal_gps)


'''
# 如果提取 图像信息不需要机身自讨 精度更高
Image ImageDescription
Image Make
Image Model
Image Orientation
Image XResolution
Image YResolution
Image ResolutionUnit
Image Software
Image DateTime
Image YCbCrPositioning
Image ExifOffset
GPS GPSVersionID
GPS GPSLatitudeRef
GPS GPSLatitude
GPS GPSLongitudeRef
GPS GPSLongitude
GPS GPSAltitudeRef
GPS GPSAltitude
Image GPSInfo
Image XPComment
Image XPKeywords
Thumbnail Compression
Thumbnail XResolution
Thumbnail YResolution
Thumbnail ResolutionUnit
Thumbnail JPEGInterchangeFormat
Thumbnail JPEGInterchangeFormatLength
EXIF ExposureTime
EXIF FNumber
EXIF ExposureProgram
EXIF ISOSpeedRatings
EXIF ExifVersion
EXIF DateTimeOriginal
EXIF DateTimeDigitized
EXIF ComponentsConfiguration
EXIF CompressedBitsPerPixel
EXIF ShutterSpeedValue
EXIF ApertureValue
EXIF ExposureBiasValue
EXIF MaxApertureValue
EXIF SubjectDistance
EXIF MeteringMode
EXIF LightSource
EXIF Flash
EXIF FocalLength
EXIF MakerNote
EXIF FlashPixVersion
EXIF ColorSpace
EXIF ExifImageWidth
EXIF ExifImageLength
Interoperability InteroperabilityIndex
Interoperability InteroperabilityVersion
EXIF InteroperabilityOffset
EXIF ExposureIndex
EXIF FileSource
EXIF SceneType
EXIF CustomRendered
EXIF ExposureMode
EXIF WhiteBalance
EXIF DigitalZoomRatio
EXIF FocalLengthIn35mmFilm
EXIF SceneCaptureType
EXIF GainControl
EXIF Contrast
EXIF Saturation
EXIF Sharpness
EXIF SubjectDistanceRange
EXIF BodySerialNumber


'''

# 读取图片的经纬度和拍摄时间
def Api_1_1Get_ImageGPS(path):

    f = open(path, 'rb')
    GPS = {}
    gps_=[-1,-1,-1]
    
    try:
        tags = exifread.process_file(f)
    except:
        return gps_
    #print(tags)
    
    #for tag in tags:               
       # print(str(tag),str(tags[str(tag)]))
    

    # 南北半球标识
    if 'GPS GPSLatitudeRef' in tags:

        GPS['GPSLatitudeRef'] = str(tags['GPS GPSLatitudeRef'])
        # print(GPS['GPSLatitudeRef'])
    else:
        GPS['GPSLatitudeRef'] = 'N'  # 缺省设置为北半球

    # 东西半球标识
    if 'GPS GPSLongitudeRef' in tags:
        GPS['GPSLongitudeRef'] = str(tags['GPS GPSLongitudeRef'])
        # print(GPS['GPSLongitudeRef'])
    else:
        GPS['GPSLongitudeRef'] = 'E'  # 缺省设置为东半球

    # 海拔高度标识
    if 'GPS GPSAltitudeRef' in tags:
        GPS['GPSAltitudeRef'] = str(tags['GPS GPSAltitudeRef'])

    # 获取纬度
    if 'GPS GPSLatitude' in tags:
        lat = str(tags['GPS GPSLatitude'])
        # 处理无效值
        if lat == '[0, 0, 0]' or lat == '[0/0, 0/0, 0/0]':
            GPS['GPSLatitude']=-1
            
        else:
            deg, minu, sec = [x.replace(' ', '') for x in lat[1:-1].split(',')]
            # 将纬度转换为小数形式
            GPS['GPSLatitude'] = convert_to_decimal(deg, minu, sec, GPS['GPSLatitudeRef'])

    # 获取经度
    if 'GPS GPSLongitude' in tags:
        lng = str(tags['GPS GPSLongitude'])
        # print(lng)

        # 处理无效值
        if lng == '[0, 0, 0]' or lng == '[0/0, 0/0, 0/0]':
            GPS['GPSLongitude']=-1
           
        else:
            deg, minu, sec = [x.replace(' ', '') for x in lng[1:-1].split(',')]
            # 将经度转换为小数形式
            GPS['GPSLongitude'] = convert_to_decimal(deg, minu, sec, GPS['GPSLongitudeRef'])  # 对特殊的经纬度格式进行处理

    # 获取海拔高度
    if 'GPS GPSAltitude' in tags:

        height = str(tags["GPS GPSAltitude"])
        GPS['GPSAltitude'] = convert_altitude_to_decimal(height)

    # if 'GPS RelativeAltitude' in tags:

    #     height = str(tags["GPS RelativeAltitude"])
    #     GPS['RelativeAltitude'] = convert_altitude_to_decimal(height)

        
    # 获取图片拍摄时间
    # if 'Image DateTime' in tags:
    #     GPS["DateTime"] = str(tags["Image DateTime"])
    #     print(GPS["DateTime"])
    # elif "EXIF DateTimeOriginal" in tags:
    #     GPS["DateTime"] = str(tags["EXIF DateTimeOriginal"])
    #     print(GPS["DateTime"])
    # if 'Image Make' in tags:
    #     print('照相机制造商:', tags['Image Make'])
    # if 'Image Model' in tags:
    #     print('照相机型号:', tags['Image Model'])
    # if 'Image ExifImageWidth' in tags:
    #     print('照片尺寸:', tags['EXIF ExifImageWidth'],tags['EXIF ExifImageLength'])



    gps_=[float(GPS['GPSLatitude']) ,float(GPS['GPSLongitude']), float(GPS['GPSAltitude'])]
    #print(gps_)
    return gps_

'''
# 如果需要提取相机字条和机身姿态
读取信息查看

   tiff:Make="DJI"
   tiff:Model="FC6310R"  
   dc:format="image/jpg"
   drone-dji:AbsoluteAltitude="+514.64"
   drone-dji:RelativeAltitude="+100.09"
   drone-dji:GpsLatitude="34.03250565"
   drone-dji:GpsLongtitude="108.76779926"
   drone-dji:GimbalRollDegree="+0.00"  拍照时刻云台的Roll 欧拉角
   drone-dji:GimbalYawDegree="+93.50"
   drone-dji:GimbalPitchDegree="-89.90"
   drone-dji:FlightRollDegree="+2.10"  拍照时刻飞行器机体的Roll 欧拉角
   drone-dji:FlightYawDegree="+93.50"
   drone-dji:FlightPitchDegree="+1.00"
   drone-dji:FlightXSpeed="+0.00"
   drone-dji:FlightYSpeed="+0.00"
   drone-dji:FlightZSpeed="+0.00"
   drone-dji:CamReverse="0"
   drone-dji:GimbalReverse="0"
   drone-dji:SelfData="Undefined"
   drone-dji:CalibratedFocalLength="3666.666504"   焦距
   drone-dji:CalibratedOpticalCenterX="2736.000000"
   drone-dji:CalibratedOpticalCenterY="1824.000000"
   drone-dji:RtkFlag="50"
   drone-dji:RtkStdLon="0.01117"
   drone-dji:RtkStdLat="0.01132"
   drone-dji:RtkStdHgt="0.02493"
   drone-dji:DewarpFlag="1"
   drone-dji:PhotoDiff=""
   crs:Version="7.0"
   crs:HasSettings="False"
   crs:HasCrop="False"
   crs:AlreadyApplied="False">
  </rdf:Description>

'''
 

 #  读取单个照片的 gps信息 这个方法有问题  读取高度精度损失
def Api_1_2Get_Image_AllInfo(file_path):
    b = b"\x3c\x2f\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e"
    a = b"\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20"

    aa=["\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20"]
    bb=["\x3c\x2f\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e"]

    #xml format to save EXIF的数据规范
    # aa ['<rdf:Description ']
    #print("aa",aa)
    # bb ['</rdf:Description>']
    #print("bb",bb)



    # rb是读取二进制文件
    img = open(file_path, 'rb')
    # bytearray() 方法返回一个新字节数组
    data = bytearray()
    #标识符,
    flag = False

    for i in img.readlines():
       
        # 按行读取二进制信息,标签成对出现
        if a in i:
            flag = True
        if flag:
            #把第i行数据复制到新数组中
            data += i
        if b in i:
            break
    #print("======大疆精灵4照片中原始数据 =======\n",data)

    if len(data) > 0:
        data = str(data.decode('ascii'))#ascii 
        #print(data)
        #filter()函数用于过滤序列,过滤掉不符合条件的元素,返回符合条件的元素组成新列表。
        #filter(function,iterable) ,function -- 判断函数。iterable -- 可迭代对象
        #python允许用lambda关键字创造匿名函数。
        # 在 lambda 关键字之后、冒号左边为参数列表,可不带参数,也可有多个参数。若有多个参数,则参数间用逗号隔开,冒号右边为 lambda 表达式的返回值。
        #left--->right
        # judge condition 'drone-dji:' in x
        lines = list(filter(lambda x: 'drone-dji:' in x, data.split("\n")))
        #print("lines",lines)
        dj_data_dict = {}
       
        for d in lines:
            # remove 'drone-dji:'
            d = d.strip()[10:]
            # k is name
            # v is value
            k, v = d.split("=")
            v=v.replace('\"','')
            
            #print(k, v)
            dj_data_dict[k] = v
        return dj_data_dict
    else:
        dj_data_dict="error"


def Api_2Get_Image_GPS(img_path):


    #img_name=img_path[img_path.rfind('/')+1:img_path.rfind('.')]# 去掉后缀
    #print(img_name)
    dj_data_dict=Api_1_1Get_ImageGPS(img_path)

    GPS_lat_lon_h=[-1,-1,-1]
    if dj_data_dict !="error":
        

        #dj_data_dict['GpsLatitude'] # 这种方法会损失高度
        #dj_data_dict['GpsLongtitude']
        #dj_data_dict['RelativeAltitude']
      
        lat=float(dj_data_dict[0])
        lon=float(dj_data_dict[1])  
        absh=float(dj_data_dict[2])  

        GPS_lat_lon_h=[lat,lon,absh]
    
    #print(GPS)
    return GPS_lat_lon_h





# 遍历文件夹读取照片的GPS 高度保留厘米
def API_read_directory(img_path_dir):

           
   
    Gnss_list=[]
   
    for filename in os.listdir(img_path_dir):
        file_dir_name=img_path_dir+filename
        #print(filename)
        GPS_lat_lon_h=Api_2Get_Image_GPS(file_dir_name)
        gnss_temp=[]
        
        gnss_temp.append(filename)
        gnss_temp.append(GPS_lat_lon_h[0])
        gnss_temp.append(GPS_lat_lon_h[1])
        gnss_temp.append(GPS_lat_lon_h[2])
       

        #print("1 照片读取到的GNSS",gnss_temp)
        Gnss_list.append(gnss_temp)
    return Gnss_list


def API_Save2txt(GPS_txt_name,Gnss_list):

    with open(GPS_txt_name, 'w') as file:
        for row in Gnss_list:
            line = ' '.join(map(str, row))
            file.write(f"{line}\n")

    print(GPS_txt_name,"保存成功")


def API_read2txt(GPS_txt_name):
    
    print(GPS_txt_name,"读取txt数据成功")
    Gnss_list = []
    with open(GPS_txt_name, 'r') as file:
        for line in file:
            row = list(map(str, line.split()))
            Gnss_list.append(row)
            #print(row)
    return Gnss_list


#====================测试========================
'''
if __name__ == "__main__":
   

    # 参数
    # 0-1 gps照片路径
    img_path_dir="E:/v0_Project/V0_Mybao/v8_slam/python工具/0测试数据/d1_100mRTKColmap/images/gps_images/"
    # 0-2 txt保存的名字
    GPS_txt_name="GPS.txt"

    # 1读取数据
    Gnss_list=API_read_directory(img_path_dir)

    # 2保存txt 格式: name lat lon h
    API_Save2txt(GPS_txt_name,Gnss_list)

    # 3读取txt 格式: name lat lon h
    Gnss_list_Read = API_read2txt(GPS_txt_name)

'''

  

数据格式

DJI_0002.JPG 34.03250563926396 108.7677992500047 514.6380141189607
DJI_0005.JPG 34.03267641704175 108.76781155556024 514.4640141184373
DJI_0011.JPG 34.03394725037507 108.76789833333802 514.635014120011
DJI_0015.JPG 34.03487661148619 108.76796561111581 514.6420141205874
DJI_0018.JPG 34.03509530593064 108.76797844444913 514.6150141188659
DJI_0022.JPG 34.035064472597305 108.76773913889359 514.58201412093
DJI_0025.JPG 34.03463080593064 108.76770336111582 514.6600141209601
DJI_0028.JPG 34.03403180593064 108.76765755556025 514.5780141181838
DJI_0031.JPG 34.033382778152856 108.76761005556025 514.5470141202469
DJI_0035.JPG 34.032533167041734 108.7675511111158 514.6610141190716
DJI_0041.JPG 34.03248758370841 108.7671833611158 514.8310141174146
DJI_0042.JPG 34.03248605593062 108.76717719444913 514.781014119351

  

标签:读取,EXIF,tags,drone,GNSS,slam,dji,GPS,gps
From: https://www.cnblogs.com/gooutlook/p/18253338

相关文章

  • (slam工具)3 GNSS-ECEF-ENU 坐标系下转换
      https://github.com/Dongvdong/v1_1_slam_tool '''gnss和enu坐标系相互转化'''importnumpyasnpfrompyprojimportProj,TransformerimportpyprojimportmathfromAPI_1GetGpsFromIMGimport*use_cgcs2000Towgs84=0#......
  • Unity 读取xml
      ReadXml.cs内容:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem.Xml;publicclassReadXml:MonoBehaviour{privateXmlDocumentxmldoc;privateXmlNoderoot;privatestringurl;voidStart(......
  • 如何解决c++使用mysql数据库读取中文输出时乱码问题
    使用vs写c++输出数据库中文时出现乱码设置utf-8还是不行这是数据库的内容这是输出:在网上找有说改成utf-8的格式,加入这样一句:mysql_query(conn,"setnamesutf8");效果就是这样:发现错误依旧,询问群友后修改,需要在连接数据库的函数中加入如下一句:mysql_query(conn,"set......
  • 申瓯通信 在线录音管理系统 download 任意文件读取漏洞复现
    0x01产品简介申瓯通信在线录音管理系统是一款功能强大的录音管理解决方案,旨在满足公司、集团单位在区域分布下对录音数据的集中管理需求。该系统基于SOC1900、SOC1600等系列录音盒开发,是一个多线路、多设备、多区域的录音统一管理平台。该系统将各个分点的录音盒的录音统一集......
  • Python数据分析与建模库-03数据分析处理库Pandas-1.数据读取
    该视频主要讲述了pandas库在数据处理中的重要性。首先介绍了pandas库是基于numpy库封装了一些操作,简化了数据处理过程。然后通过读取CSV文件的例子,演示了如何使用pandas的read_csv函数将数据读入,并展示了数据类型和数据格式。接着介绍了pandas库中的DataFrame格式,它可以看作......
  • OpenCV 根据 URL 读取网络图片
    OpenCV 提供了一个 imread() 函数可以在本地磁盘读取图片并进行各种操作,这里介绍一种方法,可以让OpenCV根据URL也能读取网络图片(配合Nginx服务更好用)参考链接:【Python】根据URL读取网络图片的两种方式(OpenCV)_cv2读取网络图片-CSDN博客 调用 VideoCapture 进行转换im......
  • 学会python——读取大文本文件(python实例六)
    目录1、认识Python2、环境与工具2.1python环境2.2VisualStudioCode编译3、读取大文本文件3.1代码构思3.2代码示例3.3运行结果4、总结1、认识PythonPython是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。Python的设计具有很强的可读......
  • python学习 - 读取xls文件的操作案例代码
    #!/usr/bin/evnpython#-*-encoding:utf-8-*-importxlrdimportxlwtimportxlutils.copyclassExcels:defcreateExcel(self):workbook=xlwt.Workbook()sheet=workbook.add_sheet(u"sheet页名称",cell_overwrite_ok=True)......
  • 【上传云】第一步:本地读取文件夹下的文件内容到数据库中
    背景:本地有一些文件,需要上传到云端这里先介绍第一步:将本地文件夹下的所有文件路径跟文件名都读取到数据库中,为下一步的上传做铺垫所需:并不需要上传所有格式的文件,故在此步骤里做过滤操作FileFilterzipFilter=pathname->!pathname.getName().endsWith("zxx");传文......
  • (2)cessium python 选择TXT文件gnss估计可视化
      1注册账号https://ion.cesium.com/tokens?page=110511L42获取秘钥https://ion.cesium.com/tokens?page=1 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyZmVmYjIwZC01MWMwLTQ1ODMtOTgyYi01NWRlYjI5MDQzZTQiLCJpZCI6MzY5MTAsImlhdCI6MTcxODQ0MzQyM30.W67FXI......