easyidp.metashape.Metashape¶
- class easyidp.metashape.Metashape(project_path=None, chunk_id=None, raw_img_folder=None, check_img_existance=True)¶
Metashape 3D 重建项目中每个块的对象
- __init__(project_path=None, chunk_id=None, raw_img_folder=None, check_img_existance=True)¶
初始化 Metashape 类的方法
- 参数:
project_path (str, optional) -- 要打开的 metashape 项目文件,例如 "xxxx.psx",默认值为 None,表示创建一个空类
chunk_id (int or str, optional) -- 要打开的块 ID 或名称(标签),默认值为 None,打开第一个块。
raw_img_folder (str, optional) -- 原始无人机图像文件夹,默认值为 None
check_img_existance (bool) -- 设置为 False 时忽略丢失的照片,适用于仅有少量图像的测试项目,以避免 FileNotFoundError
示例
>>> import easyidp as idp >>> test_data = idp.data.TestData()
Then open the demo Metashape project:
>>> ms = idp.Metashape(test_data.metashape.lotus_psx) <'Lotus.psx' easyidp.Metashape object with 1 active chunks> id label ---- ------- -> 0 Chunk 1
或者您可以创建一个空类,然后打开项目:
>>> ms = idp.Metashape() >>> ms.open_project(test_data.metashape.lotus_psx) <'Lotus.psx' easyidp.Metashape object with 1 active chunks> id label ---- ------- -> 0 Chunk 1
小心
一个 Metashape 项目可能有多个块,每个
easyidp.Metashape项目一次只能处理一个块。ID 前的箭头显示哪个块已被打开
<'multichunk.psx' easyidp.Metashape object with 2 active chunks> id label ---- ------------ -> 1 multiple_bbb 2 miltiple_aaa
Methods
__init__([project_path, chunk_id, ...])初始化 Metashape 类的方法
back2raw(roi[, save_folder])Projects ROIs to raw images using batch matrix operations.
back2raw_crs(points_xyz[, ignore, log])将一个 GIS 坐标 ROI(多边形)投影到所有图像上
back2raw_old(roi[, save_folder])将多个 GIS 坐标 ROI(多边形)投影到所有图像上
change_photo_folder(raw_img_folder[, ...])Change the folder path of raw images
get_photo_position([to_crs, refresh])获取所有照片的中心地理位置(在给定的 CRS 上)
open_chunk(chunk_id[, project_path])切换到其他块,或新项目中的块
open_project(project_path[, chunk_id])打开一个新的 3D 重建项目以覆盖当前项目。
检查原始照片路径的功能
show_roi_on_img(img_dict, roi_name[, img_name])在给定图像上可视化给定 ROI 的特定反向投影结果。
sort_img_by_distance(img_dict_all, roi[, ...])按照片到 ROI 的距离排序 back2raw img_dict 结果的高级包装器
Attributes
crsthe geographic coordinates (often the same as the export DOM and DSM),
<class 'pyproj.crs.crs.CRS'>dom输出的数字正射影像图 (DOM),
easyidp.GeoTiffdsm输出的数字表面模型 (DSM),
easyidp.GeoTiffpcd输出的点云,
easyidp.PointCloudthe folder contains the metashape project (.psx) files
the metashape project (file) name.
被选为easyidp的块(本类只处理Metashape项目中的一个块)
the folder that contains the origial images
项目 / 块名称
项目元信息
该项目是否被激活,(通常用于Metashape),
<class 'bool'>the container for all sensors in this project (camera model),
<class 'easyidp.Container'>, a dict-like object consisted bySensor该项目中所有照片的容器(图像),
<class 'easyidp.Container'>,由Photo组成的类字典对象- back2raw(roi, save_folder=None, **kwargs) dict¶
Projects ROIs to raw images using batch matrix operations.
This is an optimized version of
back2raw()using vectorized numpy operations (einsum) for significant speedup (typically 10-30x).- 参数:
roi (easyidp.ROI | dict) -- The ROI object or dictionary with polygon coordinates. Each ROI should have shape (n_vertices, 3) with CRS coordinates.
save_folder (str, optional) -- Folder to save output JSON and PNG files, by default None.
ignore (str | None, optional) -- Currently not implemented in batch version.
log (bool, optional) -- Currently not implemented in batch version.
- 返回:
Same structure as
back2raw():{roi_name: {photo_name: pixel_coords (n, 2)}}- 返回类型:
dict
备注
Uses point deduplication to minimize redundant calculations.
Batch processes all photos simultaneously using einsum.
Groups photos by sensor for efficient batch calibration.
示例
>>> import easyidp as idp >>> ms = idp.Metashape(project_path) >>> roi = idp.ROI(shapefile_path) >>> roi.get_z_from_dsm(dsm_path) >>> >>> # Optimized batch processing >>> out = ms.back2raw(roi) >>> # Same output structure as ms.back2raw(roi)
参见
back2rawOriginal implementation (non-optimized).
- back2raw_crs(points_xyz, ignore=None, log=False)¶
将一个 GIS 坐标 ROI(多边形)投影到所有图像上
- 参数:
points_hv (ndarray (nx3)) -- 多边形顶点的3D坐标,CRS坐标
ignore (str | None, optional) -- 是否容忍图像外的小部分,详见
easyidp.reconstruct.Sensor.in_img_boundary()。 -None:严格在图像区域内; -x:仅y(垂直)在图像区域内,x可以在图像外; -y:仅x(水平)在图像区域内,y可以在图像外。log (bool, optional) -- 是否打印日志以进行调试,默认值为False
- 返回:
一个字典,键=图像名称,值=像素坐标
- 返回类型:
dict,
示例
数据准备
>>> import easyidp as idp >>> ms = idp.Metashape(test_data.metashape.lotus_psx) >>> dsm = idp.GeoTiff(test_data.metashape.lotus_dsm) >>> ms.crs = dsm.crs >>> plot = np.array([ # N1E1 plot geo coordinate ... [ 368020.2974959 , 3955511.61264302, 97.56272272], ... [ 368022.24288365, 3955512.02973983, 97.56272272], ... [ 368022.65361232, 3955510.07798313, 97.56272272], ... [ 368020.69867274, 3955509.66725421, 97.56272272], ... [ 368020.2974959 , 3955511.61264302, 97.56272272] ... ])
..注意:: 在进行反向投影计算之前,需要指定Metashape项目的CRS(
ms.crs = dsm.crs)然后使用此函数在原始图像上找到先前的ROI位置:
>>> out_dict = ms.back2raw_crs(plot) >>> out_dict["DJI_0478"] array([[ 2.03352333, 1474.90817792], [ 25.04572582, 1197.08827224], [ 311.99971438, 1214.81701547], [ 288.88669685, 1492.59824542], [ 2.03352333, 1474.90817792]])
- back2raw_old(roi, save_folder=None, **kwargs)¶
将多个 GIS 坐标 ROI(多边形)投影到所有图像上
- 参数:
roi (easyidp.ROI | dict) -- 由easyidp.ROI()或字典创建的<ROI>对象
save_folder (str, optional) -- 保存json文件和原始图像上ROI部分的文件夹,默认值为None
ignore (str | None, optional) -- 是否容忍图像外的小部分,详见
easyidp.reconstruct.Sensor.in_img_boundary()。 -None:严格在图像区域内; -x:仅y(垂直)在图像区域内,x可以在图像外; -y:仅x(水平)在图像区域内,y可以在图像外。log (bool, optional) -- 是否打印日志以进行调试,默认值为False
示例
数据准备
>>> import easyidp as idp >>> lotus = idp.data.Lotus() >>> ms = idp.Metashape(project_path=lotus.metashape.project) >>> roi = idp.ROI(lotus.shp, name_field=0) [shp][proj] Use projection [WGS 84] for loaded shapefile [plots.shp] Read shapefile [plots.shp]: 100%|███████████████| 112/112 [00:00<00:00, 2481.77it/s] >>> roi = roi[0:2] >>> roi.get_z_from_dsm(lotus.pix4d.dsm)
然后使用此函数进行反向投影:
>>> out_all = ms.back2raw(roi) { 'N1W1': { 'DJI_0478.JPG': array([[ 14.96726711, 1843.13937997], [ 38.0361733 , 1568.36113526], [ 320.25420037, 1584.28772847], [ 297.16110119, 1859.05913936], [ 14.96726711, 1843.13937997]]) 'DJI_0479': array([...]) ... } 'N1W2': {...} # output of `back2raw_crs()` }
- change_photo_folder(raw_img_folder, check_img_existance=True)¶
Change the folder path of raw images
- 参数:
raw_img_folder (str | dict) -- 包含原始图像文件夹的新文件夹路径。如果类型== str:直接替换根字符串。如果类型== dict:(未实现)例如:{'path/to/flight1/': 'new/path/to/flight1', }
check_img_existance (bool) -- 设置为 False 时忽略丢失的照片,适用于仅有少量图像的测试项目,以避免 FileNotFoundError
- chunk_id¶
被选为easyidp的块(本类只处理Metashape项目中的一个块)
- enabled¶
该项目是否被激活,(通常用于Metashape),
<class 'bool'>
- get_photo_position(to_crs=None, refresh=False)¶
获取所有照片的中心地理位置(在给定的 CRS 上)
- 参数:
to_crs (pyproj.CRS, optional) -- 转换为另一个地理坐标,默认值为None,即项目的CRS
refresh (bool, optional) --
False:使用缓存的结果(如果有),默认值True:重新计算照片位置
- 返回:
字典包含"photo.label":[x, y, z]坐标
- 返回类型:
dict
示例
数据准备
>>> import numpy as np >>> np.set_printoptions(suppress=True) >>> import easyidp as idp >>> lotus = idp.data.Lotus() >>> ms = idp.Metashape(project_path=lotus.metashape.project)
然后使用此函数获取照片在3D世界中的位置:
>>> out = ms.get_photo_position() { 'DJI_0422': array([139.54053245, 35.73458169, 130.09433649]), 'DJI_0423': array([139.54053337, 35.73458315, 129.93437641]), ... }
小心
默认情况下,如果未指定metashape项目的CRS,它将以默认CRS(epsg: 4326)返回 -> (经度, 纬度, 高度),如果需要转换为与DOM/DSM相同的坐标,请先指定CRS
>>> dom = idp.GeoTiff(lotus.metashape.dom) >>> ms.crs = dom.crs >>> out = ms.get_photo_position() { 'DJI_0422': array([ 368017.73174354, 3955492.1925972 , 130.09433649]), 'DJI_0423': array([ 368017.81717717, 3955492.35300323, 129.93437641]), ... }
- label¶
项目 / 块名称
- meta¶
项目元信息
- open_chunk(chunk_id, project_path=None)¶
切换到其他块,或新项目中的块
- 参数:
chunk_id (int or str) -- 要打开的块ID或名称(标签)
project_path (str, optional) -- 要打开的新Metashape项目文件,如“xxxx.psx”,默认值为None,表示在当前Metashape项目内切换
示例
数据准备
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> ms = idp.Metashape(test_data.metashape.multichunk_psx) <'multichunk.psx' easyidp.Metashape object with 4 active chunks> id label ---- -------------- -> 1 multiple_bbb 2 multiple_aaa 3 multiple_aaa_1 4 multiple_aaa_2
然后通过ID或标签从块1切换到块4:
>>> ms.open_chunk('4') # or >>> ms.open_chunk('multiple_aaa_2') >>> ms <'multichunk.psx' easyidp.Metashape object with 4 active chunks> id label ---- -------------- 1 multiple_bbb 2 multiple_aaa 3 multiple_aaa_1 -> 4 multiple_aaa_2
- open_project(project_path, chunk_id=None)¶
打开一个新的 3D 重建项目以覆盖当前项目。
- 参数:
project_path (str, optional) -- 要打开的pix4d项目文件,如“xxxx.psx”,或不带后缀的“xxxx”。
chunk_id (int or str, optional) -- 要打开的块 ID 或名称(标签),默认值为 None,打开第一个块。
示例
>>> import easyidp as idp >>> test_data = idp.data.TestData() >>> ms = idp.Metashape() <Empty easyidp.Metashape object> >>> ms.open_project(test_data.metashape.lotus_psx) <'Lotus.psx' easyidp.Metashape object with 1 active chunks> id label ---- ------- -> 0 Chunk 1
- project_folder¶
the folder contains the metashape project (.psx) files
- project_name¶
the metashape project (file) name.
- raw_img_folder¶
the folder that contains the origial images
- sensors¶
the container for all sensors in this project (camera model),
<class 'easyidp.Container'>, a dict-like object consisted bySensor
- show_photo_folder()¶
检查原始照片路径的功能
- show_roi_on_img(img_dict, roi_name, img_name=None, **kwargs)¶
在给定图像上可视化给定 ROI 的特定反向投影结果。
- 参数:
img_dict (dict) -- 来自back2raw()的反向结果
roi_name (str) -- 要显示的ROI名称
img_name (str) -- 图像文件名,默认值为None,绘制所有可用图像
corrected_poly_coord (np.ndarray, optional) -- 图像上校正的2D多边形像素坐标(如果有),默认值为None
title (str, optional) -- 显示在顶部的图像标题,默认值为None ->
ROI [roi_name] on [img_name]save_as (str, optional) -- 保存输出图形的文件路径,默认值为None
show (bool, optional) -- 是否显示(在jupyter notebook中)或弹出(在命令行中)图形,默认值为False
color (str, optional) -- 多边形线条颜色,默认值为'红色'
alpha (float, optional) -- 多边形透明度,默认值为0.5
dpi (int, optional) -- 生成图形的dpi,默认值为72
示例
>>> img_dict_ms = roi.back2raw(ms)
检查图像"DJI_0479.JPG"上的"N1W1" ROI:
>>> ms.show_roi_on_img(img_dict_ms, "N1W1", "DJI_0479")
检查所有可用图像上的"N1W1" ROI:
>>> ms.show_roi_on_img(img_dict_ms, "N1W1")
有关更多详细信息,请参见 此示例
- sort_img_by_distance(img_dict_all, roi, distance_thresh=None, num=None, save_folder=None)¶
按照片到 ROI 的距离排序 back2raw img_dict 结果的高级包装器
- 参数:
img_dict_all (dict) -- roi.back2raw(...)的所有输出字典,例如 img_dict = roi.back2raw(...) -> img_dict
roi (idp.ROI) -- 您的ROI变量
num (None or int) -- 保留最近的{x}张图像
distance_thresh (None or float) -- 保留距离ROI比此距离更近的图像。
save_folder (str, optional) -- 保存json文件和原始图像上ROI部分的文件夹,默认值为None
- 返回:
与roi.back2raw(...)的输出结构相同
- 返回类型:
dict
示例
在之前的
back2raw()结果中:>>> out_all = ms.back2raw(roi) { 'N1W1': { 'DJI_0478.JPG': array([[ 14.96726711, 1843.13937997], [ 38.0361733 , 1568.36113526], [ 320.25420037, 1584.28772847], [ 297.16110119, 1859.05913936], [ 14.96726711, 1843.13937997]]) 'DJI_0479': array([...]) ... } 'N1W2': {...} # output of `back2raw_crs()` }
图像顺序混乱,在大多数应用情况下,可能只需要1-3张最接近(现实世界中的ROI)的图像,因此提供了此函数进行排序/过滤。
在以下示例中,它过滤了3张相机到现实世界中的ROI距离小于10米的图像:
>>> img_dict_sort = ms.sort_img_by_distance( ... out_all, roi, ... distance_thresh=10, # distance threshold is 10m ... num=3 # only keep 3 closest images ... ) >>> img_dict_sort { 'N1W1': { 'DJI_0500': array([[1931.09279469, 2191.59919979], [1939.92139124, 1930.65101348], [2199.9439422 , 1939.32128527], [2191.19230849, 2200.557026 ], [1931.09279469, 2191.59919979]]), 'DJI_0517': array([[2870.94915401, 2143.3570243 ], [2596.8790503 , 2161.04730612], [2578.87033498, 1886.89058023], [2853.13891851, 1869.99769984], [2870.94915401, 2143.3570243 ]]), 'DJI_0518': array([[3129.43264924, 1984.91814896], [2856.71879306, 2002.03817639], [2838.71418138, 1730.00287388], [3111.73360179, 1713.76233134], [3129.43264924, 1984.91814896]]) }, 'N1W2': { 'DJI_0500': array([[2214.36789052, 2200.35979344], [2221.8996575 , 1940.70687713], [2479.9825464 , 1949.3909589 ], [2472.52171907, 2209.40355333], [2214.36789052, 2200.35979344]]), 'DJI_0517': array([[2849.82108263, 1845.6733702 ], [2577.37309441, 1863.60741328], [2559.80046778, 1592.07656949], [2832.52942622, 1574.92640413], [2849.82108263, 1845.6733702 ]]), 'DJI_0516': array([[2891.61686486, 2542.98979632], [2616.06780032, 2559.41601014], [2598.43900454, 2282.36641612], [2874.23023492, 2266.71552931], [2891.61686486, 2542.98979632]]) } }
或选择最近的一张图像:
>>> img_dict_sort = ms.sort_img_by_distance( ... out_all, roi, ... num=1 # only keep the closest images ... ) >>> img_dict_sort { 'N1W1': { 'DJI_0500': array([[1931.09279469, 2191.59919979], [1939.92139124, 1930.65101348], [2199.9439422 , 1939.32128527], [2191.19230849, 2200.557026 ], [1931.09279469, 2191.59919979]]) }, 'N1W2': { 'DJI_0500': array([[2214.36789052, 2200.35979344], [2221.8996575 , 1940.70687713], [2479.9825464 , 1949.3909589 ], [2472.52171907, 2209.40355333], [2214.36789052, 2200.35979344]]) } }
您可以使用``list(dict.keys())[0]``自动获取图像名称以迭代每个绘图:
for plot_name, plot_value in img_dict_sort.items(): img_name = list(plot_value.key())[0] coord = plot_value[img_name] # or coord = img_dict_sort[plot_name][img_name]