2D+3D捕获策略

如果您的应用同时需要2D和3D数据,那么您可以参考本教程。

我们解释并强调了不同的2D-3D捕获方法的优缺点,阐明了一些限制,并解释了它们如何影响循环时间。我们也谈到了使用外部光源和使用内部投影仪来拍摄2D图像的区别。

2D数据

RGB图像

3D数据

点云

获取2D数据有两种不同的方式:

  1. 单独通过 camera.capture2D(Zivid::Settings2D or Zivid::Settings ).imageRGBA_SRGB() 获取,请参阅 2D图像捕获流程

  2. 作为 2D3D 捕获 frame = camera.capture2D3D(Zivid::Settings) 的一部分:

    1. frame.pointCloud().copyImageRGBA_SRGB() 。这确保了 2D 和 3D 数据之间的 1:1 映射。

    2. frame.frame2D().imageRGBA_SRGB() 。这和你单独捕获 2D 图像是一样的。

使用哪一种方式来获取2D数据取决于您的要求。

不同的场景会导致不同的权衡。我们首先根据您需要的数据对其进行细分。然后我们将讨论不同场景下捕获速度与图像质量的权衡。

关于外部光源

在我们讨论不同的策略之前,我们需要讨论外部光源。2D捕获的理想光源是强漫射光,因为这会限制 光晕效果 。使用内部投影仪作为光源时,光晕效果几乎是不可避免的。 以一定角度安装相机 可显着降低这种影响,但外部漫射光源仍然会提供更好的效果。外部光源会导致3D数据中出现额外噪声,因此最好在3D采集期间关闭外部光源。

除了减少光晕效应外,高照度的外部光源还可以消除由环境光变化引起的曝光变化。环境光变化的典型来源有:

  • 日光变化(白天/黑夜、云等)

  • 开门和关门

  • 顶灯打开和关闭

备注

Zivid 2+R 对环境光的变化具有很强的适应能力。

Zivid 2+ M60/M130/L110 和 Zivid 2 的注意事项

这些曝光变化对3D和2D数据的影响不同。2D数据中曝光变化的影响取决于所使用的检测算法。如果在2D中执行分割,这些变化可能会,也可能不会影响分割性能。对于点云,您可能会发现由于噪声的变化而导致点云完整性的变化。

这就引出了一个问题:我们是否应该使用相机的投影仪来捕获2D图像?

如何决定是否使用投影仪作为2D捕获的光源。

查看 优化彩色图像 了解有关此主题的更多信息。

2D数据先于3D数据

如果您在2D中执行分割,然后确定您的抓取位姿,那么您需要在获取3D之前得到2D数据。获取2D数据的最快方法是使用单独的2D捕获。因此,如果您在使用3D数据之前就需要使用2D数据,那么您应该先执行单独的2D捕获。

警告

在 2D 和 3D 捕获之间切换时,可能需要重新配置相机。这会导致 2D+3D 捕获时间增加,因为 2D+3D 捕获是连续进行的。具体如下:

  • 如果可能的话,保持 2D 采集的光圈设置(aperture )与 3D 采集的光圈设置(aperture )一样。

  • 考虑在 2D 和 3D 中使用相同的采样设置,请参阅 Sampling(采样)- 2DSampling(采样) - 3D

    • 切换采样设置的惩罚时间为 35ms。

    • 在 3D 中使用低分辨率的收益通常大于损失,特别是对于具有挑战性的场景。

以下代码示例展示了您可以如何:

  1. 捕获2D图像

  2. 使用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();

下面显示了实际的基准数字。您会在页面底部找到更详细的表格。

Display Options

Capture 2D + 3D

hidden
hidden
2+R2+2
High-end NVIDIAHigh-end NVIDIAHigh-end NVIDIA
2D3D2D3D2D3D
Consumer Goods Settings
Consumer Goods Fast
Consumer Goods Quality

2D数据作为如何使用3D数据的一部分

在这种情况下,我们不必在访问 3D 数据之前先访问 2D 数据。因此,我们只需关心整体速度和质量。

速度

为了达到最佳速度,我们应该避免切换惩罚。

  • 保持 2D 采集的光圈设置(aperture )与 3D 采集的光圈设置(aperture )一样。

  • 在 2D 和 3D 中使用相同的采样设置,请参阅 Sampling(采样)- 2DSampling(采样) - 3D

    • 切换采样设置的惩罚时间为 35ms。

    • 在 3D 中使用低分辨率的收益通常大于损失,特别是对于具有挑战性的场景。

2D图像质量

为了获得最佳的 2D 质量,请根据您的需求调整 2D 设置。有关此主题的更多信息,请参阅 优化彩色图像

下面显示了实际的基准数字。您会在页面底部找到更详细的表格。

hidden
2+R2+2
High-end NVIDIAHigh-end NVIDIAHigh-end NVIDIA
Consumer Goods Settings
Consumer Goods Fast130 ms (±2)475 ms (±2)310 ms (±18)
Consumer Goods Quality260 ms (±1)905 ms (±6)455 ms (±19)

2D数据在使用3D数据之后

下表列出了 3D+2D 捕获时间的示例。

hidden
hidden
2+R2+2
High-end NVIDIAHigh-end IntelHigh-end NVIDIAHigh-end IntelHigh-end NVIDIAHigh-end Intel
2D3D2D3D2D3D2D3D2D3D2D3D
Capture 3D and then 2D
Projector On for 2D
Projector Off for 2D

相机分辨率和 1:1 映射

为了实现准确的 2D 分割和检测,高分辨率彩色图像非常有用。Zivid 2+ 配备了 5 MPx 成像传感器,而 Zivid 2 配备了 2.3 MPx 传感器。下表显示了不同相机在 2D 和 3D 捕获时的分辨率输出。

2D 捕获分辨率

2D 捕获

Zivid 2+

Zivid 2

全分辨率

2448 x 2048

1944 x 1200

2x2 子采样

1224 x 1024

972 x 600

4x4 子采样

612 x 512

不支持

3D 捕获分辨率

3D 捕获

Zivid 2+

Zivid 2

全分辨率

2448 x 2048

1944 x 1200

2x2 子采样

1224 x 1024

972 x 600

4x4 子采样

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::PixelSettings::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::phase,
    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 = "phase"
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 值,我们使用以下索引:

[(0,0)(0,2)(0,4)(0,...)(0,W)(2,0)(2,2)(2,4)(2,...)(2,W)(4,0)(4,2)(4,4)(4,...)(4,W)(...,0)(...,2)(...,4)(...,...)(...,...)(H,0)(H,2)(H,4)(H,...)(H,W)], where W=width2H=height2

为了提取与红色像素相对应的所有 RGB 值,我们使用以下索引:

[(1,1)(1,3)(1,5)(1,...)(1,W)(3,1)(3,3)(3,5)(3,...)(3,W)(5,1)(5,3)(5,5)(5,...)(5,W)(...,1)(...,3)(...,5)(...,...)(...,...)(H,1)(H,3)(H,5)(H,...)(H,W)], where W=width1H=height1

备注

如果您需要使用内参,并且 2D 和 3D 捕获具有不同的分辨率,请确保正确使用它们。有关更多信息,请参阅 相机内参

总结

我们的建议:
  • 使用全分辨率进行 2D 捕获

  • 使用了子采样分辨率的 3D 捕获

备注

仅当您在捕获和复制具有不同分辨率的 2D 和 3D 时想要实现 1 对 1 像素对应关系时,才需要在用户代码中进行子采样或降采样。

下表显示了不同硬件上的实际测量结果。

Zivid 2+

Z2+ LR110 Fast

Z2+ L110 Fast

Zivid 2

( Z2 M70 Fast )

小技巧

如需在 PC 上测试不同的 2D-3D 策略,您可以运行 ZividBenchmark.cpp 示例,并使用从 YML 文件加载的设置。您可以在 示例 页面选择 C++ 选项查看说明。

Cameras

Configurations

Display Options

Capture 2D + 3D

Capture 2D and then 3D
Capture 3D and then 2D
Capture 3D including 2D
hidden
hidden
2+R2+
High-end NVIDIAHigh-end NVIDIA
2D3D2D3D
Capture 2D and then 3D
Projector On for 2D
Projector Off for 2D
Capture 3D and then 2D
Projector On for 2D
Projector Off for 2D
Capture 3D including 2D
Projector Off for 2D

版本历史

SDK

变更

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 的并发处理和采集,并且优化了捕获模式之间的切换。