照片的GPS位置信息读取

一、照片的 EXIF信息

手机、相机拍摄的照片会自带一些诸如拍摄时间、地点、镜头型号、曝光度、图像尺寸等附加信息,在Windows上可以通过右键文件属性查看和修改相关参数。

EXIF (exchangeable image file format) 就是此类信息的简称。

Python第三方包 exifread 为读取 照片 EXIF信息提供方便。

 

二、 照片的 GPS信息

照片EXIF信息中记录了照片拍摄时的GPS 经纬度信息,通过高德提供的开发者工具可以进一步解析出具体的地址信息,具体方法实现如下:

# !/usr/bin/python3
# coding: utf-8
import json
import os
import traceback

import exifread
import requests


def parse_gps_express(gps_express):
    '''
    GPS坐标表达式转数值
    :param gps_express: GPS坐标表达式 [1,2,3/4]
    :return: GPS坐标数值 1.033542
    '''
    try:
        express = str(gps_express).replace(" ", "").replace("[", "").replace("]", "")
        parts = express.split(",")
        subpart = parts[2].split("/")

        degrees = float(parts[0])
        minutes = float(parts[1])
        seconds = float(subpart[0]) / float(subpart[1])
        return degrees + minutes / 60 + seconds / 3600
    except:
        raise Exception("Error information for the picture")


def photo_gps(photo_path):
    '''
    照片拍摄地GPS坐标
    :param photo_path: 照片的磁盘路径
    :return: 照片的 (GPS经度,GPS纬度)
    '''
    if not os.path.isfile(photo_path):
        raise Exception("File is not exist")

    with open(photo_path, 'rb') as f:
        exif_dict = exifread.process_file(f)
        longitude_ref = str(exif_dict["GPS GPSLongitudeRef"]).strip()
        longitude = parse_gps_express(str(exif_dict["GPS GPSLongitude"]))
        latitude_ref = str(exif_dict["GPS GPSLatitudeRef"]).strip()
        latitude = parse_gps_express(str(exif_dict["GPS GPSLatitude"]))

    lng = longitude if "E" == longitude_ref else 0 - longitude
    lat = latitude if "N" == latitude_ref else 0 - latitude
    return lng, lat


def convert_gps(gps_coordinates):
    '''
    坐标转换:GPS转高德
    :param gps_coordinates: 多个位置(GPS经度,GPS纬度)的集合
    :return: 多个位置(高德经度,高德纬度)的集合
    '''
    try:
        coordinates = "|".join(gps_coordinates) # 最多批量查询40个
        token = "cb1c527f67df87bdc3a72f8a75987e62" # 自行申请,免费

        url = "https://restapi.amap.com/v3/assistant/coordinate/convert" \
              "?locations={0}&key={1}&coordsys=gps&output=json".format(coordinates, token)

        response = requests.get(url) # 个人开发者访问限流:100000次/日
        result = json.loads(response.text)
        if "1" == result["status"]:
            return result["locations"].split(";")
        else:
            raise Exception(result["info"])
    except Exception as e:
        raise e


def map_address(gd_coordinates):
    '''
    逆地理编码(高德坐标转地址)
    :param gd_coordinates:多个位置(高德经度,高德纬度)的集合
    :return:多个位置地址信息的集合
    '''
    try:
        coordinates = "|".join(gd_coordinates) # 最多批量查询20个
        token = "cb1c527f67df87bdc3a72f8a75987e62" # 自行申请,免费
        batch = "true" if len(gd_coordinates) > 1 else "false"

        url = "https://restapi.amap.com/v3/geocode/regeo" \
              "?location={0}&key={1}&batch={2}&radius=500&extensions=base&output=json".format(coordinates, token, batch)

        response = requests.get(url) # 个人开发者访问限流:6000次/日
        result = json.loads(response.text)
        if "1" == result["status"]:
            address = []
            if "true" == batch:
                add_lst = list(result["regeocodes"])
                for add in add_lst:
                    address.append(add["formatted_address"])
            else:
                fmt_add = result["regeocode"]["formatted_address"]
                address.append(fmt_add)
            return address
        else:
            raise Exception(result["info"])
    except Exception as e:
        raise e


if __name__ == '__main__':
    try:
        lng1, lat1 = photo_gps("d:/1.jpg")
        lng2, lat2 = photo_gps("d:/2.jpg")
        lng3, lat3 = photo_gps("d:/3.jpg")

        gps_coordinates = list()
        gps_coordinates.append("%s,%s" % (lng1, lat1))
        gps_coordinates.append("%s,%s" % (lng2, lat2))
        gps_coordinates.append("%s,%s" % (lng3, lat3))

        gd_coordinates = convert_gps(gps_coordinates)
        addresses = map_address(gd_coordinates)
        for add in addresses:
            print(add)
    except:
        traceback.print_exc()

 

代码中明示的token为我个人所有,仅供交流学习,不可用于任何商业活动。

实现细节的建议:高德限制用户日访问次数,为避免不必要麻烦,建议多用批量查询。

 

 

参考资料

1、《高德关于访问token的生成的说明》

2、《高德关于访问流量限制的说明》

3、《GPS坐标转换高德坐标方法说明》

4、《高德关于地理/逆地理转换说明》

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值