尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

基于Python与OpenCV的无人机航拍图像自动拼接实战指南

基于Python与OpenCV的无人机航拍图像自动拼接实战指南 最近在做一个地理信息相关的项目需要将大量无人机航拍的小范围地图比如单个地块、小区拼接成一张完整的、覆盖更大区域的地图。手动用PS一张张去对齐、处理接缝不仅效率低下而且精度难以保证对于非专业GIS人员来说门槛太高。市面上专业的GIS软件如ArcGIS、QGIS功能强大但要么价格昂贵要么学习曲线陡峭对于只想快速完成拼接任务的开发者或学生来说并不友好。因此我花时间研究并整合了一套完全免费、基于开源工具链的“小地图实时无缝拼接大地图”的解决方案。这套方案的核心是利用Python脚本自动化处理图像配准与融合无需复杂的环境配置从单张图片处理到批量自动拼接都有完整的代码示例。无论是用于学术研究、小型项目展示还是个人兴趣探索你都可以跟着本文一步步实现。本文将手把手带你完成以下内容理解核心原理搞懂图像拼接Image Stitching背后的关键步骤——特征检测、匹配、透视变换与融合。搭建轻量级环境使用Python和OpenCV10分钟内完成所有依赖安装。实战单次拼接从两张有重叠区域的照片开始编写代码实现自动对齐与拼接。升级批量处理处理一个文件夹内的数十张、上百张航拍图自动生成全景图。处理常见问题解决拼接错位、鬼影、亮度不均等典型问题并提供优化思路。探索高级应用简单介绍如何与Web地图结合实现动态预览。即使你没有计算机视觉基础也能跟着教程跑通整个流程。如果有Python基础你将能完全理解并定制代码。让我们开始吧1. 图像拼接的核心概念它如何“看懂”并连接图片在开始写代码之前我们需要明白工具在背后做了什么。图像拼接不是简单地把图片边缘贴在一起而是一个完整的计算机视觉流程主要包括以下四个步骤1. 特征检测与描述程序会像人眼一样在每张图片中寻找独特的、稳定的“关键点”比如建筑物的拐角、窗户的轮廓、树木的尖端等。常用的算法有SIFT、SURF、ORB等。ORB因为免费且速度快是我们本次的首选。算法不仅找到点还会为每个点生成一个“特征描述符”一串数字来表示该点周围像素的纹理和方向信息。2. 特征匹配程序会比较两张图片中所有特征点的描述符为第一张图的每个点在第二张图中寻找最相似的“伙伴”。这就像在两张不同的班级合照里找到同一个同学。匹配结果会生成一系列“点对”。3. 图像对齐透视变换通过上一步匹配成功的点对程序可以计算出两张图片之间的几何变换关系。对于航拍图由于拍摄视角近似垂直我们通常使用**单应性矩阵Homography Matrix**来描述这种变换。这个3x3的矩阵H能将第二张图片上的任意点(x2, y2)映射到第一张图片的坐标系中(x1, y1)。计算H的常用方法是RANSAC算法它能有效剔除错误的匹配点对离群点保证变换矩阵的准确性。4. 图像融合将第二张图片根据计算出的单应性矩阵“扭曲”到第一张图片的坐标系后它们就对齐了。但在重叠区域直接拼接会有明显的接缝。因此需要融合技术常见的有 *直接覆盖简单粗暴适用于对齐极好的情况。 *线性渐变Alpha Blending在重叠区域让两张图的像素按距离权重混合实现平滑过渡。 *多频段融合Multi-Band Blending更高级的方法能更好地处理亮度、颜色差异消除鬼影是OpenCVstitcher模块的默认方法。为什么强调“实时”和“无缝”实时在我们的上下文中更多指“自动化流程”。你准备好图片运行脚本程序会自动完成上述所有步骤无需人工干预每一步。无缝通过精准的图像对齐步骤3和自然的图像融合步骤4最终生成的大图在重叠区域过渡平滑看不出明显的接缝、重影或亮度跳跃仿佛是用一台超广角相机一次性拍成的一样。理解了这些再看代码就不会觉得是在操作“黑盒”了。2. 环境准备10分钟搞定Python与OpenCV我们的工具链非常简洁核心就是Python OpenCV。OpenCVOpen Source Computer Vision Library是一个强大的计算机视觉库内置了图像拼接所需的全套算法。2.1 安装Python确保你的电脑上安装了Python 3.7或更高版本。可以在命令行CMD或终端输入python --version或python3 --version来检查。如果没有安装请前往 Python官网 下载安装记得勾选“Add Python to PATH”。2.2 安装OpenCV及其他依赖我们使用pip包管理器来安装。打开命令行依次执行以下命令# 安装OpenCV的核心库包含主要图像处理功能 pip install opencv-python # 安装OpenCV的扩展库包含更多算法如SIFT但非必须ORB已包含在核心库中 # 如果你需要尝试SIFT可以安装 pip install opencv-contrib-python # 安装numpy这是Python科学计算的基础OpenCV依赖它 pip install numpy # 安装matplotlib用于在脚本中显示图片方便调试 pip install matplotlib版本说明本文代码基于opencv-python 4.8.x和numpy 1.24.x编写。不同小版本间API基本稳定如果遇到问题可以尝试指定版本安装如pip install opencv-python4.8.1.78。2.3 验证安装创建一个名为test_env.py的Python文件输入以下代码import cv2 import numpy as np print(fOpenCV版本: {cv2.__version__}) print(fNumPy版本: {np.__version__}) # 尝试读取一张图片请将路径替换为你电脑上的一张图片 # img cv2.imread(your_image.jpg) # if img is not None: # print(图片读取成功) # else: # print(图片读取失败请检查路径。)运行这个脚本 (python test_env.py)如果成功输出版本号且没有报错说明环境配置成功。3. 从两张图开始手写代码理解拼接全流程我们先不直接用OpenCV的高级拼接器而是自己实现核心步骤这能让你彻底理解原理。假设我们有left.jpg和right.jpg两张有水平重叠的航拍图。3.1 项目结构创建一个新的项目文件夹例如image_stitcher结构如下image_stitcher/ ├── images/ # 存放待拼接的图片 │ ├── left.jpg │ └── right.jpg ├── utils.py # 工具函数可选 └── stitch_two.py # 两张图拼接的主脚本3.2 核心代码实现 (stitch_two.py)以下是完整的、带有详细注释的代码import cv2 import numpy as np import matplotlib.pyplot as plt def stitch_images(img1, img2): 拼接两张有重叠区域的图像。 参数: img1: 第一张图像作为基准。 img2: 第二张图像。 返回: result: 拼接后的图像。 status: 是否拼接成功 (True/False)。 # 步骤1: 将图片转换为灰度图特征检测通常在灰度图上进行 gray1 cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) gray2 cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 步骤2: 初始化特征检测器与描述符 - 使用ORB # ORB是SIFT和SURF的免费替代品速度较快 orb cv2.ORB_create(nfeatures5000) # 设定最大特征点数量 # 步骤3: 检测关键点并计算描述符 kp1, des1 orb.detectAndCompute(gray1, None) kp2, des2 orb.detectAndCompute(gray2, None) # 可视化关键点可选用于调试 # img1_kp cv2.drawKeypoints(img1, kp1, None, color(0,255,0), flags0) # img2_kp cv2.drawKeypoints(img2, kp2, None, color(0,255,0), flags0) # plt.figure(), plt.imshow(cv2.cvtColor(img1_kp, cv2.COLOR_BGR2RGB)), plt.title(Keypoints in Image 1) # plt.figure(), plt.imshow(cv2.cvtColor(img2_kp, cv2.COLOR_BGR2RGB)), plt.title(Keypoints in Image 2) # plt.show() # 步骤4: 特征匹配 # 使用BFMatcher暴力匹配器进行汉明距离匹配ORB描述符是二进制字符串用汉明距离 bf cv2.BFMatcher(cv2.NORM_HAMMING, crossCheckTrue) matches bf.match(des1, des2) # 按距离排序距离越小匹配越好 matches sorted(matches, keylambda x: x.distance) # 可视化前50个匹配点可选 # img_matches cv2.drawMatches(img1, kp1, img2, kp2, matches[:50], None, flagscv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) # plt.figure(figsize(20,10)) # plt.imshow(cv2.cvtColor(img_matches, cv2.COLOR_BGR2RGB)), plt.title(Feature Matches) # plt.show() # 步骤5: 提取匹配点的坐标 src_pts np.float32([kp1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2) dst_pts np.float32([kp2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2) # 步骤6: 使用RANSAC算法计算单应性矩阵H # H能将img2上的点映射到img1的坐标系 H, mask cv2.findHomography(dst_pts, src_pts, cv2.RANSAC, 5.0) # mask是一个布尔数组标记哪些匹配点是内点inliers if H is None: print(警告无法计算单应性矩阵图片重叠区域可能不足或特征点太少。) return None, False # 步骤7: 应用透视变换将img2“扭曲”到img1的视角 # 首先计算拼接后画布的大小 h1, w1 img1.shape[:2] h2, w2 img2.shape[:2] # 获取img2四个角变换后的坐标 corners2 np.float32([[0, 0], [0, h2], [w2, h2], [w2, 0]]).reshape(-1, 1, 2) transformed_corners2 cv2.perspectiveTransform(corners2, H) # 结合img1的角点找到最终画布的边界 all_corners np.concatenate((np.float32([[0,0], [0,h1], [w1,h1], [w1,0]]).reshape(-1,1,2), transformed_corners2), axis0) [x_min, y_min] np.int32(all_corners.min(axis0).ravel() - 0.5) [x_max, y_max] np.int32(all_corners.max(axis0).ravel() 0.5) # 计算平移变换矩阵使得所有点坐标都为非负 translation_dist [-x_min, -y_min] H_translation np.array([[1, 0, translation_dist[0]], [0, 1, translation_dist[1]], [0, 0, 1]]) # 步骤8: 扭曲img2并平移 result cv2.warpPerspective(img2, H_translation.dot(H), (x_max - x_min, y_max - y_min)) # 步骤9: 将img1粘贴到结果画布上简单覆盖 result[translation_dist[1]:translation_dist[1]h1, translation_dist[0]:translation_dist[0]w1] img1 return result, True if __name__ __main__: # 读取图片 img_left cv2.imread(images/left.jpg) # 请确保图片路径正确 img_right cv2.imread(images/right.jpg) if img_left is None or img_right is None: print(错误无法读取图片请检查文件路径。) exit() # 调用拼接函数 stitched_image, success stitch_images(img_left, img_right) if success: # 保存结果 cv2.imwrite(output/stitched_two.jpg, stitched_image) # 确保有output文件夹 print(拼接成功结果已保存至 output/stitched_two.jpg) # 使用matplotlib显示结果可选 plt.figure(figsize(15, 10)) # OpenCV默认是BGRmatplotlib显示需要转为RGB plt.imshow(cv2.cvtColor(stitched_image, cv2.COLOR_BGR2RGB)) plt.title(拼接结果) plt.axis(off) plt.show() else: print(拼接失败。)3.3 运行与结果将你的两张有重叠区域的图片命名为left.jpg和right.jpg放入images/文件夹。在项目根目录下创建output/文件夹。在命令行运行python stitch_two.py。如果一切顺利你会在output/文件夹下看到拼接好的图片stitched_two.jpg并在屏幕上弹出显示窗口。第一次运行可能遇到的问题ModuleNotFoundError: No module named cv2说明OpenCV安装失败请回到第2节重新安装。error: (-215:Assertion failed) !_src.empty() in function cvtColor说明图片路径错误没有成功读取图片。请检查图片文件名和路径是否正确。拼接结果错位或重叠区域很奇怪可能两张图片重叠区域太少低于20%或特征点不明显如纯色天空、水面。尝试更换特征更丰富的图片或调整orb cv2.ORB_create(nfeatures5000)中的nfeatures参数增大。通过这个例子你已经掌握了拼接的核心流程。接下来我们让这个工具变得更强大、更自动化。4. 批量拼接处理一个文件夹里的所有航拍图实际项目中我们往往有几十甚至上百张按顺序拍摄的航拍图。手动指定每两张图去拼接不现实。我们需要一个能自动排序、并依次拼接所有图片的脚本。思路是顺序拼接Stitching in a chain。假设图片按拍摄顺序命名为img_001.jpg,img_002.jpg, ...。我们先拼接第1张和第2张得到结果A然后用结果A去拼接第3张得到结果B再用结果B去拼接第4张如此循环直到所有图片处理完毕。4.1 项目结构升级image_stitcher/ ├── batch_images/ # 存放所有待批量拼接的图片 (e.g., img_001.jpg, img_002.jpg, ...) ├── utils.py ├── stitch_two.py └── stitch_batch.py # 新的批量拼接脚本4.2 批量拼接核心代码 (stitch_batch.py)import cv2 import numpy as np import os import glob from stitch_two import stitch_images # 导入我们之前写的双图拼接函数 def load_and_sort_images(image_folder, pattern*.jpg): 从文件夹加载图片并按文件名排序。 参数: image_folder: 图片文件夹路径。 pattern: 文件匹配模式如 *.jpg, *.png。 返回: images: 按文件名排序后的图片列表。 filenames: 对应的文件名列表。 image_paths sorted(glob.glob(os.path.join(image_folder, pattern))) images [] filenames [] for path in image_paths: img cv2.imread(path) if img is not None: images.append(img) filenames.append(os.path.basename(path)) else: print(f警告无法读取图片 {path}已跳过。) print(f成功加载 {len(images)} 张图片。) return images, filenames def stitch_multiple_images(images): 顺序拼接多张图片。 参数: images: 图片列表假设已按空间顺序排列。 返回: final_result: 最终拼接图。 success: 是否成功。 if len(images) 2: print(错误至少需要两张图片进行拼接。) return None, False # 以第一张图为起点 current_result images[0] print(f开始拼接基准图片: 第1张) for i in range(1, len(images)): print(f正在拼接第 {i1} 张图片...) next_image images[i] # 调用之前写的双图拼接函数 # 注意这里 current_result 作为 img1 (基准), next_image 作为 img2 current_result, success stitch_images(current_result, next_image) if not success: print(f警告拼接第 {i1} 张图片时失败。尝试跳过此图继续。) # 一种容错策略跳过无法拼接的图继续用当前结果拼接下一张 # 你也可以选择终止或者尝试调整参数重新拼接 # 这里我们选择跳过继续循环 # 为了继续需要将 current_result 恢复为上一次成功的结果 # 但 stitch_images 修改了 current_result所以我们需要在失败时跳出或处理 # 简单起见这里打印警告并尝试继续实际可能效果不好 # 更健壮的做法是保存上一次成功的结果这里为简化流程我们假设 stitch_images 在失败时返回了 None if current_result is None: print(严重错误拼接过程中断。) return None, False # 可选每拼接完一张保存中间结果以便调试 # cv2.imwrite(foutput/intermediate_{i1}.jpg, current_result) print(所有图片拼接完成) return current_result, True if __name__ __main__: # 配置参数 IMAGE_FOLDER batch_images # 你的图片文件夹 OUTPUT_PATH output/panorama_batch.jpg FILE_PATTERN *.jpg # 可根据需要改为 *.png 等 # 1. 加载并排序图片 images, filenames load_and_sort_images(IMAGE_FOLDER, FILE_PATTERN) if len(images) 2: print(图片数量不足无法拼接。) exit() # 2. 执行批量拼接 final_panorama, success stitch_multiple_images(images) # 3. 保存并显示结果 if success: cv2.imwrite(OUTPUT_PATH, final_panorama) print(f批量拼接成功结果已保存至 {OUTPUT_PATH}) # 显示结果对于大图可能显示不全建议直接查看文件 # 可以等比例缩小显示 scale_percent 20 # 缩小到原图的20% width int(final_panorama.shape[1] * scale_percent / 100) height int(final_panorama.shape[0] * scale_percent / 100) dim (width, height) resized cv2.resize(final_panorama, dim, interpolationcv2.INTER_AREA) cv2.imshow(批量拼接结果 (已缩小), resized) cv2.waitKey(0) # 按任意键关闭窗口 cv2.destroyAllWindows() else: print(批量拼接失败。)4.3 运行批量拼接将你按顺序命名的航拍图如DJI_001.jpg,DJI_002.jpg, ...放入batch_images/文件夹。运行python stitch_batch.py。程序会依次加载图片并打印拼接进度。最终结果将保存在output/panorama_batch.jpg。注意事项图片顺序至关重要确保文件名能正确反映拍摄的空间顺序如按数字排序。如果顺序错乱拼接会失败。重叠区域要求相邻图片之间必须有足够的重叠区域建议20%-40%。无人机航拍时通常设置自动重叠度即可。内存消耗随着拼接进行中间结果图会越来越大可能消耗大量内存。处理上百张大图时需要注意。现在你已经拥有了一个可以自动化处理序列图像拼接的工具。但在实际使用中你可能会遇到一些问题我们接下来集中解决。5. 常见问题与优化方案即使算法很强大现实中的图片总会带来各种挑战。下面是一个问题排查表以及相应的解决方案。问题现象可能原因排查与解决思路拼接错位、重影1. 特征点匹配错误。2. 单应性矩阵计算不准确RANSAC内点太少。3. 图片之间存在视差非纯平移或平面场景。1.可视化匹配点取消代码中drawMatches部分的注释检查匹配是否正确。错误的匹配线会交叉混乱。2.调整RANSAC阈值cv2.findHomography(..., cv2.RANSAC, 5.0)中的5.0是重投影误差阈值像素。对于高分辨率图或匹配点精度高可以调小如2.0对于低质量图可以调大如10.0。3.使用更稳定的特征尝试SIFT算法需安装opencv-contrib-python。orb cv2.SIFT_create()。SIFT对旋转、尺度变化更稳定但速度慢。4.限制匹配距离只保留距离足够小的优质匹配。在matches sorted(matches, ...)后可以good_matches [m for m in matches if m.distance 0.75 * min_dist]。拼接结果有黑色区域或空白透视变换后画布计算不准确或基准图片位置放置不对。检查stitch_images函数中画布大小计算部分 (x_min, y_min, x_max, y_max)。确保H_translation矩阵正确地将所有像素平移到了正坐标区域。我们的代码已处理此问题。如果仍有黑边可以在最后对结果图进行一次裁剪。重叠区域模糊或鬼影图像融合方式不佳。我们的简单覆盖法在接缝处会生硬如果对齐不完美就会产生鬼影。启用高级融合使用OpenCV内置的cv2.detail_MultiBandBlender或直接使用cv2.Stitcher类见第6节。多频段融合能极大改善视觉效果。亮度/颜色不一致拍摄时曝光不同或相机自动白平衡导致相邻图片色温差异。1.前期处理在拍照时使用手动或锁定曝光/白平衡。2.后期处理在拼接前进行直方图匹配。OpenCV没有直接函数但可以用cv2.createCLAHE()进行自适应直方图均衡化或使用scikit-image库的match_histograms函数。程序报错或内存不足1. 图片分辨率太高。2. 图片数量太多中间结果图巨大。1.缩放图片在读取图片后立即进行缩放。img cv2.resize(img, (new_width, new_height))。对于测试将宽度缩放到1000-2000像素通常足够。2.增量式拼接与缓存对于超多图片不要一次性在内存中生成完整全景图。可以每拼接几张就保存到磁盘然后以这张中间图为基准继续拼接但这会损失一些精度。更专业的工具如OpenCV Stitcher有相关优化。特征点太少匹配失败图片内容特征贫乏如纯色天空、水面、雪地、纹理重复的墙面。1.增加特征点数量orb cv2.ORB_create(nfeatures10000)。2.调整特征点检测参数ORB的scaleFactor,edgeThreshold等。3.使用其他检测器如AKAZE或SIFT。4.人工添加特征如果场景可控可以在拍摄时在地面放置一些高对比度标记物。6. 进阶使用OpenCV内置的高性能拼接器OpenCV提供了一个高度优化、功能完整的cv2.Stitcher类。它内部集成了特征检测、匹配、光束法平差Bundle Adjustment、波形校正、多频段融合等一系列高级功能能处理更复杂的场景如360°全景并且通常比我们手写的简单流程效果更好、更稳定。6.1 使用cv2.Stitcher进行拼接创建一个新脚本stitch_opencv.pyimport cv2 import numpy as np import glob import os def stitch_with_opencv(image_folder, output_pathoutput/panorama_opencv.jpg): 使用OpenCV内置Stitcher拼接图片。 # 1. 加载图片 images [] image_paths sorted(glob.glob(os.path.join(image_folder, *.jpg))) for path in image_paths: img cv2.imread(path) if img is not None: # 可选缩小图片以加快处理速度 # scale 0.5 # new_width int(img.shape[1] * scale) # new_height int(img.shape[0] * scale) # img cv2.resize(img, (new_width, new_height)) images.append(img) else: print(f跳过无法读取的图片: {path}) if len(images) 2: print(图片数量不足。) return False print(f开始使用OpenCV Stitcher处理 {len(images)} 张图片...) # 2. 创建拼接器 # 尝试创建高精度拼接器 stitcher cv2.Stitcher.create(cv2.Stitcher_PANORAMA) # 对于航拍图也可以尝试 SCANS 模式 # stitcher cv2.Stitcher.create(cv2.Stitcher_SCANS) # 3. 执行拼接 status, panorama stitcher.stitch(images) # 4. 处理结果 if status cv2.Stitcher_OK: cv2.imwrite(output_path, panorama) print(f拼接成功结果保存至: {output_path}) # 显示 cv2.imshow(OpenCV Stitcher 结果, panorama) cv2.waitKey(0) cv2.destroyAllWindows() return True else: # 错误码解读 error_codes { cv2.Stitcher_ERR_NEED_MORE_IMGS: 需要更多图片, cv2.Stitcher_ERR_HOMOGRAPHY_EST_FAIL: 单应性矩阵估计失败, cv2.Stitcher_ERR_CAMERA_PARAMS_ADJUST_FAIL: 相机参数调整失败, } error_msg error_codes.get(status, f未知错误 (代码: {status})) print(f拼接失败: {error_msg}) return False if __name__ __main__: stitch_with_opencv(batch_images, output/panorama_opencv_final.jpg)6.2cv2.Stitcher的优势与注意事项优势一体化一行代码完成所有复杂步骤。更健壮内置光束法平差能优化多张图片的整体几何一致性减少累积误差。融合效果好默认使用多频段融合接缝处理更自然。功能丰富支持多种拼接模式全景、扫描等。注意事项黑盒内部过程不如自己写的代码透明调试困难。参数调优可以通过stitcher.setPanoConfidenceThresh(0.5)等方法设置置信度阈值等参数但需要查阅文档。内存与时间对于大量高分辨率图片可能比简单脚本更耗资源。失败处理如果失败错误信息不如自定义流程详细。建议对于大多数标准航拍拼接任务优先尝试cv2.Stitcher。如果遇到特定问题如需要极致的控制或调试再回退到自己实现的流程。7. 工程实践与扩展思路将脚本用于实际项目时需要考虑更多工程化问题。7.1 项目结构优化创建一个更规范的项目geo_stitch_tool/ ├── config.yaml # 配置文件拼接参数、路径等 ├── requirements.txt # 依赖列表 ├── src/ │ ├── __init__.py │ ├── feature_matcher.py # 特征匹配相关函数 │ ├── image_aligner.py # 图像对齐与变换 │ ├── blender.py # 图像融合器 │ └── stitcher.py # 主拼接逻辑 ├── scripts/ │ └── run_stitch.py # 命令行入口 ├── inputs/ # 输入图片 ├── outputs/ # 输出结果 └── logs/ # 运行日志使用argparse或click库创建命令行接口方便指定输入文件夹、输出路径、缩放比例、特征点数量等参数。7.2 性能优化并行计算特征检测和描述符计算是独立的可以对多张图片使用多进程multiprocessing加速。GPU加速OpenCV部分函数支持CUDA加速需编译OpenCV with CUDA。对于大规模处理可以考虑。金字塔缩放在特征匹配时可以先在低分辨率图像上匹配再在原图上精炼加快速度。7.3 与Web地图集成预览拼接出的大地图可以转换为Web地图服务如TMS瓦片在Leaflet或OpenLayers中展示。生成地理参考如果你的图片带有GPS信息EXIF可以使用GDAL库的gdal_translate和gdalwarp工具为拼接图生成世界文件.tfw或直接转换为GeoTIFF。切图使用gdal2tiles.py将GeoTIFF切割成金字塔瓦片。发布将瓦片放入任何HTTP服务器如Nginx用Leaflet加载。一个简单的概念性代码片段展示如何读取GPS信息需要piexif库import piexif from PIL import Image def get_gps_info(image_path): 从图片EXIF中读取GPS信息。 img Image.open(image_path) exif_dict piexif.load(img.info[exif]) gps_info exif_dict.get(GPS, {}) # 解析经纬度、海拔... # 注意这是一个复杂的过程需要将度分秒格式转换为十进制 return gps_info7.4 版本管理与依赖隔离使用venv或conda创建独立的Python环境并通过requirements.txt固定依赖版本确保项目在任何机器上可复现。# requirements.txt opencv-python4.8.1.78 numpy1.24.3 matplotlib3.7.1 Pillow9.5.0 # 用于PIL piexif1.1.3 # 用于读取EXIF从理解原理、手写代码到使用高级API再到考虑工程化扩展你已经掌握了一套完整的免费小地图拼接大地图的解决方案。这套工具链灵活、可控且完全免费足以应对大多数中小型项目的需求。关键在于根据你的图片特点重叠度、纹理、曝光调整参数并处理好那些“边缘情况”。
返回列表