1. 先搞清楚 Metashape 的 region 到底是个什么存在
对于经常用 Metashape 做摄影测量处理的朋友来说,region(处理区域)这个概念其实很微妙。它不像照片对齐、密集点云生成那样有直观的中间结果,更像是一个隐形的边界框,悄悄影响着后期一大堆计算的范围。很多人跑了几百个项目,可能都没有手动碰过它,直到某天发现密集点云只重建出了局部、DEM 边缘缺了一块、或者正射影像的范围完全不符合预期,才意识到是这个"看不见的盒子"在捣鬼。
简单说一下我的理解:Metashape 里的一个 chunk(项目块)中包含相机、点云、模型、DEM、正射影像等产物,而 region 就是一块用旋转立方体定义的"感兴趣区"。它的核心作用就是告诉软件:你只需要处理这个立方体内部的数据。所有需要消耗算力的操作,比如密集点云匹配、DEM 生成、正射影像镶嵌,都会优先考虑 region 范围。范围之外的影像即便参与了空三,也不一定参与最终产物计算。
这个 region 在 Metashape 的 Python API 里,对应的是Metashape.Region对象。它有三个核心属性:
center:Region 中心点的坐标,类型是Metashape.Vector,三维向量。size:Region 在三个轴向上的尺寸,同样是Metashape.Vector,三维向量。rotation:Region 的旋转矩阵,类型是Metashape.Matrix,用来描述这个立方体相对世界坐标系的姿态。
把这三点拆开看,其实就是一个完整的空间包围盒模型:一个中心点,加上三个方向上的边长,再加上一个旋转姿态。想通过脚本改变region.center,本质上就是在操作这个三维包围盒的位置。
这里要注意的是,region 并不只是简单的 Axis-Aligned Bounding Box(AABB,轴对齐包围盒),而是一个 Oriented Bounding Box(OBB,有向包围盒)。也就是说它可以旋转,不一定和坐标轴平行。这一点在实际处理倾斜摄影、带状航线时特别重要。你拍了一条沿河道的测线,场景是不规则的长条形,这时候一个能旋转的 region 才是合理的裁剪边界。
但问题也来了:Metashape 图形界面里虽然提供了Resize Region和Rotate Region工具,可以手动拖动调整区域,但手动调整的问题在于不够精确,而且难以批量处理。如果是几十上百个 chunk 的项目,一个一个手动拖,耗时不说,还很容易把各 chunk 的 region 搞得各不相同,导致后期合并时出现范围不一致的麻烦。所以用 Python 脚本直接改region.center,就成了解决这类问题的高效手段。
这篇内容就是专门给需要用代码控制 Metashape 处理范围的朋友写的。无论你是做航测内业、三维重建流程自动化,还是想把自己手里重复性的区域框选工作交给脚本完成,理解region.center的修改方式都能帮你省下大量时间。
2. 周边概念不能少:center、size、rotation 之间的连带关系
很多人在写脚本改center的时候,习惯性只复制region.center = new_center这一行,然后发现运行报错,或者改了之后效果不对。原因就在于没有理解center、size、rotation三者的连带关系。
2.1 三者共同定义一个完整的空间盒子
Region对象在 Metashape 内部被定义为一个由中心点、尺寸、旋转矩阵共同确定的立方体。这就好比我们在三维软件里面创建一个长方体:先确定它的位置(对应 center),再确定长宽高(对应 size),最后确定它的摆放姿态(对应 rotation)。光改位置,不改姿态和尺寸,盒子是被平移了,但如果你对这个盒子的期望不仅仅是"移动",而是"重新生成一个符合需求的新边界",那就必须把三个属性一起策划好。
在代码层面,Metashape.Region允许我们分别读写这三个字段:
import Metashape chunk = Metashape.app.document.chunk region = chunk.region # 查看当前值 print("Center:", region.center) print("Size:", region.size) print("Rotation:", region.rotation)注意,print(region.rotation)出来的是一个 3x3 矩阵,看起来可能是这样:
Matrix([[0.8660254037844387, -0.4999999999999998, 0.0], [0.4999999999999998, 0.8660254037844387, 0.0], [0.0, 0.0, 1.0]])这个矩阵的含义就是旋转 30 度之类的姿态信息。它与你定义的center坐标结合,决定了整个盒子的方向。
2.2 坐标系统与测量单位
另一个容易踩坑的地方是坐标系。Metashape 的 region 属性默认使用 chunk 的局部坐标(通常是chunk.transform定义的坐标系),而不是地理坐标系(比如 WGS84 / UTM)。所以在写脚本的时候,你要先搞清楚 chunk 当前使用的坐标系是什么。
如果你导入的照片带有 POS 信息(比如无人机 DJI 的经纬度高程),Metashape 在对齐照片后,会生成一个chunk.transform.matrix,将局部坐标转换到地理坐标。而region.center返回的坐标是在这个转换之后的空间里的坐标,单位是米(如果当地坐标系用米制),但是你打印出来的数值通常和你在Reference面板里看到的地理坐标不一定一致,因为还有一个从地理坐标到投影坐标的换算关系。
我经常看到的错误就是:有人直接在脚本里写region.center = Metashape.Vector([经纬度, 经纬度, 高程]),结果运行不报错,但 region 飞到了十万八千里外。原因就是他使用了经纬度坐标,而 region 需要的是投影坐标(或 chunk 的本地坐标)。解决办法呢,要么先把经纬度通过Metashape.CoordinateSystem.transform转成投影坐标,要么用照片的chunk.crs先转换:
crs = chunk.crs # 例:从 WGS84 经纬度转为本地投影坐标 local_coord = crs.project(Metashape.Vector([lon, lat, alt])) region.center = local_coord2.3 修改 center 不会重置 rotation
这一点从代码层面看,region.center的赋值仅仅改变位置。如果当前 region 的 rotation 是歪的,那么你平移之后它依然歪着。这在某些场景下没有问题,但如果你是想用一个正正经经的、平行于坐标轴的盒子去框住目标区域,就得连rotation一起重置。一个常用的做法是把它设置为单位矩阵:
region.rotation = Metashape.Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])同时按需求设定尺寸:
region.size = Metashape.Vector([x_len, y_len, z_len])这时候再设置 center,你就拥有一个完全可控的正交包围盒了。
我自己的习惯是,在批量脚本里永远把这三个值一起处理。哪怕当前只需要移动 center,我也会先把 rotation 打了单位阵,size 显式设置一遍。原因很简单:脚本的可重复性。对于处理几百个 chunk 的情况,你不能保证每个 chunk 的 region 初始状态是整齐的,统一设置才能保证输出的一致。
3. 为什么要改 region.center:四个典型场景
很多基础教程只会告诉你"可以改 center",但不会告诉你什么时候需要改。这里我根据自己的项目经验总结几个高频场景,帮助大家判断自己是否用得上。
3.1 场景一:密集点云匹配只需要处理局部区域
拍摄一个大型场景时,如果照片数量多、重叠度大,密集点云匹配是非常消耗算力和时间的操作。有时候我们并不需要全场景的高密度点云,只需要某个重点部位,比如一栋古建筑的核心区域,或者一条道路的关键交叉口。这时候缩小 region 范围,并把 center 移到目标位置的中央,就能让 Metashape 只对 region 内部进行密集匹配。
这样做的好处有两个:一是时间节省明显,原本跑三四个小时的密集匹配可能缩短到几十分钟;二是噪点减少,因为远处的、无关的地物不再参与匹配,点云质量更干净。当然,前提是照片在目标区域内的覆盖足够。
3.2 场景二:控制 DEM 和正射影像的生成范围
Metashape 在生成 DEM 和正射影像时,默认的边界通常是取 chunk 内容的包围盒。如果数据中存在一些飞散的、低质量的匹配点,或者不想要边缘多余的植被、建筑,就可以通过移动 center 同时调整 size 来裁剪输出范围。这里需要提醒一下,region 只是处理范围,最终导出边界还会受导出对话框中的region选项影响。在 Python 脚本里,只要导出的时候 region 设定正确,导出的结果就受控。
3.3 场景三:多 chunk 数据范围对齐
在多区块项目中,常常会把一个大场景拆成多个 chunk 分别处理。在合并生成最终成果之前,我们希望所有 chunk 的处理范围保持一致。如果每个 chunk 的照片覆盖略有偏移,默认 region 就会不同。这时候写一个循环脚本,将各 chunk 的 center 设成同一个坐标,size 设成同样大小,就能保证最终合并后的成果范围一致。
3.4 场景四:分块处理与拼接
还有一个比较高级的用法,就是完全自定义分块。比如你把一个带状区域分成三块处理,第一块 region 中心在 A 点,第二块在 B 点,第三块在 C 点,每块独立生成点云,最后在外部软件里拼接。通过脚本修改 center,你可以精确控制每一块的位置,而不是依赖软件自动计算出来的 region。
4. 实操:用 Python 改 region.center 的完整步骤
下面我想从一个最简洁的示例开始,逐步加注释和错误处理,帮助你把脚本直接用起来。
4.1 环境准备与基本获取
首先确保 Metashape 的 Python API 可用。Metashape 自带 Python 3 环境,你可以直接在 Tools > Python 里打开 Python 控制台,也可以用命令行调用 metashape.exe 执行脚本。控制台方式最直观,适合调试:
import Metashape doc = Metashape.app.document chunk = doc.chunk print("当前 chunk 名称:", chunk.label) print("region.center 当前值:", chunk.region.center)这里要注意,如果当前没有打开文档,doc.chunk可能会报错。建议加一个判断:
if doc.chunk is None: raise Exception("当前文档没有 chunk,请先打开项目或新建 chunk")4.2 直接修改 center 的两种方式
第一种方式是直接给region.center赋值一个新的Vector:
chunk.region.center = Metashape.Vector([10.0, 20.0, 30.0])这种方式要求你明确知道目标中心在 chunk 坐标系下的坐标。如果你只是想把中心沿某个方向移动一段距离,可以先读取当前 center,加上偏移量再写回:
center = chunk.region.center offset = Metashape.Vector([5.0, -3.0, 0.0]) # 向 x 方向移动5米,y方向移动-3米 new_center = center + offset chunk.region.center = new_center这个方法比较直观,但要注意:如果你的 chunk 有地理参考,center 是在投影坐标系的,offset 的单位和坐标系的单位一致(通常是米)。在某些特殊坐标系下,可能不是米制,比如度分秒,这时你加的 offset 就会变得毫无意义。所以我在有地理参考的 chunk 上,习惯先把坐标转换到“目标坐标系里的米制投影坐标”再处理。
4.3 一个相对稳妥的设置方法:连带 size 和 rotation
我更推荐这种写法,以免后续处理出现意外:
chunk.region.center = Metashape.Vector([100.0, 200.0, 50.0]) chunk.region.size = Metashape.Vector([80.0, 60.0, 40.0]) chunk.region.rotation = Metashape.Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])因为如果只设置 center,而 size 或 rotation 是历史遗留的异常值,region 可能变成一个畸形盒子,后续处理范围完全不是你预期的。统一设置之后,你就是自己画了一个俯视图矩形、高度上严格的盒子。
4.4 从地理坐标转换为本地坐标再设置
假设你有一份目标中心经纬度坐标,例如[116.3913, 39.9075, 50](海拔50米),想把 region.center 设到这个位置。那么你需要这样做:
import Metashape chunk = Metashape.app.document.chunk crs = chunk.crs if crs is None: # 没有地理坐标系时,直接用局部坐标 chunk.region.center = Metashape.Vector([116.3913, 39.9075, 50]) else: # 经纬度在高程方向有时需要额外的地理坐标转换 point_geo = Metashape.Vector([116.3913, 39.9075, 50]) point_local = crs.project(point_geo) chunk.region.center = point_local不过要注意,crs.project需要输入地理坐标系坐标,且要符合该 crs 的坐标系定义。对于 WGS84,输入经度、纬度、椭球高(或海拔,取决于设置)。如果高程基准不一致,结果会有些偏差。更稳妥的做法是直接从参考面板中读取一个已经验证过的控制点坐标。比如你有一个 GCP 的坐标,那么你可以在 Reference panel 选中某一行,右键导出坐标,再作为中心输入。但那样就失去了自动化的意义。我的做法是先用一个小工具测试一个已知点的转换是否正确,再批量使用。
4.5 加入保存与提示
修改完 region 后,如果脚本在大量 chunk 上运行,可以给用户一些反馈:
import Metashape doc = Metashape.app.document for chunk in doc.chunks: chunk.region.center = Metashape.Vector([x_val, y_val, z_val]) chunk.region.size = Metashape.Vector([x_size, y_size, z_size]) chunk.region.rotation = Metashape.Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) print("已修改 chunk:", chunk.label)5. 结合真实坐标的脚本实例:某跨场景重建项目的处理
这里我想给一个相对完整的脚本例子,背景是一个虚构的跨场景重建项目。我们有一条长约 1.2 公里的带状区域,分成了 4 个 chunk 处理,每个 chunk 的范围和大小都有略微差异。为了保证最终拼接效果,我要把四个 chunk 的 region 统一设置为一个矩形范围:中心点位于(500,300,25),长向 600 米,宽向 200 米,高度 50 米,并且水平放置。脚本如下:
import Metashape doc = Metashape.app.document target_center = Metashape.Vector([500.0, 300.0, 25.0]) target_size = Metashape.Vector([600.0, 200.0, 50.0]) target_rot = Metashape.Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) for i, chunk in enumerate(doc.chunks): if chunk is None: continue chunk.region.center = target_center chunk.region.size = target_size chunk.region.rotation = target_rot print("Chunk {}: region.center -> {}".format(chunk.label, chunk.region.center)) print("Chunk {}: region.size -> {}".format(chunk.label, chunk.region.size))这个脚本在控制台直接跑就行。如果要在命令行模式跑,注意保存工程路径:
doc.save(path)因为修改完 region 后如果不保存,关掉软件就白干了。血的教训,我之前写批量脚本忘掉保存,跑完了去关软件,第二天打开项目发现 region 根本没变,花了半天才想起来是没保存。
当然,在实际项目中,这四个 chunk 可能用的是不同的地理参考坐标系。如果是这样,你直接给同一个固定坐标是不对的。解决办法是,先把中心坐标从某一个 chunk 的坐标系转换到另一个 chunk 的坐标系。一个典型的做法是:
# 以第一个 chunk 的坐标系为基准 base_chunk = doc.chunks[0] base_crs = base_chunk.crs for chunk in doc.chunks: if chunk.crs is None: continue # 将基准坐标转为地理坐标 point_geo = base_crs.unproject(target_center) # 再转为当前 chunk 的本地坐标 point_local = chunk.crs.project(point_geo) chunk.region.center = point_local chunk.region.size = target_size # size 是米制长度,一般不受投影影响,但如果投影变形大则需注意 chunk.region.rotation = target_rot这里有个问题:target_size在米制坐标系下是长度,像 UTM 这种投影在短距离内形变很小,可以直接用。如果用的是某些大比例尺地方坐标系,可能需要根据比例因子换算,但绝大多数无人机摄影测量项目用 UTM/高斯投影都没问题。
6. 常见问题排查:改完 center 后效果不对怎么办
我在实际使用中踩过不少坑,这里整理成速查表,希望对大家有帮助。
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 运行脚本不报错,但 region.center 没变化 | 没有保存工程文档,或修改了错误的 chunk | 检查doc.chunk和doc.chunks的关系,运行后立即doc.save() |
| center 设置成经纬度,region 飞到了奇怪的位置 | 把地理坐标直接赋值给了 region.center | 先用chunk.crs.project()转换为投影坐标 |
| 显示的单位看起来不像米 | chunk 使用的是未知坐标系或局部坐标系 | 检查chunk.crs定义,确认单位;必要时输出chunk.transform.matrix来看整体变换 |
| region 变成一个个点或一条线 | size 设置为 0 或极小值 | 确保 size 的三个分量都大于 0,且足够覆盖目标区域 |
| region 旋转后裁剪范围不对 | rotation 矩阵不正确,或没有和 size 匹配 | 使用单位矩阵 I 作为 rotation,再显式设置 size |
| 用图形界面查看 region 没有变化,但脚本输出正确 | Metashape 视图缓存未刷新 | 执行完脚本后,手动旋转或缩放视图,或者重新运行Reset View相关命令;也有可能是多窗口未刷新 |
| 批量处理时部分 chunk 设置成功,部分失败 | 某个 chunk 没有相机、未对齐,或没有 region | 加判断if chunk.region is not None:再操作 |
我再特别提两个大家容易忽略的细节:
6.1 center 和 size 联合作用下的“覆盖范围”
很多人以为只要设置 center,region 就会自动适应所有内容,其实不然。如果你的 size 设置太小,即使 center 在目标位置,很多点云还是会被裁剪掉。如果你只设置了 center 但 size 很大,计算结果会比预期大得多。所以合理的做法是根据点云或兴趣区域的范围先估算一个 size,再放置 center。估算方法很简单:先打印当前的 region 看看默认值:
print("当前 region size:", chunk.region.size)然后用默认 size 作为参考,只挪 center,不改变尺寸,往往是最安全的操作。按我的经验,80% 的场景只需要挪 center,不需要动 size。
6.2 是否需要用chunk.resetRegion()来重置
Metashape API 中有一个便捷方法叫做chunk.resetRegion(),它会把 region 重置为包含所有对齐照片的范围。如果你发现修改 center 前 region 已经乱了,先调用这个方法恢复到一个合理初始状态,再设置 center 效果更好:
chunk.resetRegion() # 之后再设置自己的 region chunk.region.center = Metashape.Vector([x, y, z])这个方法特别适合那种你花了很多时间手动调 region,又调乱了,想用脚本全部重来的场景。但注意,resetRegion()会覆盖你的 size 和 rotation,所以顺序是先 reset,再赋值。
7. 进阶技巧:把 region.center 和相机位置联动起来
前面说到的都是手动指定坐标,但还有一类需求更灵活:把 region.center 设置到相机或者某些特征点的中心位置。比如你想把处理区域聚焦在所有照片的平均位置,或者某个特定航带的中点。
7.1 平均相机位置作为 center
无人机拍摄时,所有相机位置的平均点通常能代表场景的中心。通过脚本可以这样算:
import Metashape chunk = Metashape.app.document.chunk camera_positions = [] for camera in chunk.cameras: if camera.transform: pos = camera.center # 注意:camera.center 是相机中心坐标 camera_positions.append(pos) if camera_positions: avg = Metashape.Vector([sum(p[0] for p in camera_positions) / len(camera_positions), sum(p[1] for p in camera_positions) / len(camera_positions), sum(p[2] for p in camera_positions) / len(camera_positions)]) chunk.region.center = avg这里有个细节:camera.center返回的是相机在 chunk 坐标系下的位置。如果 chunk 有地理参考,这个坐标也是投影坐标,可以直接用于 region.center。不过如果你想用地理坐标,就需要再转换一次。
另外要注意,如果有些照片没有完成对齐,camera.transform可能是 None,所以最好加个判断:
for camera in chunk.cameras: if camera.transform is None: continue pos = camera.center camera_positions.append(pos)我做过一个项目,照片数量两千多张,中间掺杂了几十张没对齐的照片,如果不加过滤,平均中心会被拉偏,region 就框不准了。
7.2 把 center 移动到指定标注点或 GCP
如果你的项目里有地面控制点,可以通过名称找到它的坐标,并设置为 region.center。举个例子:
for marker in chunk.markers: if marker.label == "target_center": chunk.region.center = marker.position break这里marker.position是 marker 在 chunk 坐标系下的坐标,可以直接用。这个技巧特别适合那种把固定标志点设为项目中心——比如用 RTK 测量的某个特征点作为重建核心区中心。
7.3 配合缓冲区调整 center
有时候想让 region 的中心稍微偏离特征点,比如当目标物不在照片覆盖中心,而在边缘。我们可以先找到特征点坐标,再根据航线方向偏移一定距离。一个简单实现:
new_center = marker.position + Metashape.Vector([buffer_x, buffer_y, 0]) chunk.region.center = new_center这种偏移计算很简单,但务必要根据实际坐标方向和尺寸来定 buffer,不然很容易把 region 的中心移到覆盖范围以外,导致区域边缘缺数据。
8. 批处理与自动化流程中的 region.center 管理
如果你已经在用脚本批量处理大量数据,那么 region.center 的自动化管理就是一个不容忽视的环节。我见过不少自动化流程,照片导入、对齐、建密集点云全部脚本化,但偏偏在 region 这一块留了手动步骤,导致整条产线在中间断了一下。下面聊聊怎么把 region 调整也纳入自动流程。
8.1 多 chunk 统一处理示例
对于每个 chunk,在生成密集点云之前,统一把 region 按照预设范围设置好,这是最稳妥的。示例:
import Metashape doc = Metashape.app.document for chunk in doc.chunks: if chunk is None: continue if not chunk.cameras: continue chunk.resetRegion() center = chunk.region.center # 先拿到默认中心 # 这里做一个简单的统一偏移 chunk.region.center = center + Metashape.Vector([10.0, 10.0, 0.0]) # 也可以直接改成你手工确认过的坐标 doc.save()实际上,如果只是做统一偏移,最稳的初始中心就是 resetRegion 后的 center。因为每个 chunk 的默认中心就是其数据范围的中心,你在此基础上做偏移,不需要考虑坐标参考系的额外转换。
8.2 从文件读取坐标批量设置
有些时候,你的坐标预先存在 CSV 文件里,比如:
chunk_name, x, y, z chunk_001, 500, 300, 25 chunk_002, 520, 310, 28用 Python 读取并设置,非常方便:
import csv import Metashape doc = Metashape.app.document chunks_by_label = {chunk.label: chunk for chunk in doc.chunks} with open("region_centers.csv", "r") as f: reader = csv.DictReader(f) for row in reader: label = row["chunk_name"] if label in chunks_by_label: chunk = chunks_by_label[label] chunk.region.center = Metashape.Vector([ float(row["x"]), float(row["y"]), float(row["z"]) ]) print("已设置", label)这种方式在实际生产环境中太常见了。比如你有一个测区范围表,或每块的任务规划信息,直接导入脚本即可完成批量 region 调整,全程不需要图形界面参与。
8.3 自动判断范围(根据点云或 sparse cloud)
如果你不想手动输入坐标,而是希望 region.center 自动适配某些数据范围,可以借助 sparse cloud 或 dense cloud 的坐标计算。比如,让 region.center 位于 sparse cloud 的中心:
cloud = chunk.point_cloud if cloud is not None: points = cloud.points n = len(points) if n > 0: sum_x, sum_y, sum_z = 0.0, 0.0, 0.0 # 注意:直接遍历所有点可能非常慢,项目大时建议抽样 step = max(1, n // 10000) for i in range(0, n, step): p = points[i].coord sum_x += p[0] sum_y += p[1] sum_z += p[2] center = Metashape.Vector([sum_x / (n // step), sum_y / (n // step), sum_z / (n // step)]) chunk.region.center = center这个思路虽然简单,但要注意性能问题。上百万个点全部遍历会卡顿很久,所以用抽样步长限制在一万次以内,兼顾速度和精度。这种方法不需要知道具体坐标,完全自适应,适合做动态管线。
8.4 应用在模型重建中的注意点
当 region.center 被移动到新的位置时,region 范围有可能超出照片覆盖范围,这时候生成的密集点云只覆盖了 region 与照片重叠的部分,其他部分会留下空白。所以在自动流程中,建议在设置 center 后打印出当前 region 范围,并和 chunk 中的相机位置做比对,确认没有明显偏差。
一个简单的辅助函数:
def region_info(chunk): c = chunk.region.center s = chunk.region.size return "center: {}, size: {}".format(c, s)把每个 chunk 的 region 信息写进日志文件,这样即使后续结果有问题,也能回溯检查是哪一步设置错了。
9. 版本兼容性和脚本稳定性建议
Metashape 的 Python API 在不同版本之间有一些细微差别,特别是老版本 1.x 和较新的 2.x 之间,部分接口可能改名或改变了默认行为。以chunk.region为例,1.x 版本已经存在,2.x 也保留。但听说在更早的版本(比如 1.0)里,region 可能没有开放给脚本,直到 1.1 之后才稳定。
我目前实际验证过的版本范围是 1.5 到 2.1,在这几个版本中region.center的读写方式基本一致。不过建议仍然在脚本开头做一次版本检测:
import Metashape print("Metashape Version:", Metashape.app.version)如果出现 API 变更,官方文档是最终的参考。不过文档里关于 region 的说明并不详尽,很多细节还是靠实操摸索。
另外,在脚本执行时,如果 Metashape 正在后台执行其他任务(比如正在对齐照片),修改 region 可能会引起冲突。稳妥的做法是在空闲状态执行,或者在新的 Python 控制台里单独运行,避免与 UI 操作并发。
我也试过在批处理脚本里面直接调用Metashape.app.document.save(),保存时会卡一会儿。对于大项目,保存几十上百兆的工程文件,耗时可能几秒到几十秒,所以如果你处理的是大量 chunk,建议每处理完几个 chunk 保存一次,而不是最后一次性保存,以免中途出错丢了进度。
10. 结尾:我踩过的一次坑
最后分享一下我自己的一个教训。有一回处理某个跨场景重建项目,需要在密集匹配之前把所有 chunk 的 region 统一。我当时图省事,只在循环里写了:
chunk.region.center = Metashape.Vector([x, y, z])没有重置 rotation 和 size。结果是,由于每个 chunk 的默认 region 大小不同,有些 chunk 的 region 变得特别大,有些又特别小,密集匹配的结果参差不齐,后面融合模型的时候,不同 chunk 之间出现了明显裂缝。后来我老老实实地在脚本里把 size 和 rotation 一起设置,重新处理,才解决了问题。
还有一次,我在有地理参考的 chunk 里直接把经纬度赋值给了 center,结果 region 跑到了非洲某处(纬度和经度数字在投影坐标系里的含义完全变了),整整废了半天时间才发现。所以在这里认真跟大家说一句:处理 region 前,先确认坐标系;设置 region 时,三个属性一起考虑;跑完脚本后,记得保存工程。
如果你现在的项目里也遇到了 region 范围不对、批量处理需要统一范围、或者自动化流程卡在手动改 region 这一步,不妨照着上面的思路去写一个脚本。改 region.center 本身并不复杂,但把它用对、用好,确实能让你的 Metashape 处理效率提升一个台阶。