感兴趣区域(ROI)的使用教程
感兴趣区域 (ROI) 会移除用户定义感兴趣区域之外的点,从而缩短捕获时间。ROI 可以是 3D 中的框、相机的 z 值范围,或两者兼而有之。
如果应用程序只需要一部分视野而不是整个场景,那么ROI功能会很有用。例如,如果您想要检测料箱中的零件,相对于针对真个场景进行检测,您的检测算法可能会受益于搜索空间减少的料箱 内部 空间。
将 ROI 定义为框
ROI 框过滤的好处
ROI 框过滤提供以下一种或多种优势:
- 减少捕获时间(相同点云质量)
需要传输、复制和处理的数据更少;通过以下一项或两项操作可以显著提高速度:
性能较低的 GPU (Intel/Jetson)
繁重的点云处理工作(Omni/Stripe、5MP 分辨率、多采集 HDR)
- 更好的点云质量(相同的捕获时间)
可以使用不同的设置;例如:
使用 Stripe/Omni 引擎代替 Phase
使用 Sampling::Pixel 实现更高分辨率
在 HDR 中添加更多采集
- 更便宜的 GPU(相同的捕获时间)
由于需要处理的数据较少,因此您可以使用诸如以下的硬件:
使用Intel/Jetson 代替 Nvidia 独立显卡
- 更便宜的网卡(相同的捕获时间)
由于需要传输的数据较少,您可能不会使网络饱和,从而可以使用例如:
1G 而非 2.5G/10G 网卡
2.5G 而非 10G 网卡
The parameter Settings::RegionOfInterest::Box enables using ROI as a box.
Three points define the base plane of the box and two extents define the height:
这三个点(
Box::PointO、Box::PointA、Box::PointB)在 3D 相机参考系中给出,并定义ROI框的基平面。系统会自动找到第四个点,将基平面绑定到坐标系中并完成矩形的设定。三点依次构成两个向量:点O是向量的原点。
点A定义了从原点生成的第一个向量。
点B定义了从原点生成的第二个向量。
两个范围(
Box::Extents)将基坐标系挤压成一个框。由点 O、点 A 和点 B 定义的向量 OA 和 OB 的叉积给出了范围(extent)的方向。因此,负范围(extent)将沿叉积的相反方向延伸。
ROI盒的示意图:三个点(O、A和B)定义了框的底部平面,并自动选择第四个点来完成矩形。然后可以向上 (+E2) 和向下 (-E1) 拉伸由四个点定义的有界平面以完成框的定义。
备注
ROI盒的基坐标系 没有 被限制为一个角垂直的矩形。因此可以定义一个平行四边形作为底面,并定义一个平行六面体的ROI盒。
小技巧
请遵循以下经验法则来选择三个定义点:
在任意的一个角落选择点O。
选择点A,使点B位于相对于点A 逆时针 方向的位置。
在点A逆时针方向的某个位置选择点B。
这样,范围(extents)将具有朝向相机的正方向。
在 Zivid Studio 中配置 ROI 框
在 Zivid Studio 中创建 ROI 框后,您可以导出 YAML 格式的配置文件,并将其重新加载到您的应用程序中。
const auto settingsFile = "Settings.yml";
std::cout << "Loading settings from file: " << settingsFile << std::endl;
const auto settingsFromFile = Zivid::Settings(settingsFile);
ROI 框示例和表现
机器人拾取示例
这是一个使用低端 PC(搭载 Intel Iris Xe 笔记本电脑集成显卡 和 1G 网卡)进行大量点云处理的示例,其中 ROI 框过滤方法对提升效率很有益处。
想象一下,一个机器人用固定安装的 Zivid 2+ MR130 相机从 600 x 400 x 300 毫米的箱子中拾取物品。为了给机器人留出足够的空间,相机安装在距离箱子顶部 1700 毫米的位置,提供大约 1000 x 800 毫米的视场。当相机安装在这个距离时,大部分视场都在 ROI 之外,因此可以从每一侧裁剪约 20/25% 的像素列/行。从下表可以看出,使用 ROI 框过滤可以显著缩短捕获时间。
Zivid 2 - Presets 预设值 |
采集时间 |
捕获时间 |
||
|---|---|---|---|---|
未设置 ROI |
设置了 ROI |
未设置 ROI |
设置了 ROI |
|
Manufacturing Specular |
0.64 s |
0.64 s |
2.1 s |
1.0 s |
Consumer Goods Quality |
0.90 s |
0.88 s |
5.0 s |
3.0 s |
机器人引导/装配示例
这是一个使用低端PC(配备Nvidia MX 250笔记本 GPU 和 1G 网卡)进行大规模点云处理的例子,在此场景中 ROI 框区域过滤技术极为有益。
在某些机器人引导应用(如钻孔、焊接、涂胶)或装配应用(如插销入孔)中,相对于相机在成像距离下的视场(FOV),感兴趣的区域(ROI)可能非常小。在这种情况下,ROI 往往仅包含点云中 5-10% 的点,利用 ROI 框过滤可以大幅减少数据采集时间(见下表)。
Zivid 2 - Presets 预设值 |
采集时间 |
捕获时间 |
||
|---|---|---|---|---|
未设置 ROI |
设置了 ROI |
未设置 ROI |
设置了 ROI |
|
Manufacturing Specular |
0.65 s |
0.63 s |
1.3 s |
0.7 s |
Manufacturing Small Features |
0.70 s |
0.65 s |
5.0 s |
0.8 s |
深度范围定义的ROI
The parameter Settings::RegionOfInterest::Depth enables to use ROI as a range of z-values from the camera, where points are kept within the following thresholds:
最小深度阈值(
RegionOfInterest::Depth::minValue)最大深度阈值(
RegionOfInterest::Depth::maxValue)
如果场景的前方或后方有需要过滤的点,那么这种方式将会很有用。请注意,z值是基于相机参考系给出的,即垂直于相机方向进行过滤。因此,如果相机垂直安装在您要拍摄的物体上,效果最佳。
ROI API
ROI是 相机设置 的一部分,在Zivid SDK主设置对象下进行设置。因此,它在*当您捕获时*应用,而不是之后应用在点云对象上。
小技巧
ROI 框过滤方法可以减少捕获时间,而深度范围定义的 ROI 则 不会 。
Zivid::Settings settings{
Zivid::Settings::Color{ settings2D },
Zivid::Settings::Engine::stripe,
Zivid::Settings::RegionOfInterest::Box::Enabled::yes,
Zivid::Settings::RegionOfInterest::Box::PointO{ 1000, 1000, 1000 },
Zivid::Settings::RegionOfInterest::Box::PointA{ 1000, -1000, 1000 },
Zivid::Settings::RegionOfInterest::Box::PointB{ -1000, 1000, 1000 },
Zivid::Settings::RegionOfInterest::Box::Extents{ -1000, 1000 },
Zivid::Settings::RegionOfInterest::Depth::Enabled::yes,
Zivid::Settings::RegionOfInterest::Depth::Range{ 200, 2000 },
Zivid::Settings::Processing::Filters::Cluster::Removal::Enabled::yes,
Zivid::Settings::Processing::Filters::Cluster::Removal::MaxNeighborDistance{ 10 },
Zivid::Settings::Processing::Filters::Cluster::Removal::MinArea{ 100 },
Zivid::Settings::Processing::Filters::Hole::Repair::Enabled::yes,
Zivid::Settings::Processing::Filters::Hole::Repair::HoleSize{ 0.2 },
Zivid::Settings::Processing::Filters::Hole::Repair::Strictness{ 1 },
Zivid::Settings::Processing::Filters::Noise::Removal::Enabled::yes,
Zivid::Settings::Processing::Filters::Noise::Removal::Threshold{ 7.0 },
Zivid::Settings::Processing::Filters::Noise::Suppression::Enabled::yes,
Zivid::Settings::Processing::Filters::Noise::Repair::Enabled::yes,
Zivid::Settings::Processing::Filters::Outlier::Removal::Enabled::yes,
Zivid::Settings::Processing::Filters::Outlier::Removal::Threshold{ 5.0 },
Zivid::Settings::Processing::Filters::Reflection::Removal::Enabled::yes,
Zivid::Settings::Processing::Filters::Reflection::Removal::Mode::global,
Zivid::Settings::Processing::Filters::Smoothing::Gaussian::Enabled::yes,
Zivid::Settings::Processing::Filters::Smoothing::Gaussian::Sigma{ 1.5 },
Zivid::Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::Enabled::yes,
Zivid::Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::Strength{ 0.4 },
Zivid::Settings::Processing::Filters::Experimental::ContrastDistortion::Removal::Enabled::no,
Zivid::Settings::Processing::Filters::Experimental::ContrastDistortion::Removal::Threshold{ 0.5 },
Zivid::Settings::Processing::Resampling::Mode::upsample2x2,
Zivid::Settings::Diagnostics::Enabled::no,
};
setSamplingPixel(settings, camera);
std::cout << settings << std::endl;
var settings = new Zivid.NET.Settings()
{
Engine = Zivid.NET.Settings.EngineOption.Stripe,
RegionOfInterest =
{
Box = {
Enabled = true,
PointO = new Zivid.NET.PointXYZ{ x = 1000, y = 1000, z = 1000 },
PointA = new Zivid.NET.PointXYZ{ x = 1000, y = -1000, z = 1000 },
PointB = new Zivid.NET.PointXYZ{ x = -1000, y = 1000, z = 1000 },
Extents = new Zivid.NET.Range<double>(-1000, 1000),
},
Depth =
{
Enabled = true,
Range = new Zivid.NET.Range<double>(200, 2000),
},
},
Processing =
{
Filters =
{
Cluster =
{
Removal = { Enabled = true, MaxNeighborDistance = 10, MinArea = 100}
},
Hole =
{
Repair = { Enabled = true, HoleSize = 0.2, Strictness = 1 },
},
Noise =
{
Removal = { Enabled = true, Threshold = 7.0 },
Suppression = { Enabled = true },
Repair = { Enabled = true },
},
Outlier =
{
Removal = { Enabled = true, Threshold = 5.0 },
},
Reflection =
{
Removal = { Enabled = true, Mode = ReflectionFilterModeOption.Global },
},
Smoothing =
{
Gaussian = { Enabled = true, Sigma = 1.5 },
},
Experimental =
{
ContrastDistortion =
{
Correction = { Enabled = true, Strength = 0.4 },
Removal = { Enabled = true, Threshold = 0.5 },
},
},
},
Resampling = { Mode = Zivid.NET.Settings.ProcessingGroup.ResamplingGroup.ModeOption.Upsample2x2 },
},
Diagnostics = { Enabled = false },
};
settings.Color = settings2D;
SetSamplingPixel(ref settings, camera);
Console.WriteLine(settings);
settings = zivid.Settings()
settings.engine = zivid.Settings.Engine.stripe
settings.region_of_interest.box.enabled = True
settings.region_of_interest.box.point_o = [1000, 1000, 1000]
settings.region_of_interest.box.point_a = [1000, -1000, 1000]
settings.region_of_interest.box.point_b = [-1000, 1000, 1000]
settings.region_of_interest.box.extents = [-1000, 1000]
settings.region_of_interest.depth.enabled = True
settings.region_of_interest.depth.range = [200, 2000]
settings.processing.filters.cluster.removal.enabled = True
settings.processing.filters.cluster.removal.max_neighbor_distance = 10
settings.processing.filters.cluster.removal.min_area = 100
settings.processing.filters.hole.repair.enabled = True
settings.processing.filters.hole.repair.hole_size = 0.2
settings.processing.filters.hole.repair.strictness = 1
settings.processing.filters.noise.removal.enabled = True
settings.processing.filters.noise.removal.threshold = 7.0
settings.processing.filters.noise.suppression.enabled = True
settings.processing.filters.noise.repair.enabled = True
settings.processing.filters.outlier.removal.enabled = True
settings.processing.filters.outlier.removal.threshold = 5.0
settings.processing.filters.reflection.removal.enabled = True
settings.processing.filters.reflection.removal.mode = (
zivid.Settings.Processing.Filters.Reflection.Removal.Mode.global_
)
settings.processing.filters.smoothing.gaussian.enabled = True
settings.processing.filters.smoothing.gaussian.sigma = 1.5
settings.processing.filters.experimental.contrast_distortion.correction.enabled = True
settings.processing.filters.experimental.contrast_distortion.correction.strength = 0.4
settings.processing.filters.experimental.contrast_distortion.removal.enabled = False
settings.processing.filters.experimental.contrast_distortion.removal.threshold = 0.5
settings.processing.resampling.mode = zivid.Settings.Processing.Resampling.Mode.upsample2x2
settings.diagnostics.enabled = False
settings.color = settings_2d
_set_sampling_pixel(settings, camera)
print(settings)
Apply ROI box as post-processing
The ROI box filter can also be applied as a post-processing step on an already-captured point cloud, using PointCloud::maskByRegionOfInterest() (in-place) or PointCloud::maskedByRegionOfInterest() (returns a new copy).
This avoids the need to recapture when the ROI changes.
See the ROIBoxViaArucoMarker and ROIBoxViaCheckerboard samples for examples.
std::cout << "Creating a masked version of the point cloud based on ROI" << std::endl;
const auto roiPointCloud = pointCloud.maskedByRegionOfInterest(roiSettings);
std::cout << "Displaying the ROI-filtered point cloud" << std::endl;
visualizeZividPointCloud(roiPointCloud);
This is particularly useful in robot-mounted setups, where a workspace ROI box can be defined once in the robot base frame and applied to every capture regardless of camera viewpoint.
The StitchUsingRobotMountedCamera sample demonstrates this by transforming each point cloud to the base frame and then masking it with a fixed workspace ROI box:
const auto smallWorkspaceRoiBox = Zivid::Settings::RegionOfInterest::Box{
Zivid::Settings::RegionOfInterest::Box::Enabled::yes,
Zivid::Settings::RegionOfInterest::Box::PointO{ -150, 300, 50 },
Zivid::Settings::RegionOfInterest::Box::PointA{ -150, 600, 50 },
Zivid::Settings::RegionOfInterest::Box::PointB{ 150, 300, 50 },
Zivid::Settings::RegionOfInterest::Box::Extents{ -75, 40 },
};
auto pointCloud = frame.pointCloud();
pointCloud.transform(baseToCameraTransform);
pointCloud.maskByRegionOfInterest(workspaceRoiBox);
var smallWorkspaceRoiBox = new Zivid.NET.Settings.RegionOfInterestGroup.BoxGroup
{
Enabled = true,
PointO = new Zivid.NET.PointXYZ { x = -150, y = 300, z = 50 },
PointA = new Zivid.NET.PointXYZ { x = -150, y = 600, z = 50 },
PointB = new Zivid.NET.PointXYZ { x = 150, y = 300, z = 50 },
};
smallWorkspaceRoiBox.Extents = new Zivid.NET.Range<double>(-75, 40);
var pointCloud = frame.PointCloud;
pointCloud.Transform(baseToCameraTransform);
pointCloud.MaskByRegionOfInterest(workspaceRoiBox);
small_workspace_roi_box = zivid.Settings.RegionOfInterest.Box(
enabled=True,
point_o=[-150, 300, 50],
point_a=[-150, 600, 50],
point_b=[150, 300, 50],
extents=(-75, 40),
)
point_cloud = frame.point_cloud()
point_cloud.transform(base_to_camera_transform)
point_cloud.mask_by_region_of_interest(workspace_roi_box)
教程
查看以下教程,了解如何使用ROI API的示例。
有关性能信息,请查看 Region of Interest(感兴趣区域) 。
版本历史
SDK |
变更 |
|---|---|
2.18.0 |
Added |
2.14.0 |
在 Zivid Studio 中,将操纵器添加到 ROI 框。 |
2.12.0 |
ROI 框过滤可减少捕获时间。 |
2.9.0 |
添加了ROI API。 |