2D+3D捕获策略
如果您的应用同时需要2D和3D数据,那么您可以参考本教程。
我们解释并强调了不同的2D-3D捕获方法的优缺点,阐明了一些限制,并解释了它们如何影响循环时间。我们也谈到了使用外部光源和使用内部投影仪来拍摄2D图像的区别。
- 2D数据
RGB图像
- 3D数据
获取2D数据有两种不同的方式:
单独通过
camera.capture2D(Zivid::Settings2D or Zivid::Settings ).imageRGBA_SRGB()获取,请参阅 2D图像捕获流程 。作为 2D3D 捕获
frame = camera.capture2D3D(Zivid::Settings)的一部分:frame.pointCloud().copyImageRGBA_SRGB()。这确保了 2D 和 3D 数据之间的 1:1 映射。frame.frame2D().imageRGBA_SRGB()。这和你单独捕获 2D 图像是一样的。
使用哪一种方式来获取2D数据取决于您的要求。
不同的场景会导致不同的权衡。我们首先根据您需要的数据对其进行细分。然后我们将讨论不同场景下捕获速度与图像质量的权衡。
关于外部光源
Before we go into the different strategies we have to discuss external light. The ideal light source for a 2D capture is strong and diffuse because this limits the blooming effects. With the internal projector as the light source, the blooming effects are almost inevitable. Mounting the camera at an angle significantly reduces this effect, but still an external diffuse light source is better. External light introduces noise in the 3D data, so one should ideally turn the external light off during 3D capture.
除了减少光晕效应外,高照度的外部光源还可以消除由环境光变化引起的曝光变化。环境光变化的典型来源有:
日光变化(白天/黑夜、云等)
开门和关门
顶灯打开和关闭
备注
、Zivid 3 和 Zivid 2+R 对环境光的变化具有很强的抗干扰能力。
Zivid 2+ M60/M130/L110 和 Zivid 2 的注意事项
这些曝光变化对3D和2D数据的影响不同。2D数据中曝光变化的影响取决于所使用的检测算法。如果在2D中执行分割,这些变化可能会,也可能不会影响分割性能。对于点云,您可能会发现由于噪声的变化而导致点云完整性的变化。
这就引出了一个问题:我们是否应该使用相机的投影仪来捕获2D图像?
查看 优化彩色图像 了解有关此主题的更多信息。
2D数据先于3D数据
如果您在2D中执行分割,然后确定您的抓取位姿,那么您需要在获取3D之前得到2D数据。获取2D数据的最快方法是使用单独的2D捕获。因此,如果您在使用3D数据之前就需要使用2D数据,那么您应该先执行单独的2D捕获。
警告
在 2D 和 3D 捕获之间切换时,可能需要重新配置相机。这会导致 2D+3D 捕获时间增加,因为 2D+3D 捕获是连续进行的。具体如下:
如果可能,请将 2D 采集的光圈值设置为与 3D 采集相同。此建议不适用于 Zivid 3,因其光圈是固定的。
考虑在 2D 和 3D 中使用相同的采样设置,请参阅 Sampling(采样)- 2D 和 Sampling(采样) - 3D 。
切换采样设置的惩罚时间为 35ms。
在 3D 中使用低分辨率的收益通常大于损失,特别是对于具有挑战性的场景。
以下代码示例展示了您可以如何:
捕获2D图像
使用2D数据和并行执行3D捕获
const auto frame2dAndCaptureTime = captureAndMeasure2D(camera, settings2D);
std::future<Duration> userThread =
std::async(std::launch::async, useFrame<Zivid::Frame2D>, std::ref(frame2dAndCaptureTime.frame));
const auto frameAndCaptureTime = captureAndMeasure3D(camera, settings2D3D);
const auto processTime = useFrame(frameAndCaptureTime.frame);
const auto processTime2D = userThread.get();
下面显示了实际的基准数字。您会在页面底部找到更详细的表格。
2D数据作为如何使用3D数据的一部分
在这种情况下,我们不必在访问 3D 数据之前先访问 2D 数据。因此,我们只需关心整体速度和质量。
速度
为了达到最佳速度,我们应该避免切换惩罚。
Zivid 3 没有可调节光圈,但对于其他相机,请保持 2D 采集的光圈与 3D 采集的光圈相同。
在 2D 和 3D 中使用相同的采样设置,请参阅 Sampling(采样)- 2D 和 Sampling(采样) - 3D 。
切换采样设置的惩罚时间为 35ms。
在 3D 中使用低分辨率的收益通常大于损失,特别是对于具有挑战性的场景。
2D图像质量
为了获得最佳的 2D 质量,请根据您的需求调整 2D 设置。有关此主题的更多信息,请参阅 优化彩色图像 。
下面显示了实际的基准数字。您会在页面底部找到更详细的表格。
2D数据在使用3D数据之后
下表列出了 3D+2D 捕获时间的示例。
相机分辨率和 1:1 映射
为了实现精确的 2D 分割与检测,高分辨率的彩色图像非常有益。Zivid 3 配备了 800 万像素成像传感器,Zivid 2+ 配备了 500 万像素传感器,而 Zivid 2 则配备了 230 万像素传感器。下表列出了不同相机进行 2D 和 3D 捕获时的分辨率输出。
2D 捕获 |
Zivid 3 |
Zivid 2+ |
Zivid 2 |
|---|---|---|---|
全分辨率 |
2816 x 2816 |
2448 x 2048 |
1944 x 1200 |
2x2 子采样 |
1408 x 1408 |
1224 x 1024 |
972 x 600 |
4x4 子采样 |
704 x 704 |
612 x 512 |
不支持 |
3D 捕获 |
Zivid 3 |
Zivid 2+ |
Zivid 2 |
|---|---|---|---|
全分辨率 |
2816 x 2816 |
2448 x 2048 |
1944 x 1200 |
2x2 子采样 |
1408 x 1420 |
1224 x 1024 |
972 x 600 |
4x4 子采样 |
704 x 704 |
612 x 512 |
不支持 |
执行 capture2D3D() 捕获时,结果是包含 2D 和 3D 数据的 frame 。
2D 数据可以通过两种方式提取:
frame.frame2D().imageRGBA_SRGB()这与您单独捕获 2D 是一样的。
frame.pointCloud().copyImageRGBA_SRGB()即使在设置定义 2D 和 3D 具有不同分辨率的情况下,这也将确保 1:1 映射。
2D 采集的输出分辨率通过 Settings2D::Sampling::Pixel 设置控制,3D 采集的输出分辨率则通过 Settings::Sampling::Pixel 和 Settings::Processing::Resampling 设置的组合控制。请参阅 像素采样 (2D) 、 像素采样 (3D) 和 Resampling(重采样) 。
如上所述,分割和检测通常需要高分辨率 2D 数据。例如,我们推荐的 Consumer Goods(消费品) Z2+ MR130 Quality 预设使用的 Sampling::Pixel 设置为 by2x2 。在这种情况下,我们应该:
对 3D 数据进行上采样,以恢复 1:1 对应关系,或
将 2D 索引映射到经过子采样的 3D 数据中的索引,或者
通过
frame.pointCloud().copyImageRGBA_SRGB()从点云获取二维数据
重采样
为了匹配 2D 捕获的分辨率,只需应用取消子采样的上采样即可。这样操作仍保留了子采样捕获的速度优势。例如:
auto settings2D = Zivid::Settings2D{
Zivid::Settings2D::Acquisitions{ Zivid::Settings2D::Acquisition{} },
Zivid::Settings2D::Sampling::Pixel::all,
};
auto settings = Zivid::Settings{
Zivid::Settings::Engine::stripe,
Zivid::Settings::Acquisitions{ Zivid::Settings::Acquisition{} },
Zivid::Settings::Sampling::Pixel::blueSubsample2x2,
Zivid::Settings::Sampling::Color::disabled,
Zivid::Settings::Processing::Resampling::Mode::upsample2x2,
};
settings_2d = zivid.Settings2D()
settings_2d.acquisitions.append(zivid.Settings2D.Acquisition())
settings_2d.sampling.pixel = zivid.Settings2D.Sampling.Pixel.all
settings = zivid.Settings()
settings.engine = "stripe"
settings.acquisitions.append(zivid.Settings.Acquisition())
settings.sampling.pixel = zivid.Settings.Sampling.Pixel.blueSubsample2x2
settings.sampling.color = zivid.Settings.Sampling.Color.disabled
settings.processing.resampling.mode = zivid.Settings.Processing.Resampling.Mode.upsample2x2
更多相关的详细信息,请参阅 Resampling(重采样) 。
在不同分辨率之间映射像素索引
另一种方法是将 2D 索引映射到子采样 3D 数据中的索引。此选项稍微复杂一些,但可能更高效。点云可以保持子采样,因此消耗更少的内存和处理能力。
为了建立全分辨率 2D 数据与经过子采样的点云之间的关联,需要一种特定的映射技术。该过程涉及从拜耳网格中蓝色或红色像素对应的像素中提取RGB值。
Zivid::Experimental::Calibration::pixelMapping(camera, settings); 可用于获取执行此映射所需的参数。以下是使用此函数的示例。
const auto pixelMapping = Zivid::Experimental::Calibration::pixelMapping(camera, settings);
std::cout << "Pixel mapping: " << pixelMapping << std::endl;
cv::Mat mappedBGR(
fullResolutionBGR.rows / pixelMapping.rowStride(),
fullResolutionBGR.cols / pixelMapping.colStride(),
CV_8UC3);
std::cout << "Mapped width: " << mappedBGR.cols << ", height: " << mappedBGR.rows << std::endl;
for(size_t row = 0; row < static_cast<size_t>(fullResolutionBGR.rows - pixelMapping.rowOffset());
row += pixelMapping.rowStride())
{
for(size_t col = 0; col < static_cast<size_t>(fullResolutionBGR.cols - pixelMapping.colOffset());
col += pixelMapping.colStride())
{
mappedBGR.at<cv::Vec3b>(row / pixelMapping.rowStride(), col / pixelMapping.colStride()) =
fullResolutionBGR.at<cv::Vec3b>(row + pixelMapping.rowOffset(), col + pixelMapping.colOffset());
}
}
return mappedBGR;
pixel_mapping = calibration.pixel_mapping(camera, settings)
return rgba[
int(pixel_mapping.row_offset) :: pixel_mapping.row_stride,
int(pixel_mapping.col_offset) :: pixel_mapping.col_stride,
0:3,
]
有关映射的更多详细信息(例如 blueSubsample2x2 )
为了提取与蓝色像素相对应的所有 RGB 值,我们使用以下索引:
为了提取与红色像素相对应的所有 RGB 值,我们使用以下索引:
备注
如果您需要使用内参,并且 2D 和 3D 捕获具有不同的分辨率,请确保正确使用它们。有关更多信息,请参阅 相机内参 。
总结
- 我们的建议:
使用全分辨率进行 2D 捕获
使用了子采样分辨率的 3D 捕获
备注
仅当您在捕获和复制具有不同分辨率的 2D 和 3D 时想要实现 1 对 1 像素对应关系时,才需要在用户代码中进行子采样或下采样。
下表显示了不同硬件上的实际测量结果。
- Zivid 3
(
Z3 XL250 Fast)- Zivid 2+
(
Z2+ LR110 Fast)(
Z2+ L110 Fast)- Zivid 2
(
Z2 M70 Matte)
小技巧
如需在 PC 上测试不同的 2D-3D 策略,您可以运行 ZividBenchmark.cpp 示例,并使用从 YML 文件加载的设置。您可以在 示例 页面选择 C++ 选项查看说明。
版本历史
SDK |
变更 |
|---|---|
2.17.0 |
新增对 Zivid 3 XL250 的支持。 |
2.14.0 |
增加了对 Zivid 2+ MR130、LR110 和 MR60 的支持,与旧款 Zivid 2+ 型号相比,它们速度更快,更适合拣选物品。 |
2.12.0 |
对于 Zivid 2+,2D 捕获的采集时间最多可减少 50%,3D 捕获的采集时间最多可减少 5%。请注意,Zivid One+已达到其生命周期终点,不再提供支持。因此,与 2D+3D 捕获相关的大多数复杂性不再适用。 |
2.11.0 |
Zivid 2 和 Zivid 2+ 现在支持 3D ➞ 2D 和 3D ➞ 2D 的并发处理和采集,并且优化了捕获模式之间的切换。 |