获取照片中Exif信息里GPS经纬度数

本文详细介绍了如何通过编程方法从图片中提取GPS坐标点,包括加载图片、获取属性、解析坐标值并转换为经纬度信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#region 读取图片中GPS点


        /// <summary>
        /// 获取图片中的GPS坐标点
        /// </summary>
        /// <param name="p_图片路径">图片路径</param>
        /// <returns>返回坐标【纬度+经度】用"+"分割 取数组中第0和1个位置的值</returns>
        public String fnGPS坐标(String p_图片路径)
        {
            String s_GPS坐标 = "";
            //载入图片   
            Image objImage = Image.FromFile(p_图片路径);
            //取得所有的属性(以PropertyId做排序)   
            var propertyItems = objImage.PropertyItems.OrderBy(x => x.Id);
            //暂定纬度N(北纬)   
            char chrGPSLatitudeRef = 'N';
            //暂定经度为E(东经)   
            char chrGPSLongitudeRef = 'E';
            foreach (PropertyItem objItem in propertyItems)
            {
                //只取Id范围为0x0000到0x001e
                if (objItem.Id >= 0x0000 && objItem.Id <= 0x001e)
                {
                    objItem.Id = 0x0002;
                    switch (objItem.Id)
                    {
                        case 0x0000:
                            var query = from tmpb in objItem.Value select tmpb.ToString();
                            string sreVersion = string.Join(".", query.ToArray());
                            break;
                        case 0x0001:
                            chrGPSLatitudeRef = BitConverter.ToChar(objItem.Value, 0);
                            break;
                        case 0x0002:
                            if (objItem.Value.Length == 24)
                            {
                                //degrees(将byte[0]~byte[3]转成uint, 除以byte[4]~byte[7]转成的uint)   
                                double d = BitConverter.ToUInt32(objItem.Value, 0) * 1.0d / BitConverter.ToUInt32(objItem.Value, 4);
                                //minutes(將byte[8]~byte[11]转成uint, 除以byte[12]~byte[15]转成的uint)   
                                double m = BitConverter.ToUInt32(objItem.Value, 8) * 1.0d / BitConverter.ToUInt32(objItem.Value, 12);
                                //seconds(將byte[16]~byte[19]转成uint, 除以byte[20]~byte[23]转成的uint)   
                                double s = BitConverter.ToUInt32(objItem.Value, 16) * 1.0d / BitConverter.ToUInt32(objItem.Value, 20);
                                //计算经纬度数值, 如果是南纬, 要乘上(-1)   
                                double dblGPSLatitude = (((s / 60 + m) / 60) + d) * (chrGPSLatitudeRef.Equals('N') ? 1 : -1);
                                string strLatitude = string.Format("{0:#} deg {1:#}' {2:#.00}\" {3}", d
                                                                    , m, s, chrGPSLatitudeRef);
                                //纬度+经度
                                s_GPS坐标 += dblGPSLatitude + "+";
                            }
                            break;
                        case 0x0003:
                            //透过BitConverter, 将Value转成Char('E' / 'W')   
                            //此值在后续的Longitude计算上会用到   
                            chrGPSLongitudeRef = BitConverter.ToChar(objItem.Value, 0);
                            break;
                        case 0x0004:
                            if (objItem.Value.Length == 24)
                            {
                                //degrees(将byte[0]~byte[3]转成uint, 除以byte[4]~byte[7]转成的uint)   
                                double d = BitConverter.ToUInt32(objItem.Value, 0) * 1.0d / BitConverter.ToUInt32(objItem.Value, 4);
                                //minutes(将byte[8]~byte[11]转成uint, 除以byte[12]~byte[15]转成的uint)   
                                double m = BitConverter.ToUInt32(objItem.Value, 8) * 1.0d / BitConverter.ToUInt32(objItem.Value, 12);
                                //seconds(将byte[16]~byte[19]转成uint, 除以byte[20]~byte[23]转成的uint)   
                                double s = BitConverter.ToUInt32(objItem.Value, 16) * 1.0d / BitConverter.ToUInt32(objItem.Value, 20);
                                //计算精度的数值, 如果是西经, 要乘上(-1)   
                                double dblGPSLongitude = (((s / 60 + m) / 60) + d) * (chrGPSLongitudeRef.Equals('E') ? 1 : -1);
                            }
                            break;
                        case 0x0005:
                            string strAltitude = BitConverter.ToBoolean(objItem.Value, 0) ? "0" : "1";
                            break;
                        case 0x0006:
                            if (objItem.Value.Length == 8)
                            {
                                //将byte[0]~byte[3]转成uint, 除以byte[4]~byte[7]转成的uint   
                                double dblAltitude = BitConverter.ToUInt32(objItem.Value, 0) * 1.0d / BitConverter.ToUInt32(objItem.Value, 4);
                            }
                            break;
                    }
                }
            }
            return s_GPS坐标;
        }


        #endregion
<think>好的,我现在需要帮助用户在ArcGIS Pro 3.4.3中创建一个Python脚本工具,将带有地理标记的照片批量转换为KMZ文件。首先,我需要理解用户的需求,然后结合提供的引用和ArcGIS Pro的相关知识来构建解决方案。 首先,用户提到他们想将包含经纬度信息照片批量转换为KMZ文件。KMZ是Google Earth使用的压缩格式,通常包含KML文件和相关的资源,如图片。因此,核心任务是从照片中提取经纬度信息,生成对应的地标,并打包成KMZ。 根据引用[1]中的信息,ArcGIS Pro的地形工具通过Python脚本扩展功能,虽然用户的需求不涉及地形,但可以借鉴脚本工具的创建方法。引用[3]详细说明了如何创建Python脚本工具,包括工具名、标签的设置,以及如何从Python调用工具。因此,我需要确保脚本符合这些规范。 接下来,我需要考虑如何从照片中读取经纬度信息。通常,带有地理标记的照片(如JPEG格式)会在EXIF数据中存储GPS信息。Python中有库如Pillow(PIL)或exifread可以读取这些信息。因此,脚本需要处理这些EXIF数据,提取经纬度,并转换为十进制度格式,因为KML需要这种格式。 然后,需要将这些坐标点生成地理数据,比如Shapefile或要素类,再转换为KML/KMZ。根据引用[2],用户可能已经了解如何将坐标数据生成Shapefile,但这需要的是直接生成KMZ。ArcPy模块中的ConvertCoordinateNotation和LayerToKML工具可能有用。或者,直接使用Python生成KML文件结构,然后压缩为KMZ。 步骤分解可能如下: 1. 遍历输入文件夹中的照片,提取GPS经纬度。 2. 将经纬度转换为十进制度(可能需要处理度分秒格式)。 3. 创建点要素类或Shapefile存储这些点。 4. 将要素类转换为KML,然后打包为KMZ。 5. 创建ArcGIS Pro脚本工具,配置参数(输入文件夹、输出KMZ路径等)。 需要注意的问题: - EXIF数据中的经纬度可能以度分秒存储,需要转换为十进制。 - 处理不同照片格式的兼容性。 - 确保ArcPy的环境设置正确,比如工作空间、输出坐标系。 - 脚本工具的参数验证,比如输入是否为文件夹,输出路径是否正确。 根据引用[3],脚本工具需要正确的名称和标签,并配置参数。用户需要将脚本添加到工具箱中,设置参数(输入文件夹、输出KMZ路径),然后脚本处理这些参数。 可能的代码结构: - 使用arcpy.mp模块访问项目。 - 使用os模块遍历文件夹。 - 使用exifread读取EXIF。 - 创建临时要素类,插入点。 - 使用arcpy.conversion.LayerToKML生成KMZ。 此外,可能需要处理照片路径与点属性的关联,例如在KML中显示图片的缩略图或链接。但KMZ本身可以包含图片,但用户的需求可能只是将照片的位置生成地标,可能不需要嵌入图片。需要澄清,但假设用户只需要地标点,每个点对应照片的位置,并在点击时显示照片信息。 因此,生成的KML需要每个Placemark的<description>包含照片路径或缩略图。但KMZ中如何引用外部图片可能需要考虑路径问题,或者将图片嵌入到KMZ中。这可能复杂化脚本,但用户可能只需基本的位置点。 综上,步骤大致如下: 1. 读取照片EXIF GPS信息。 2. 创建要素类存储点。 3. 转换为KML/KMZ。 4. 创建脚本工具,设置参数。 现在,编写具体的Python脚本,并指导用户如何将其封装为ArcGIS Pro的脚本工具。</think>在 ArcGIS Pro 3.4.3 中实现此功能需要结合 Python 脚本和 ArcPy 地理处理框架,以下是分步实现方案: ### 一、脚本编写步骤 1. **读取照片元数据** 使用 `exifread` 库提取照片GPS 经纬度信息: ```python import exifread def get_gps_coords(image_path): with open(image_path, 'rb') as f: tags = exifread.process_file(f) lat_tag = tags.get('GPS GPSLatitude') lon_tag = tags.get('GPS GPSLongitude') # 转换度分秒为十进制格式 lat = float(lat_tag.values[0]) + float(lat_tag.values[1]/60) + float(lat_tag.values[2]/3600) lon = float(lon_tag.values[0]) + float(lon_tag.values[1]/60) + float(lon_tag.values[2]/3600) return lat, lon ``` 2. **创建地理处理工具框架** ```python import arcpy import os class Toolbox: def __init__(self): self.label = "PhotoToKMZ Toolbox" self.alias = "" self.tools = [PhotoToKMZ] class PhotoToKMZ: def __init__(self): self.label = "Generate KMZ from Photos" self.description = "Convert geotagged photos to KMZ" def getParameterInfo(self): params = [ arcpy.Parameter( name="input_folder", displayName="Input Photo Folder", datatype="DEFolder", parameterType="Required" ), arcpy.Parameter( name="output_kmz", displayName="Output KMZ File", datatype="DEFile", parameterType="Required" ) ] return params ``` 3. **生成要素类并转换** ```python def execute(self, parameters, messages): input_folder = parameters[0].valueAsText output_kmz = parameters[1].valueAsText # 创建临时要素类 sr = arcpy.SpatialReference(4326) # WGS84 fc = arcpy.CreateFeatureclass_management("memory", "PhotoPoints", "POINT", spatial_reference=sr)[0] arcpy.AddField_management(fc, "PhotoPath", "TEXT") # 插入点要素 with arcpy.da.InsertCursor(fc, ["SHAPE@XY", "PhotoPath"]) as cursor: for photo in os.listdir(input_folder): if photo.lower().endswith(('.jpg', '.jpeg')): photo_path = os.path.join(input_folder, photo) try: lat, lon = get_gps_coords(photo_path) cursor.insertRow([(lon, lat), photo_path]) except Exception as e: arcpy.AddWarning(f"跳过 {photo}: {str(e)}") # 转换为KMZ arcpy.LayerToKML_conversion(fc, output_kmz) ``` ### 二、工具创建流程 1. **创建脚本工具** - 在 Catalog 窗格中右键单击工具箱 > New > Script - 名称填写 `PhotoToKMZ`(遵循Python命名规范,无空格)[^3] - 标签填写 "Generate KMZ from Photos" - 脚本文件选择上述Python文件 2. **配置参数** - 添加两个参数:文件夹类型输入参数和文件类型输出参数 - 输出参数扩展名设置为 `.kmz` ### 三、关键技术点 1. **坐标转换**:需处理 EXIF 存储的度分秒格式(如 $(\frac{37}{1}, \frac{45}{1}, \frac{4326}{100})$)转换为十进制度 2. **批量处理**:使用 `os.listdir` 遍历文件夹,支持 JPEG/JPG 格式 3. **错误处理**:跳过无 GPS 信息照片并生成警告 ### 四、验证方法 1. 准备包含 EXIF GPS 信息的测试照片 2. 运行工具后使用 Google Earth 打开输出的 KMZ 文件 3. 确认点位位置与照片实际拍摄坐标一致
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

csdn_aspnet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值