社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

女朋友背着我,用 Python 偷偷隐藏了她的行踪

Python编程时光 • 3 年前 • 466 次点击  


点击上方“AirPython”,选择“加为星标
第一时间关注Python技术干货!


后台回复关键字 “黑魔法”,即可获取明哥整理的《Python黑魔法指南

1

目 标 场 景


女朋友会 Python 是多么可怕的一件事!


上篇文章发布之后,一位朋友告诉忽略了一件事,假设女朋友会 Python 的话,那岂不是要翻车?如果是这样的话,女朋友发过来的图片包含的地理位置是否真实,要打一个 Big Big 的问号了?

实际上,利用 Python 是可以非常方便地修改一张图片的地理位置。

2

编 写 代 码


在编写脚本之前,需要在虚拟环境下安装依赖库:piexif


第一步,我们读取原图的经度和纬度然后将地理位置格式化为浮点类型。


拿到 GPS 图片坐标之后,需要转为火星坐标系数据。





    
def read_image(self, image_path):
    """
    开始处理图片
    exifread:读取图片属性
    :return:
    """

    exif_dict = piexif.load(image_path)

    if exif_dict['GPS']:

         # 纬度
         gps_lati_pre = exif_dict['GPS'][2]

         gps_lati = dms_to_gps(gps_lati_pre)

         # 经度
         gps_long_pre = exif_dict['GPS'][4]
         gps_long = dms_to_gps(gps_long_pre)

         # GPS坐标转为高德坐标
         lng, lat = wgs84togcj02(gps_long, gps_lati)

         print(f"原图地理位置如下\n经度:{lng}\n纬度:{lat}\n")

         return f'{lng}{lat}'
    else:
         print(f'抱歉!这张图片不包含地理位置!')


第二步,利用高德 Web 服务 API 中的 逆地理编码 解析出原图的详细位置。


def get_address_by_location(self, location):
    """
    通过经纬度拿到地理位置
    :param location:
    :return:
    """

    params = {
       'key': self.ak,
        'location': location,
        'sig': self.sign
    }

    resp = json.loads(requests.get(url=self.url_regeo, params=params).text)

    if resp and resp.get('regeocode'and resp.get('regeocode').get('formatted_address'):
         address = resp.get('regeocode').get('formatted_address')
         print(f'原图的拍摄地址为:{address}\n')
    else:
         print('api解析地址出错,请检查ak!\n')


第三步,寻找一个要定位的地理位置


首先,输入目标城市和具体地址,利用高德 Web 服务 API 中的地理编码拿到要定位的地理位置。





    
def get_location_by_address(self, city, address):
    """
    通过地理位置到拿到经纬度
    地理编码:https://lbs.amap.com/api/webservice/guide/api/georegeo/
    :param address:
    :return:
    """

    params = {
            'key': self.ak,
            'city': city,
            'address': address,
            'sig': self.sign
    }

    resp = json.loads(requests.get(url=self.url_geo, params=params).text)

    # 获取坐标地址
    if resp and len(resp.get('geocodes')) >= 1 and resp.get('geocodes')[0].get('location'):
         location = resp.get('geocodes')[0].get('location')
         gps_data = location.split(',')

         # 得到经度和纬度
         gps_long = float(gps_data[0])
         gps_lati = float(gps_data[1])

         return gps_long, gps_lati
    else:
         print('api解析地址出错,请检查ak!')
         return None


第四步,修改图片的地理位置


由于 piexif 中经、纬度数据都是元组类型,因此需要将要设置的数据进行一次处理。


def gps_to_dms(gps_data):
    """
    坐标转为度、分、秒(double)
    116.397451
    http://www.gzhatu.com/du2dfm.html
    :param gps_data:
    :return:{1: b'N', 2: ((22, 1), (32, 1), (945, 100)), 3: b'E', 4: ((114, 1), (1, 1), (3445, 100))
    """

    # 度:向下取整
    gps_degree = math.floor(gps_data)

    gps_data_temp1 = (gps_data - gps_degree) * 60

    # 分
    gps_minute = math.floor(gps_data_temp1)

    gps_data_temp2 = gps_data_temp1 - gps_minute

    # 秒,取小数点后4位
    gps_second = round(gps_data_temp2 * 602)

    # 注意:秒必须转换为整形
    result = ((gps_degree, 1), (gps_minute, 1), (int(gps_second * 100 ), 100))

    return result


最后,将正确格式的经纬度数据写入到图片中去。


def write_image(self, image_path, gps_long, gps_lati):
    """
    修改文件夹下所有文件的属性
    :param image_path: 文件夹路径
    :return:
    """

    # 读取图片
    img = Image.open(image_path)

    try:
        exif_dict = piexif.load(img.info['exif'])
    except:
        print('加载文件地理位置异常!')
        return

    # 修改地理位置
    # GPS GPSLatitudeRef:N
    # GPS GPSLatitude:[22, 32, 189/20]
    # GPS GPSLongitudeRef:E
    # GPS GPSLongitude:[114, 1, 689/20]
    exif_dict['GPS'][2] = gps_to_dms(gps_lati)
    exif_dict['GPS'][4] = gps_to_dms(gps_long)

    exif_bytes = piexif.dump(exif_dict)

    # 写入到新的图片中去
    img.save(image_path, 'jpeg', exif=exif_bytes)


3

结 果 结 论


通过上面的 4 步操作,能将任意地理位置写入到图片中。


除了地理位置,图片的元数据,包含:拍摄器材、拍摄时间、拍摄参数都能进行二次修改


源码已经上传到后台,扫描下方二维码,关注公众号后回复「 行踪 即可获得下载链接。



推荐阅读



太赞了!《Python 黑魔法指南》终于面世了

pip install 和conda install有什么区别吗?

520情人节:属于Python 程序员的脱单攻略大合集

一道 3 行代码的 Python面试题,我懵逼了一天

如何用简单的位操作实现高级算法

Python吊打Excel?屁!那是你不会用!




长按下图  ➡   关注博主

(按左边关注 Python, 按右边关注 Goalng


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/63153
 
466 次点击