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捕获

跳转到源码

source

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 数据。因此,我们只需关心整体速度和质量。

速度

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

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

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

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

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

2D图像质量

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

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

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

下表列出了 3D+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 值,我们使用以下索引:

\[\begin{split}\begin{bmatrix} (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) \\ \end{bmatrix}\text{, where }\begin{matrix} W=width-2 \\ H=height-2 \end{matrix}\end{split}\]

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

\[\begin{split}\begin{bmatrix} (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) \\ \end{bmatrix}\text{, where }\begin{matrix} W=width-1 \\ H=height-1 \end{matrix}\end{split}\]

备注

如果您需要使用内参,并且 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++ 选项查看说明。

版本历史

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