🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
问题描述
无人机像素经纬度识别。根据代码,我的需求就是鼠标点击照片中某一点的坐标,能迅速识别出这一点的经纬度信息,但是两张照片,拍摄的同一位置显示的结果并不相同,我的无人机是垂直于地面飞行,不考虑地球曲率、图像畸变,我的思路是先提取出图像的经纬度信息,这个经纬度信息是飞行器拍摄位置也是图像中心点的经纬度坐标,知道了图像的GSD,调用鼠标,计算鼠标点击区域的经纬度信息。
代码如下:
import exifread
import cv2
import numpy as np
import math# 从图像文件中提取GPS信息
def extract_gps_info(file_path):with open(file_path, 'rb') as f:tags = exifread.process_file(f)if 'GPS GPSLatitude' in tags and 'GPS GPSLongitude' in tags:latitude = tags['GPS GPSLatitude'].valueslongitude = tags['GPS GPSLongitude'].valueslatitude_ref = tags['GPS GPSLatitudeRef'].valueslongitude_ref = tags['GPS GPSLongitudeRef'].valueslat_degrees = float(latitude[0].num) / float(latitude[0].den)lat_minutes = float(latitude[1].num) / float(latitude[1].den)lat_seconds = float(latitude[2].num) / float(latitude[2].den)lon_degrees = float(longitude[0].num) / float(longitude[0].den)lon_minutes = float(longitude[1].num) / float(longitude[1].den)lon_seconds = float(longitude[2].num) / float(longitude[2].den)if latitude_ref == 'S':lat_degrees = -lat_degreesif longitude_ref == 'W':lon_degrees = -lon_degreeslatitude_decimal = lat_degrees + lat_minutes/60 + lat_seconds/3600longitude_decimal = lon_degrees + lon_minutes/60 + lon_seconds/3600return latitude_decimal, longitude_decimalelse:return None# 主函数
if __name__ == '__main__':# 图像文件路径file_path = 'DJI_20231225165215_0426_T.JPG'# 提取GPS信息gps_info = extract_gps_info(file_path)if gps_info is not None:latitude_decimal, longitude_decimal = gps_infoprint(f"Latitude: {latitude_decimal:.6f}")print(f"Longitude: {longitude_decimal:.6f}")else:print("No GPS information found in the image.")# 加载热红外图像infrared_image = cv2.imread(file_path, cv2.IMREAD_UNCHANGED)# 无人机位置和姿态数据uav_latitude = latitude_decimal # 无人机纬度uav_longitude = longitude_decimal # 无人机经度uav_altitude = 20 # 无人机高度(米)uav_roll_angle = 0 # 无人机横滚角(度)uav_pitch_angle = -90 # 无人机俯仰角(度)uav_yaw_angle = 64.60#74.40 # 无人机偏航角(度)# 相机内参数focal_length = 758.33# 焦距(像素)sensor_size_width = 7.68 # 传感器宽度(毫米)sensor_size_height = 6.144 # 传感器高度(毫米)image_width = 640 # 图像宽度(像素)image_height = 512 # 图像高度(像素)gsd = 0.05275 # 单位:米 (meters),地面采样距离# 计算相机的内外参数矩阵camera_matrix = np.array([[focal_length, 0, image_width / 2],[0, focal_length, image_height / 2],[0, 0, 1]], dtype=np.float32)dist_coefs = np.zeros((4, 1), dtype=np.float32) # 假设无畸变# 鼠标单击事件回调函数def get_pixel_coord(event, x, y, flags, param):if event == cv2.EVENT_LBUTTONDOWN:# 计算点击位置在图像中的坐标pixel_x = xpixel_y = y# 计算点击点相对于中心的偏移量cx = image_width / 2 # 单位:像素 (pixels)cy = image_height / 2 # 单位:像素 (pixels)delta_x = pixel_x - cx # 单位:像素 (pixels)delta_y = pixel_y - cy # 单位:像素 (pixels)# 考虑偏航角theta = math.radians(uav_yaw_angle) # 单位:弧度 (radians)# 旋转偏移量以考虑偏航角delta_x_prime = delta_x * math.cos(theta) - delta_y * math.sin(theta) # 单位:像素 (pixels)delta_y_prime = delta_x * math.sin(theta) + delta_y * math.cos(theta) # 单位:像素 (pixels)# 根据GSD计算实际距离delta_x_meters = delta_x_prime * gsd # 单位:米 (meters)delta_y_meters = delta_y_prime * gsd # 单位:米 (meters)# 计算点击点的经纬度click_lat = uav_latitude + delta_y_meters / (111000) # 111000米大约是1度纬度的距离,单位:度 (degrees)click_lon = uav_longitude + delta_x_meters / (111000 * math.cos(math.radians(uav_latitude))) # 单位:度 (degrees)print(f"Pixel coordinates: ({x}, {y})")print(f"Latitude: {click_lat:.8f}")print(f"Longitude: { click_lon:.8f}")cv2.imshow('Infrared Image', infrared_image)cv2.setMouseCallback('Infrared Image', get_pixel_coord)cv2.waitKey(0)cv2.destroyAllWindows()
友情提示:
如上问题有的来自我自身项目开发,有的收集网站,有的来自读者…如有侵权,立马删除。再者,针对此专栏中部分问题及其问题的解答思路或步骤等,存在少部分搜集于全网社区及人工智能问答等渠道,若最后实在是没能帮助到你,还望见谅!并非所有的解答都能解决每个人的问题,在此希望屏幕前的你能够给予宝贵的理解,而不是立刻指责或者抱怨!如果你有更优解,那建议你出教程写方案,一同学习!共同进步。
解决方案
如下是上述问题的解决方案,仅供参考:
您的代码目的是通过鼠标点击图像来获取该点的经纬度信息。您已经实现了从图像中提取GPS信息,以及通过鼠标点击事件计算点击点的经纬度。但是,您提到两张照片拍摄同一位置时显示的结果不同,这可能是由几个因素造成的:
-
GPS信息的准确性:确保提取的GPS信息是准确的。有时,GPS信息可能因为多种原因(如遮挡、干扰等)而不准确。
-
图像缩放或旋转:如果图像在拍摄或处理过程中被缩放或旋转,可能会影响到计算结果。
-
GSD(地面采样距离)的一致性:确保两张照片的GSD是一致的,如果GSD不同,即使同一位置,点击相同像素点也会得到不同的经纬度。
-
相机参数的一致性:包括焦距、传感器大小等,这些参数的不同可能导致计算结果的差异。
-
地球曲率和图像畸变:虽然您提到不考虑地球曲率和图像畸变,但在实际应用中,这些因素可能对精确计算有影响。
-
鼠标点击的精度:用户点击的精度也会影响最终结果。
为了解决这个问题,您可以尝试以下步骤:
- 验证提取的GPS信息是否准确无误。
- 确保两张照片的相机参数和GSD是一致的。
- 如果可能,检查图像是否在拍摄或处理过程中被修改过。
- 考虑实现一个更精确的地理坐标转换算法,如使用地理坐标系转换库。
此外,您的代码中有几个潜在的问题需要修正:
- 在计算点击点的经纬度时,您使用了
111000
作为每度纬度的平均米数,但这个值在不同纬度下会有所变化。更准确的计算应该考虑当前纬度的地球半径。 - 您的代码中
uav_yaw_angle
有两个赋值,应该只保留一个。
修正后的代码段如下:
# 计算点击点的经纬度
# 使用WGS-84模型下的地球半径
earth_radius = 6378137 # 单位:米
click_lat = uav_latitude + (delta_y_meters / earth_radius) * (math.pi / 180)
click_lon = uav_longitude + (delta_x_meters * math.cos(math.radians(click_lat)) / earth_radius) * (math.pi / 180)
请注意,这些修正只是基于您提供的代码和描述。实际问题可能需要更详细的分析和调整。如果问题依然存在,建议检查所有可能影响计算的因素,并考虑使用更专业的地理信息系统(GIS)工具或库来处理经纬度转换。
希望如上措施及解决方案能够帮到有需要的你。
PS:如若遇到采纳如下方案还是未解决的同学,希望不要抱怨&&急躁,毕竟影响因素众多,我写出来也是希望能够尽最大努力帮助到同类似问题的小伙伴,即把你未解决或者产生新Bug黏贴在评论区,我们大家一起来努力,一起帮你看看,可以不咯。
若有对当前Bug有与如下提供的方法不一致,有个不情之请,希望你能把你的新思路或新方法分享到评论区,一起学习,目的就是帮助更多所需要的同学,正所谓「赠人玫瑰,手留余香」。
☀️写在最后
ok,以上就是我这期的Bug修复内容啦,如果还想查找更多解决方案,你可以看看我专门收集Bug及提供解决方案的专栏《CSDN问答解惑-专业版》,都是实战中碰到的Bug,希望对你有所帮助。到此,咱们下期拜拜。
码字不易,如果这篇文章对你有所帮助,帮忙给 bug菌 来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。
同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!
📣关于我
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿哇。