【Python&GIS】判断图片中心点/经纬度点是否在某个面内

        Python的exifread库可以获取图片中的源数据信息,包括经纬度、相机厂商、曝光时间、焦距、拍摄时间、拍摄地点等等信息。我们可以通过exifread库从图片中获取图片的经纬度,再通过shapely库判断该经纬度对应的点是否在我们的感兴趣区内。

        当然你需要知道图片的经纬度是什么坐标系,大部分是WGS84地理坐标系,具体需要自己了解。如果是GPS定位那么就是WGS84坐标系。

        shapely主要是在笛卡尔平面对几何对象进行操作和分析,它是一个BSD授权的Python包。shapely不关心数据格式或坐标系,但可以很容易地与这些文件包集成。

        geopandas是用来处理地理空间数据的python第三方库,它是在pandas的基础上建立的,完美地融合了pandas的数据类型,并且提供了操作地理空间数据的高级接口,使得在python中进行GIS操作变成可能。

1.导入所需要的三方库。exifread、geopandas、shapely

import exifread
import geopandas
from shapely.geometry import Point

2.打开本地图片,使用exifread读取图片的源数据信息,读取其中的经纬度信息,获取经纬度后记得关闭图片进程。

        f = open(path_image,'rb')中的path_image即为本地图片的路径。

f = open(path_image, 'rb')
# 打开图片
contents = exifread.process_file(f)
# 获取图片属性信息
longitude = contents["GPS GPSLongitude"].values
# 获取Long
longitude_f = longitude[0].num/longitude[0].den + (longitude[1].num/longitude[1].den/60) + (longitude[2].num/longitude[2].den/3600)
latitude = contents["GPS GPSLatitude"].values
# 获取Lat
latitude_f = latitude[0].num/latitude[0].den + (latitude[1].num/latitude[1].den/60) + (latitude[2].num/latitude[2].den/3600)
# print("经度:", longitude_f)  # contents['GPS GPSLatitudeRef']
# print("纬度:", latitude_f)  # contents['GPS GPSLongitudeRef']
f.close()
# 关闭图片

3.创建工作空间,将图片经纬度信息写入矢量图层,使用shapely.geometry的contains函数判断点是否在面内。

        根据返回值判断点是否在面内。返回值为True or False,True则点在面内,False则点在面外。     

datasource = geopandas.GeoDataFrame.from_file(path_conservation_area, encoding='utf-8')
# 创建工作空间
boundary_shape = datasource['geometry'][0]
# 将shp区域加载到工作空间
determine_contain = boundary_shape.contains(Point([longitude_f, latitude_f]))
# 判断点是否在区间内

4.完整代码,记得改成自己的路径。

        1)面矢量数据“path_conservation_area”的路径

        2)本地图片“path_image”的路径

# -*- coding: utf-8 -*-
"""
@Time : 2023/5/15 15:57
@Auth : RS迷途小书童
@File :Discriminative point surface.py
@IDE :PyCharm
"""
import exifread
import geopandas
from shapely.geometry import Point


def Get_LatLon(path_image):
    """
    :param path_image: 输入图片路径
    :return: 返回经纬度
    """
    f = open(path_image, 'rb')
    # 打开图片
    contents = exifread.process_file(f)
    # 获取图片属性信息
    longitude = contents["GPS GPSLongitude"].values
    # 获取Long
    longitude_f = longitude[0].num/longitude[0].den + (longitude[1].num/longitude[1].den/60) + (longitude[2].num/longitude[2].den/3600)
    latitude = contents["GPS GPSLatitude"].values
    # 获取Lat
    latitude_f = latitude[0].num/latitude[0].den + (latitude[1].num/latitude[1].den/60) + (latitude[2].num/latitude[2].den/3600)
    # print("经度:", longitude_f)  # contents['GPS GPSLatitudeRef']
    # print("纬度:", latitude_f)  # contents['GPS GPSLongitudeRef']
    f.close()
    # 关闭图片
    return longitude_f, latitude_f


def Filter_images(path_conservation_area, longitude_f, latitude_f):
    """
    :param path_conservation_area: 面数据路径
    :param longitude_f: 经度
    :param latitude_f: 纬度
    :return: True or False
    """
    # path_conservation_area = r'G:/B60/B60.shp'
    datasource = geopandas.GeoDataFrame.from_file(path_conservation_area, encoding='utf-8')
    # 创建工作空间
    boundary_shape = datasource['geometry'][0]
    # 将shp区域加载到工作空间
    determine_contain = boundary_shape.contains(Point([longitude_f, latitude_f]))
    # 判断点是否在区间内
    return determine_contain


if __name__ == "__main__":
    path_conservation_area = r'G:/B60/B60.shp'
    # 面数据路径
    path_image = "G:/image1.jpg"
    # 图片路径
    longitude_f, latitude_f = Get_LatLon(path_image)
    # 执行获取经纬度函数
    determine_contain = Filter_images(path_conservation_area, longitude_f, latitude_f)
    # 执行判断点是否在区间的函数
    print(determine_contain)

        如果不需要读取图片,已经有经纬度的点,则可以不执行Get_LatLon()函数,直接将经纬度信息作为入参执行Filter_images()函数即可。同时还可以使用for循环查看多个点数据,当然如果想查看面与面是否存在包含关系同样也可以实现,自己改下图层空间即可。

        

        本文章分享个人在工作项目中使用到的代码,仅供学习使用!如有侵权请联系作者删除,大家有问题可以留言交流,博主会及时回复。

posted @ 2023-05-15 18:30  RS迷途小书童  阅读(195)  评论(0编辑  收藏  举报  来源