2D+3D捕获策略

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

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

2D数据

RGB图像

3D数据

点云

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

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

  2. 作为3D捕获的一部分 camera.capture(Zivid::Settings).pointCloud.copyImageRGBA() ,请参阅 点云捕获过程

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

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

关于外部光源

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

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

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

  • 开门和关门

  • 顶灯打开和关闭

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

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

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

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

2D数据先于3D数据

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

小技巧

当您单独捕获 2D 时,您应该在 3D 捕获中禁用 RGB。这可以节省采集和处理时间。通过将 Sampling::Color 设置为 disabled 来禁用 3D 捕获中的 RGB。

警告

对于 Zivid 2+ 相机,可以使用 4x4 子采样模式(4x4 subsampling), Monochrome Capture(单色捕获) 。使用此功能时,2D 和 3D 捕获之间会有 35ms 的切换损失。仅当捕获紧随其后发生时才会发生这种情况。

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

  1. 捕获2D图像

  2. 使用2D数据和并行执行3D捕获

跳转到源码

源码

const auto frame2dAndCaptureTime = captureAndMeasure<Zivid::Frame2D>(camera, settings2D);
std::future<Duration> userThread =
    std::async(std::launch::async, useFrame<Zivid::Frame2D>, std::ref(frame2dAndCaptureTime.frame));
const auto frameAndCaptureTime = captureAndMeasure<Zivid::Frame>(camera, settings);
const auto processTime = useFrame(frameAndCaptureTime.frame);
const auto processTime2D = userThread.get();

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

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

在这种情况下,我们不必在使用3D数据之前获取2D数据。作为3D采集的一部分,您始终会获得2D数据。因此,我们只需要关心整体捕获速度和图像质量。

速度

为了获得最佳速度,我们仅依靠3D采集来获取良好的2D数据。2D数据无需额外采集或单独采集。

2D图像质量

为了获得最佳 2D 质量,建议使用单独的 2D 采集。

下表显示了不同配置的预期效果。文末有一个表格,它显示不同硬件上的实际测量结果。

快速

使用来自3D捕获中的2D数据。无需特殊的2D采集或设置。

最好

单独的2D捕获,紧接着执行3D捕获。

使用的硬件平台:11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz 和 NVIDIA GeForce RTX 3070

快速

最好

3D [2]

2D + 3D

Zivid 2

2D

N/A

~25 毫秒

3D

~295 ms

~290 ms

2D+3D

~295 ms

~300 ms

Zivid 2+

2D

N/A

~55 ms

3D

~170 ms

~220 ms

2D+3D

~170 ms

~260 ms

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

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

作为3D采集的一部分,您总是能够获得2D数据。下表展示了3D捕获时间的示例。

然而,针对 3D 质量进行的优化并不总是能够优化 2D 图像质量。因此,在 3D 捕获之后进行单独的 2D 捕获可能是个好主意。

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

相机分辨率和 1:1 映射

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

2D 捕获分辨率

2D 捕获

Zivid 2

Zivid 2+

全分辨率

1944 x 1200

2448 x 2048

2x2 子采样

972 x 600

1224 x 1024

4x4 子采样

不支持

612 x 512

3D 捕获分辨率

3D 捕获

Zivid 2

Zivid 2+

全分辨率 [1]

1944 x 1200

2448 x 2048

2x2 子采样 [1]

972 x 600

1224 x 1024

4x4 子采样 [1]

不支持

612 x 512

2D 和 3D 捕获的输出分辨率是由 Sampling::PixelProcessing::Resampling 设置的组合进行控制,详细内容请参阅 像素采样Resampling(重采样) 。这意味着 2D 像素和 3D 点之间可能不再具有 1:1 的对应关系。因此,从 2D 图像中的分割掩模中提取 3D 数据变得更加具有挑战性。

如上所述,分割和检测通常需要高分辨率 2D 数据。例如,我们推荐的 Consumer Goods(消费品) Z2+ M130 Quality 预设使用的 Sampling::Pixel 设置为 blueSubsample2x2 。在这种情况下,我们应该:

  • 对 3D 数据进行上采样,以恢复 1:1 对应关系,或

  • 将二维索引映射到子采样三维数据中的索引。

重采样

为了匹配 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 像素对应关系时,才需要在用户代码中进行子采样或降采样。

下表列出了不同的 2D+3D 捕获配置。显示了它们在速度和质量方面的相对表现。

捕获周期

速度

2D质量

Zivid 2

Zivid 2+

较快

快速

最好

D ➞ 2D / 2D ➞ 3D

快速

快速

最好

3D(启用 w/RGB)

最快

最快

良好

下表列出了不同硬件上的实际测量结果。这里我们使用了Fast Consumer Goods的预设设置进行3D捕获。

Zivid 2+

( Z2+ M130 Fast )

Zivid 2

( Z2 M70 Fast )

小技巧

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

版本历史

SDK

变更

2.12.0

对于 Zivid 2+,2D 捕获的采集时间最多可减少 50%,3D 捕获的采集时间最多可减少 5%。请注意,Zivid One+已达到其生命周期终点,不再提供支持。因此,与 2D+3D 捕获相关的大多数复杂性不再适用。

2.11.0

Zivid 2 和 Zivid 2+ 现在支持 3D ➞ 2D 和 3D ➞ 2D 的并发处理和采集,并且优化了捕获模式之间的切换。