简介:这份PDF文档围绕Agisoft Photoscan生成DEM与正射影像的完整作业流程展开,面向无人机航测、测绘遥感与GIS方向的初学者及一线技术人员,帮助打通从原始航拍照片到数字高程模型、正射影像产品之间的参数配置与操作路径。内容按参数预设、添加照片、装载相机POS文件、检查相机校准、对齐照片、布设像控点标记、优化照片对齐、设置边界框、建立密集点云等环节逐条梳理,并延伸至构建网格、编辑几何、构建纹理、Build DEM与Build Orthomosaic等步骤,对精度、配对预选、关键点数量、深度过滤等参数给出具体推荐值与设置依据,同时说明GCP精度设置与验证点评估思路,便于对照实操与排查问题。资源包共1个PDF文件,约512KB,篇幅紧凑,可作航测内业作业的操作参照与速查手册。目前已有1357人学习下载。
1. 从航拍到 DEM 和正射影像:Photoscan 这套流程解决什么问题
一个 2 平方公里的丘陵测区,无人机飞三个架次,拿回 800 多张带 POS 的照片,委托方要两份成果:一份能进 GIS 做坡度、汇流分析的高程栅格,一份能当底图量田埂、量房角的正射影像。Photoscan(新版更名 Metashape,菜单与参数基本沿用)从头到尾都能做出来。
它走的是 SfM 加 MVS 的路子:先从重叠区域找特征点,反算每张照片的拍摄位置和姿态,再把照片按像素匹配成稠密三维点云,最后把点云栅格化成高程模型、把照片按正射投影拼成影像。不需要摄影测量工作站,一台大内存机器加一块像样的显卡就能跑。
点云、DEM、正射影像这三样要分清:点云是带高程的离散点,DEM 是栅格化之后的高程面,正射影像是消除了相机倾斜和地形投影差、每个像素都对应真实平面位置的影像。做地形分析用 DEM,做底图用 DOM,做三维展示才用点云和 Mesh。
适合测绘、地信、水利、矿山的作业人员自己出成果而不是外包,也适合手里攥着一批照片要转栅格的研究人员。默认参数能出东西,但能不能过检查,全看旋钮怎么调。
2. 重叠度、GSD 与工程坐标系:DEM 精度在起飞前就定死了
2.1 航向旁向重叠度与 GSD 的换算:给出可套用的数字
先给结论:航向重叠不低于 75%,旁向重叠不低于 65%,这是航测出 DEM 的常规门槛。低于这个数,在草地、水面、裸岩这类弱纹理区域,特征点提取会成片失败,匹配断链,密集点云上留下空洞,后面 DEM 插值出来是一层平滑的假地形——看着正常,拿去做坡度分析全是错的。
地面分辨率(GSD)决定成果的物理极限,公式是:
GSD = 像元尺寸 × 相对航高 / 镜头焦距三项单位统一到米。举例:1 英寸传感器像元 2.4 μm,镜头焦距 8.8 mm,航高 120 m:
GSD = 2.4e-6 m × 120 m / 8.8e-3 m ≈ 0.0327 m ≈ 3.3 cm反过来要凑一个指定 GSD,航高按H = GSD × f / 像元尺寸推。很多新手先飞再算,飞完发现 GSD 只到 8 cm,出不了 1:500 的图,只能重飞。
| 项目 | 常规建议 | 平坦或水面多的测区 | 说明 |
|---|---|---|---|
| 航向重叠 | 75%–80% | ≥80% | 低于 65% 极易断链 |
| 旁向重叠 | 65%–70% | ≥70% | 丘陵区按上限走 |
| GCP 数量 | 每架次 5–8 个 | 8–10 个 | 四角加中心,别挤在中间 |
| GCP 刺点精度 | 优于 0.5 倍 GSD | 优于 0.5 倍 GSD | 影像上大约半个像素 |
| 快门类型 | 全局快门优先 | 卷帘需开补偿 | 快飞时卷帘会出果冻效应 |
2.2 GCP 布设与刺点精度:绝对精度的唯一来源
GCP 决定了成果的绝对坐标。没有 GCP,空三出来的模型形状再漂亮,位置也是飘的,平面能差几米,高程差几十厘米都属正常。
靶标用黑白十字或对顶三角,边长 40–60 cm,在 120 m 航高、3 cm GSD 下大约占 10–15 个像素,足够刺准。布点原则是包住测区而不是铺满测区:四角各一个,中心一个,测区跨度大就在长边中点补。RTK/PPK 无人机可以不布 GCP,但建议留 2–3 个当检查点,一旦发现系统性偏差,能立刻分清是空三的问题还是机载 GPS 高程的问题。
刺点动作本身容易被轻视。在 Photoscan 的 Reference 面板里把影像放大到像素级,中心对着靶标中心点,刺偏一个像素就约等于 1 倍 GSD 的误差。3 cm 的 GSD,刺偏 3 个像素,高程上就是接近 10 cm 的来源,比很多误差项都大。
2.3 新建工程、导入照片与投影坐标系设置的最小脚本
Photoscan 支持用 Python 控制台跑流程,比纯手工点击更可复现。
import PhotoScan doc = PhotoScan.app.document chunk = doc.addChunk() # 照片列表,注意路径要用原始 JPG,别用已经被压缩过的缩略图 photo_list = [r"D:\flight\IMG_0001.JPG", r"D:\flight\IMG_0002.JPG"] chunk.addPhotos(photo_list) # 关键一步:设成投影坐标系,而不是 EPSG::4326 这种地理坐标系 # EPSG::32650 = WGS84 / UTM zone 50N,高程系统按项目需求挂 EGM96 crs = PhotoScan.CoordinateSystem("EPSG::32650") chunk.crs = crs doc.save(r"D:\proj\demo.psz")逻辑说明:addPhotos会把 EXIF 里的 POS 读进 Reference 表,后续对齐时用作初值。chunk.crs必须设成投影坐标系,因为地理坐标系下 DEM 的像素单位是度,分辨率没法用米表达,面积和距离都带形变。挂高程基准时可以用复合坐标系,比如把 UTM 50N 和 EGM96 大地水准面组合,否则机载 GPS 给的椭球高和实测正常高之间会差一个大地水准面差距,丘陵区能到十几米。
注意:工程文件要及时另存版本。地面点分类、DEM 重建这些操作会覆盖中间结果,出问题时能回退到对齐完成那一步,比重新跑一遍密集点云省几个小时。
2.4 掩膜处理:把天空、水面和移动物体挡在特征匹配之外
掩膜不是可选项。天空背景、水面反光、路上的移动车辆,这三类是特征匹配的噪声源。水面反光会让软件在同一个物理点上匹配出不同深度的点,车辆会在地面上糊出一块凸起,天空区域则直接产生远处的错误点。
手工做法是在照片视图里用矩形或多边形工具刷掉。批量做法是在脚本里按规则生成:
# 对每张照片生成掩膜,参数为容差与矩形边界 chunk.generateMasks( method=PhotoScan.MaskMethod.Background, tolerance=10, camera=chunk.cameras[0] ) # 让对齐阶段使用掩膜 chunk.matchPhotos(filter_mask=True, mask_tiepoints=True)tolerance控制背景判定的宽容度,纯色背景调到 8–15 之间,复杂的城市天空要手工补。mask_tiepoints=True会让掩膜区域内的连接点不参与运算,代价是要重建一次掩膜,收益是点云上的鬼影明显减少。测区里有大面积水域时,更稳的做法是拿到水面矢量或者在 GIS 里手工描出范围再回导,靠容差自动判水面反光经常失效。
3. 对齐照片到密集点云:Photoscan 重建阶段的参数逐项拆解
3.1 Align Photos 的 5 个参数与最小运行脚本
对齐这一步决定了后面所有成果的地基。参数不多,但每一个都有明确的代价和收益。
| 参数 | 建议值 | 参数说明 |
|---|---|---|
| Accuracy | High,大测区先 Medium 试跑 | 降采样层级,Highest 用原图 |
| Generic preselection | 照片超过 50 张时开 | 用影像相似度先分组,能省一半时间 |
| Reference preselection | 有 POS 数据时开 | 按坐标临近选候选匹配,提速最明显 |
| Key point limit | 40000,弱纹理调到 60000 | 单张照片保留的特征点数上限 |
| Tie point limit | 0 | 0 表示不限制连接点总数 |
| Adaptive camera model fitting | 开 | 自动决定额外畸变参数 |
chunk.matchPhotos( accuracy=PhotoScan.Accuracy.HighAccuracy, generic_preselection=True, reference_preselection=True, filter_mask=True, mask_tiepoints=True, keypoint_limit=40000, tiepoint_limit=0 ) chunk.alignCameras()accuracy不是越高越好。Highest 用原图匹配,时间可能是 High 的四倍,而在地形起伏平缓、纹理重复的农田区,多出来的特征点大多是噪声。测区跨十几个架次时,先用 Medium 跑一遍,看对齐率是否达到 95% 以上,再决定要不要提高。
reference_preselection依赖 POS 精度。无人机自带的单点 GPS 精度只有几米,参考预选可能选错候选集,导致局部匹配失败。这种情况下把它关掉,用 Generic preselection 更稳。
3.2 Optimize Cameras 与渐进式点过滤:把 GCP 残差压到 1 倍 GSD 以内
对齐完成后,连接点里混着大量误差偏大的点,直接建密集点云会把误差放大。标准动作是循环三步:过滤、重优化、再看残差。
# 第一轮:按重建不确定性过滤,阈值 10 f = PhotoScan.PointCloudFilter() f.init(chunk, PhotoScan.Criterion.ReconstructionUncertainty) f.selectPoints(10.0) f.removePoints() chunk.optimizeCameras(fit_f=True, fit_cx=True, fit_cy=True, fit_k1=True, fit_k2=True, fit_k3=True, fit_p1=True, fit_p2=True, adaptive_fitting=True) # 第二轮:按投影精度过滤,阈值 3 f.init(chunk, PhotoScan.Criterion.ProjectionAccuracy) f.selectPoints(3.0) f.removePoints() chunk.optimizeCameras(fit_f=True, fit_cx=True, fit_cy=True, fit_k1=True, fit_k2=True, fit_k3=True, fit_p1=True, fit_p2=True, adaptive_fitting=True) # 第三轮:按重投影误差过滤,阈值 0.3 f.init(chunk, PhotoScan.Criterion.ReprojectionError) f.selectPoints(0.3) f.removePoints() chunk.optimizeCameras(fit_f=True, fit_cx=True, fit_cy=True, fit_k1=True, fit_k2=True, fit_k3=True, fit_p1=True, fit_p2=True, adaptive_fitting=True)每一步删完连接点都要重新优化一次,否则相机参数还是按旧的连接点算出来的,等于白删。三个阈值是经验值:重建不确定性针对的是游离在主体结构之外的点,投影精度针对的是匹配位置不准的点,重投影误差针对的是残差大的点。
当主点 cx、cy 和焦距 f 的初始值本来就不确定时,可以先勾上fit_f、fit_cx、fit_cy做一次粗优化,把参数拉到合理区间,再放开径向畸变 k1–k3 和切向畸变 p1、p2。一次全放开容易收敛到局部极小,残差反而变大。
优化结束后看 GCP 残差。chunk.markers里每个标记点的 error 都会更新,正常应该在 1 倍 GSD 以内。某个点突然比别的点大三五倍,先别急着删,把它单独勾掉再优化一次做对比,多数时候是刺点位置偏了,而不是那个点本身有问题。
3.3 Build Dense Cloud:Quality 与 Depth Filtering 对 DEM 的实际影响
密集点云是 DEM 的直接数据源,这里的参数直接决定成果的颗粒度。
chunk.buildDenseCloud( quality=PhotoScan.Quality.HighQuality, filter_mode=PhotoScan.FilterMode.AggressiveFiltering, keep_depth=True, reusable_depth=True )quality对应图像降采样倍率,实际影响是点间距:
| Quality | 降采样 | 点间距相对 GSD | 典型用途 |
|---|---|---|---|
| Ultra High | 原图 | 约 1 倍 | 精细单体建模,耗时最长 |
| High | 1/4 | 约 2 倍 | 常规 DEM 与正射影像 |
| Medium | 1/16 | 约 4 倍 | 大测区快速出图 |
| Low | 1/64 | 约 8 倍 | 质量预检查 |
| Lowest | 1/256 | 约 16 倍 | 只做概览,不适合出图 |
按 3 cm 的 GSD 算,High 出来的点间距约 6 cm,DEM 分辨率设在 0.05–0.1 m 是匹配的。选 Ultra High 而 DEM 只出 0.5 m,多花的时间全浪费。
filter_mode影响的是离群点处理强度。Aggressive 对地形测量最合适,会把建筑边缘、树冠外侧那些飘出去的点削掉;代价是薄结构(电线、护栏、细杆)也会一起消失。如果成果要包含这些细节,改用 Mild。keep_depth和reusable_depth打开后会保留深度图,后续重新生成点云时能直接复用,省一次完整计算,代价是工程文件膨胀,SSD 紧张就别开。
4. Build DEM 与 Build Orthomosaic:两套成果的生成参数表
4.1 高程源选密集点云还是 Mesh,分辨率设到多少
Photoscan 允许从三种数据源生成高程栅格:稀疏连接点、密集点云、Mesh。连接点只用来看粗略形态,正式成果不用它。剩两个选择:
密集点云细节最全,保留了所有可见面,包括植被冠层、车顶、屋顶,出来的本质是 DSM。Mesh 是点云三角化后的结果,表面连续、没有空洞,适合做正射影像的投影面,因为它不会在影像上留下因点云空洞产生的破洞。做法上是先出 DSM 用于正射影像,再对点云做地面点分类,用 Ground 类点重新生成 DEM。
分辨率设置有个反直觉的点:把 DEM 分辨率设得比 GSD 还细,比如 GSD 3 cm 却设成 0.01 m,不会提高精度,只会把文件撑大好几倍,地图上看到的还是插值出来的平滑曲面。合理区间是 GSD 的 1–3 倍。
4.2 Build DEM 的关键参数与无数据区域填充
chunk.buildDem( source_data=PhotoScan.DataSource.DenseCloudData, interpolation=PhotoScan.Interpolation.EnabledInterpolation, projection=chunk.crs, region=chunk.region, classes=PhotoScan.PointClass.All )source_data三个取值:TiePointsData只做预览,DenseCloudData是常规选择,MeshData在点云空洞多时更稳。projection一定要显式指定成和 chunk 一致的投影坐标系,跨带测区先决定用哪个带,不要中途改。
interpolation是重灾区,三个取值的差别很大:
Disabled不填充,点云没覆盖到的地方留 NoData。做地形分析时这是最诚实的做法,让人一眼看出数据缺失在哪里。EnabledInterpolation只填内部空洞,边界外不延伸,适合大多数交付场景。Extrapolated连边界外都外推,大范围使用会在测区边缘造出一圈根本不存在的地形,水文分析时这些假高程会直接污染汇流结果。
classes决定用哪一类点。默认的 All 出的是 DSM,建筑和树的高度都在里面;改成PhotoScan.PointClass.Ground得到的是真正意义上的 DEM,前提是点云已经做过地面点分类。
注意:DEM 里 NoData 的取值不要用 0。0 在多数高程基准下是合法值,海平面附近或者低洼地区会被当成真实地形参与计算。
4.3 Build Orthomosaic 的混合模式、颜色校正与接缝线
正射影像的生成参数里,混合模式对观感的影响最大。
chunk.buildOrthomosaic( surface_data=PhotoScan.DataSource.ElevationData, blending_mode=PhotoScan.BlendingMode.MosaicBlending, color_correction=True, enable_holes=True, fill_holes=True, ghosting_filter=True, resolution_x=0.03, resolution_y=0.03 )| 混合模式 | 效果 | 适用场景 |
|---|---|---|
| Mosaic | 按接缝线取单张影像,锐度最好 | 常规 DOM 交付 |
| Average | 多张取平均,接缝平顺但边缘发虚 | 有薄结构、想掩盖接缝跳变 |
| Disabled | 不做混合 | 排查拼接问题 |
color_correction处理的是不同架次、不同光照下的色调跳变。白天光照变化快的时段飞行,不开就会出现明显色块。反过来说,如果成果要拿去做植被指数、辐射反演这类定量分析,必须关掉,因为它直接改动像素亮度值,破坏了辐射一致性。
ghosting_filter专治移动物体,路上跑的车会在多张照片里出现在不同位置,开启后能挑一张作为主影像。接缝线在建筑边缘、陡坎和大高差处最容易拉花,Photoscan 支持手工编辑接缝线,把缝挪到人眼不敏感的地面区域。
4.4 导出 GeoTIFF 并用 gdalinfo 校验坐标系
# 导出 DEM chunk.exportRaster( path=r"D:\out\dem.tif", image_format=PhotoScan.ImageFormat.ImageFormatTIFF, source_data=PhotoScan.DataSource.ElevationData, nodata_value=-9999, tiled=True, bigtiff=True ) # 导出正射影像 chunk.exportRaster( path=r"D:\out\dom.tif", image_format=PhotoScan.ImageFormat.ImageFormatTIFF, source_data=PhotoScan.DataSource.OrthomosaicData, tiled=True, bigtiff=True, compression=PhotoScan.CompressionType.LZW )bigtiff=True在成果超过 4 GB 时必开,不开会在写到一半时报错。tiled=True让 GIS 软件按块读取,浏览大图时不卡。nodata_value统一设成 -9999 或 -32767,全流程保持一致,不然拼接时会出现 NoData 被当成有效值的低级错误。
导出之后不要直接交付,用 GDAL 验一遍:
# 查看坐标系、像素大小、NoData 值和统计范围 gdalinfo -stats dem.tif # 只看高程极值,超出测区合理范围的多半是噪声点 gdalinfo -mm dem.tif | grep "Computed Min/Max"-stats会算一遍统计量,如果最大值出现在测区边界且比周围高出几十米,基本是外推或者边缘噪声造成的,回去在点云里把边界外的点裁掉再重生成。-mm只看极值,速度更快,适合批量检查。
5. 地面点分类与成果校验:把 DSM 修成能进 GIS 的 DEM
5.1 用 Classify Ground Points 从密集点云里抠出地面
不做分类,出来的 DEM 其实是 DSM,屋顶、树冠的高度全在里面。坡度分析会报出荒诞的结果——一栋 30 米的楼在 5 米的间距上算出几百度的坡。
chunk.dense_cloud.classifyGroundPoints( max_angle=15.0, # 地面最大坡度角(度) max_distance=1.0, # 点到地面拟合面的最大距离(米) cell_size=2.0 # 分析窗口大小(米) )max_angle是判断坡面连续性的上限,丘陵区用 15–20,密集城区调到 10–12,否则屋顶斜坡会被误判成地面。max_distance控制点被接受为地面点的容差,点云噪声大时适当放宽到 1.5–2.0,但放太宽会把低矮灌木一起收进来。cell_size是窗口尺寸,经验值是 GSD 的 50–100 倍,3 cm 的 GSD 对应 1.5–3 m。
分类完先看比例:裸地测区地面点应占 60%–70%,城市建成区 20%–40% 属正常,低于 15% 说明参数过严,地面被削得残缺不全。然后回到 4.2 节,把classes改成PhotoScan.PointClass.Ground重新生成一次 DEM,这才是能用来做地形分析的高程数据。
5.2 独立检查点与 RMSE:DEM 精度怎么算出来
精度不是靠看图看出来的,要靠不参与平差的检查点算出来。在 Reference 面板里把用作检查的标记点取消勾选,它们就不会参与优化,只在平差后显示残差。
chunk.exportReference( path=r"D:\out\check_points.csv", format=PhotoScan.ReferenceFormatCSV, columns="nxyzXYZ", delimiter="," )导出的 CSV 里同时有实测坐标和模型坐标,用中误差公式统一算:
RMSE_z = sqrt( Σ(z_i − ẑ_i)² / n )平面和高程分开算。判据用 GSD 的倍数比较直观:
| 指标 | 良好 | 需要返工 |
|---|---|---|
| 平面 RMSE | ≤ 1 倍 GSD | > 3 倍 GSD |
| 高程 RMSE | ≤ 2 倍 GSD | > 3 倍 GSD |
| 单个 GCP 残差 | 均匀分布 | 单点突变超过 3 倍 |
单点突变和整体偏大是两类问题。整体偏大查 POS 高程和坐标系统设置,单点突变查刺点。把检查点结果留档,后面换算法或改参数重跑,能直接对比是否真的变好了。
5.3 GIS 中的 DEM 分割与水文预处理
DEM 交付后最常见的两个后续动作是切块和水文分析。切块用 GDAL 比在 GIS 里手工裁剪更可控:
# 按像素窗口切出一块,坐标系不变 gdal_translate -srcwin 0 0 2000 2000 dem.tif tile_00.tif # 按地理范围裁剪,顺便重采样到 5 米 gdalwarp -te 500000 4000000 505000 4005000 -tr 5 5 dem.tif dem_clip.tif-srcwin用像素行列号定位,适合规整分幅;-te用左上右下地理坐标定位,适合按行政区或流域范围裁剪。切出来的瓦片保留 1–2 个像素的重叠边,拼接时用 VRT 或合并工具而不是简单镶嵌,能避免接缝处出现坡度突变。
水文分析前要先处理 DEM 本身的问题。桥、涵洞会让水流在地表模型上断开,低洼处的凹陷会让流向计算陷入死循环,这就是水文预处理环节报错的高频来源。通行做法是先填洼再按道路矢量抬升,同时把 NoData 区域显式标注出来,不要让软件把 -9999 当成一个深坑去参与汇流计算。
本文还有配套的精品资源,点击获取