优化彩色图像
介绍
本教程旨在帮助您优化Zivid相机捕获的彩色图像的质量。我们将首先介绍如何使用获得良好颜色信息的基本工具:调整采集和颜色设置。然后我们将解决最常见的挑战(HDR中的光晕/过度饱和现象和颜色不一致性),并就如何克服这些问题提供我们的建议。
小技巧
Zivid 2+ 相机比 Zivid 2 相机具有更高的分辨率并采用了更好的去马赛克算法, 因此,Zivid 2+ 可以输出更高质量的 2D 图像。
调整采集设置
您从Zivid相机获得的彩色图像的质量取决于采集设置。本教程不包含如何调整曝光设置(曝光时间、光圈、亮度和增益)的组合以获得所需的动态范围, 调整合适的曝光以获取好的点云 一文涵盖这部分的内容。本教程侧重于调整影响彩色图像质量的特定采集设置。
曝光时间和投影仪亮度不会影响彩色图像的质量。另一方面,较高的光圈值是避免彩色图像模糊的关键。见下图。一个好的经验设定值是5.66或更高的f-值(更小的光圈)。如需了解更详细的说明,请参阅 焦深 和 Depth of Focus Calculator。
Single acquisition capture with aperture 10.37 |
Single acquisition capture with aperture 3.67 |
备注
上面的图像是在最佳成像距离之外拍摄的,以强调大光圈值时的失焦效果,而在最佳范围内拍摄时,图像不会如此模糊。
我们建议使用较低的增益值,例如1-2,因为高增益值会增加图像噪声(粒度)水平,从而降低2D图像质量;见下图。
Single acquisition capture with gain 1 |
Single acquisition capture with gain 16 |
我们通常通过调整采集设置以达到所需的动态范围和捕获时间,首要关注点是点云质量。通过这种方法,彩色图像质量是我们在给定捕获时间下针对3D质量优化的设置获得的。这种方法的缺点是它并不总是能够提供良好的彩色图像质量。然而事实情况是高质量的彩色图像(低模糊、低噪声和平衡照明)会产生高质量的点云。考虑到这一点,很明显,遵循上述微调的方法来提高彩色图像质量也会相应地提高3D质量。实现这一目标的关键是通过增加曝光时间和投影仪亮度值来补偿低增益和光圈(高 f 值)。
调整颜色设置
除了光圈和增益,彩色图像质量还取决于Gamma、Color Balance(白平衡)和Color Mode(颜色模式)等设置。本节旨在深入了解如何优化这些设置以在彩色图像中获得所需的颜色质量。有关颜色设置的更多信息,请参见此处: Processing(处理)设置。
Gamma
相机对亮度的编码与人眼不同。人眼侧重于光谱的较暗端,相机则以线性比例编码亮度。为了补偿这种影响,gamma校正被应用于使图像变暗或变亮,使其更接近人类的感知。
备注
Zivid相机的Gamma校正设定值范伟介于0.25和1.5之间。
Gamma值越低,场景会显得越亮。如果增加Gamma值,则场景会显得更暗。
Image captured with Gamma set to 0.6 |
Image captured with Gamma set to 1.3 |
是否需要gamma校正来优化图像质量用于机器视觉算法是有疑问的。尽管如此,它仍然可以帮助我们评估彩色图像质量的某些方面,例如焦点和颗粒/噪声水平。
有关示例的实现,请查看 Gamma校正。该教程展示了如何使用可配置的gamma校正捕获2D图像。
Color Balance(色彩平衡)
环境光的 color temperature (色温)会影响彩色图像的显示。您可以通过红色、绿色和蓝色通道的数字增益进行调整,使彩色图像看起来更加自然。如下图所示,您可以看到平衡颜色前后的图像的对比。如果您想自动为您的设置找到合适的色彩平衡参数,请查看 色彩平衡教程 。
备注
Zivid相机的色彩平衡增益值范围在1.0到8.0之间。
在强烈和变化的环境光下使用色彩平衡将是有益的。在没有投影仪或投影仪亮度值较低的情况下捕获图像时,调节色彩平衡是必要的。换句话说,即当环境光是相机看到的光的重要组成部分时。有两种默认的色彩平衡设置,对应投影仪开启和不开启的情况。当投影仪亮度设置为0或关闭时,色彩平衡校准为4500K,这是工业环境中的典型值。对于高于0的投影仪亮度值,会针对投影仪灯光的色温校准色彩平衡。
有关示例的实现,请参见 调整色彩平衡 教程。该教程展示了如何通过循环拍摄白色表面(一张纸、墙壁或类似物体)的图像来平衡2D图像的颜色。
Color Mode(颜色模式)
颜色模式设置控制了如何计算彩色图像。颜色模式设置可设为以下模式:
ToneMapping
UseFirstAcquisition
Automatic
ToneMapping
(色调映射)使用了所有采集项来生成一个融合的和标准化过的彩色图像。对于多次采集的HDR捕获,得到的图像动态范围通常高于8位彩色图像范围。色调映射将通过应用缩放因子将HDR颜色数据映射到8位颜色输出范围。色调映射也可用于单次采集捕获,以将捕获的彩色图像标准化为完整的8位输出。使用 ToneMapping
时,如果您移动、添加或移除了场景中的对象,重复捕获的颜色值可能会不一致。为了最大限度地控制颜色,请使用 UseFirstAcquisition
模式。
UseFirstAcquisition
使用了第一个采集项获得的颜色数据。如果捕获包含多次采集,则其它采集获得的数据不会被用于生成彩色图像。该模式下不会执行色调映射。此模式将提供对彩色图像的最大控制,并且颜色值将在使用相同设置的重复捕获中保持一致。
Automatic
是默认设置。在进行单次采集和所有采集项都具有相同(重复的)采集设置的多次采集时,
Automatic
等同于UseFirstAcquisition
。在进行具有不同采集设置的多次采集HDR时,
Automatic
等同于ToneMapping
。
备注
从SDK 2.7开始,可以通过将颜色模式设置为 UseFirstAcquisition
来禁用HDR捕获的色调映射。
对于单次采集捕获,色调映射可用于将较暗的图像变亮。
Single acquisition capture with Color Mode set to |
Single acquisition capture with Color Mode set to |
对于多次采集HDR,色调映射可用于将高动态范围颜色映射到更有限的动态范围输出。
Single acquisition capture of the first of three HDR acquisitions with Color Mode set to |
Single acquisition capture of the second of three HDR acquisitions with Color Mode set to |
Single acquisition capture of the third of three HDR acquisitions with Color Mode set to |
HDR with three acquisitions with Color Mode set to |
使用UseFirstAcquisition的HDR捕获
如果您不想对多次采集HDR使用色调映射,而是使用其中一个采集项的彩色图像,这是可以实现的。确定您要使用哪个采集项中的颜色。然后,确保该采集项是HDR采集设置序列中的第一个,并将颜色模式设置为 UseFirstAcquisition
。对于上面的示例,现在生成的彩色图像看起来就像使用三个HDR采集中的第一个采集项的单次捕获的彩色图像。
提示
在Zivid Studio的采集设置中依次点击 … → Move to top 即可将选定的采集项移动到序列中的第一个位置。
如果要更改HDR捕获中获取彩色图像的采集项,只需重新排列采集设置即可。建议使用 UseFirstAcquisition
颜色模式以在重复捕获中保持颜色一致,这对诸如基于2D图像中的颜色或纹理的对象分类等应用非常有用。有关实现示例的详细说明,请查看 如何处理HDR中颜色不一致的问题。
查看如何使用Zivid SDK配置数据处理的设置,包括Gamma、Color Balance和Color Mode:
std::cout << "Configuring settings for capture:" << std::endl;
Zivid::Settings settings{
Zivid::Settings::Engine::phase,
Zivid::Settings::Sampling::Color::rgb,
Zivid::Settings::Sampling::Pixel::blueSubsample2x2,
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::Smoothing::Gaussian::Enabled::yes,
Zivid::Settings::Processing::Filters::Smoothing::Gaussian::Sigma{ 1.5 },
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::Cluster::Removal::Enabled::yes,
Zivid::Settings::Processing::Filters::Cluster::Removal::MaxNeighborDistance{ 10 },
Zivid::Settings::Processing::Filters::Cluster::Removal::MinArea{ 100 },
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::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::Resampling::Mode::upsample2x2,
Zivid::Settings::Processing::Color::Balance::Red{ 1.0 },
Zivid::Settings::Processing::Color::Balance::Green{ 1.0 },
Zivid::Settings::Processing::Color::Balance::Blue{ 1.0 },
Zivid::Settings::Processing::Color::Gamma{ 1.0 },
Zivid::Settings::Processing::Color::Experimental::Mode::automatic
};
std::cout << settings << std::endl;
Console.WriteLine("Configuring settings for capture:");
var settings = new Zivid.NET.Settings()
{
Engine = Zivid.NET.Settings.EngineOption.Phase,
Sampling = { Color = Zivid.NET.Settings.SamplingGroup.ColorOption.Rgb, Pixel = Zivid.NET.Settings.SamplingGroup.PixelOption.BlueSubsample2x2 },
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 = { Smoothing = { Gaussian = { Enabled = true, Sigma = 1.5 } },
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} },
Cluster = { Removal = { Enabled = true, MaxNeighborDistance = 10, MinArea = 100} },
Hole = { Repair = { Enabled = true, HoleSize = 0.2, Strictness = 1 } },
Experimental = { ContrastDistortion = { Correction = { Enabled = true,
Strength = 0.4 },
Removal = { Enabled = true,
Threshold = 0.5 } } } },
Resampling = { Mode = Zivid.NET.Settings.ProcessingGroup.ResamplingGroup.ModeOption.Upsample2x2},
Color = { Balance = { Red = 1.0, Green = 1.0, Blue = 1.0 },
Gamma = 1.0,
Experimental = { Mode = ColorModeOption.Automatic } } }
};
Console.WriteLine(settings);
print("Configuring settings for capture:")
settings = zivid.Settings()
settings.engine = zivid.Settings.Engine.phase
settings.sampling.color = zivid.Settings.Sampling.Color.rgb
settings.sampling.pixel = zivid.Settings.Sampling.Pixel.blueSubsample2x2
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]
filters = settings.processing.filters
filters.smoothing.gaussian.enabled = True
filters.smoothing.gaussian.sigma = 1.5
filters.noise.removal.enabled = True
filters.noise.removal.threshold = 7.0
filters.noise.suppression.enabled = True
filters.noise.repair.enabled = True
filters.outlier.removal.enabled = True
filters.outlier.removal.threshold = 5.0
filters.reflection.removal.enabled = True
filters.reflection.removal.mode = zivid.Settings.Processing.Filters.Reflection.Removal.Mode.global_
filters.cluster.removal.enabled = True
filters.cluster.removal.max_neighbor_distance = 10
filters.cluster.removal.min_area = 100
filters.experimental.contrast_distortion.correction.enabled = True
filters.experimental.contrast_distortion.correction.strength = 0.4
filters.experimental.contrast_distortion.removal.enabled = False
filters.experimental.contrast_distortion.removal.threshold = 0.5
filters.hole.repair.enabled = True
filters.hole.repair.hole_size = 0.2
filters.hole.repair.strictness = 1
resampling = settings.processing.resampling
resampling.mode = zivid.Settings.Processing.Resampling.Mode.upsample2x2
color = settings.processing.color
color.balance.red = 1.0
color.balance.blue = 1.0
color.balance.green = 1.0
color.gamma = 1.0
settings.processing.color.experimental.mode = zivid.Settings.Processing.Color.Experimental.Mode.automatic
print(settings)
处理光晕
正如 在 光晕 - 点云中的亮点 中讨论的,光晕是当来自一个点或区域的极强光线照射到成像传感器并导致过饱和时发生的一种效果。在本文中,我们将讨论如何避免场景中的光晕问题。
有多种方法可以处理光晕问题。本教程中介绍的方法包括:更改背景、更改相机位置和方向、使用HDR,使用Color Mode或进行单独的2D捕获。
更改背景
如果背景是导致光晕的源头,请将背景材质更改为漫反射特性更强和光吸收性更强的材质 (材料的光学特性)。
Scene with white background with blooming |
Same scene with black background and effect from blooming removed from the point cloud |
调整相机角度
改变相机的位置和方向是一种处理光晕的简单而有效的方法。建议将相机偏移并倾斜,以使投影仪和其他光源不会直接反射到相机中。请参考下面右侧的图像。
只需倾斜相机,就可以恢复在过饱和区域丢失的数据,如上图右侧所示。下面左侧的图像时当相机垂直于表面安装时拍摄的点云,而右图则是稍微倾斜拍摄的场景。
一个简单的经验法则是通过调整相机的安装位置,使目标区域位于相机前方,如下图所示:
HDR捕获
使用包含多次采集的3D HDR,即通过添加一个或多个3D采集来覆盖光晕区域的高光。请记住,这将以增加捕获时间为代价。
Scene with blooming (single acquisition) |
Same scene with effect from blooming removed from the point cloud (multi-acquisition HDR) |
遵循上述步骤很可能可以恢复点云中由于光晕效应而丢失的点。但是,过饱和区域仍有可能保留在彩色图像中。
如果您只关心3D点云质量,彩色图像中的过饱和可能不是问题。但是,如果您在彩色图像上使用机器视觉算法(例如模板匹配),过饱和可能会成为问题。
备注
默认的颜色模式(Color Mode)为Automatic,对于多次采集HDR,相当于ToneMapping。用于HDR捕获的颜色融合(色调映射)算法是彩色图像中过饱和的根源。该算法解决了将不同动态范围的彩色图像映射为具有有限动态范围的彩色图像的挑战性问题。然而,色调映射算法有其局限性:过饱和问题。
使用UseFirstAcquisition颜色模式进行HDR捕获
备注
此解决方案只能与SDK 2.7及更高版本一起使用。在左上角将KB更改为旧版本以查看SDK 2.6或更低版本的解决方案。
克服过饱和的一种尝试是确认或找到针对场景中最亮对象优化的采集项。然后,将该采集项设置为采集设置中的第一个。最后,使用UseFirstAcquisition颜色模式来捕获HDR。
提示
在Zivid Studio的采集设置中依次点击 … → Move to top 即可将选定的采集项移动到序列中的第一个位置。
在某些情况下,可以消除或至少显著减少过饱和情况。
如果成像对象的材料是镜面的,这种方法可能无法消除过饱和。在这种情况下,建议考虑在投影仪关闭的情况下进行额外的捕获。请参阅以下潜在解决方案(不启用投影仪)。
额外的捕获
克服彩色图像过饱和的另一种解决方案是添加单独的捕获并优化其设置,专门用于避免这种图像伪像。这种方法将使用来自主捕获的点云数据和来自附加捕获的彩色图像。附加的捕获可以是2D或3D捕获,启用或关闭投影仪。如果您使用3D捕获,则必须关闭色调映射(Color Mode设置为UseFirstAcquisition)。
备注
可以在主要捕获之前或之后进行附加捕获。如果2D图像和3D点云的算法使用了不同的线程,请根据算法执行时间来决定。
小技巧
您可以通过单独的2D图像捕获来优化彩色图像质量的采集设置(在大多数情况下,我们优化设置的目的是获得出色的点云质量)。
启用投影仪
在某些情况下,可以通过启用投影仪来消除过饱和。
关闭投影仪
如果成像对象的材料是镜面的,则不太可能消除过饱和。因此可以考虑关闭投影仪。
如果不使用投影仪进行拍摄,您必须确保相机获得足够的光线。可以使用具有更长曝光时间、更高增益值和更低光圈值的设置来实现,或者在场景中添加额外的光源,比如使用漫射光源,并仅在彩色图像采集期间将其打开。如果在主采集期间打开,附加光源则可能会降低点云质量。
不启用投影仪并设置色彩平衡
当不使用投影仪时,也很可能需要平衡颜色。请查看 调整色彩平衡 了解实现示例的教程。该教程展示了如何通过循环拍摄白色表面(一张纸、墙壁或类似物)的图像来平衡2D图像的颜色。
处理HDR的颜色不一致的问题
如 果 Color Mode 设置为ToneMapping或Automatic(默认设置),则多次采集的HDR捕获的彩色图像是应用了色调映射之后的结果。虽然色调映射解决了为特定捕获优化颜色的挑战性问题,但它也有一个缺点。由于它是针对整个场景的函数,会导致场景变化时颜色也变得不一致。下面的例子解释了这种现象。
假设我们有一个相对较暗的场景(黑色表面上的梨)。我们找到了涵盖足够宽的动态范围的采集设置并执行了多次采集的HDR采集(左图)。然后我们在场景中添加了一个明亮的对象(香蕉),并使用相同的设置再次捕获(右图)。
HDR capture of a dark scene (Color Mode: Automatic or ToneMapping) |
HDR capture with the same settings of the same scene but with an additional bright object added |
让我们看看输出的彩色图像(右图),特别是场景中最初的深色对象(梨或黑色表面)。我们注意到这些对象的RGB值在将明亮对象(香蕉)添加到场景之前和之后是不同的。
RGB值的变化对于某些应用来说可能是一个问题,例如,使用基于颜色信息对对象进行分类的算法的应用。原因是这些算法会期望RGB值在重复捕获时保持相同(一致)。
使用UseFirstAcquisition颜色模式进行HDR捕获
备注
此解决方案只能与SDK 2.7及更高版本一起使用。在左上角将KB更改为旧版本以查看SDK 2.6或更低版本的解决方案。
要克服HDR颜色不一致的问题,请确定HDR捕获的哪些采集能够提供最佳颜色。我们建议针对场景中最亮的物体优化采集以避免饱和。然后,将该采集设置为采集设置中的第一个。最后,使用UseFirstAcquisition颜色模式来捕获您的HDR图像。
我们将通过一个示例引导您完成整个过程。让我们假设我们有一个带有两次采集的HDR。第一次采集针对深色物体(梨)进行了优化。第二次采集针对明亮物体(香蕉)进行了优化。使用UseFirstAcquisition颜色模式进行HDR捕获会得到以下结果。
HDR capture of a dark scene (Color Mode: UseFirstAcquisition) |
HDR capture with the same settings of the same scene but with an additional bright object added |
两张图像中深色物体(梨)的颜色相同。颜色一致性得以保留。
然而,因为第一次采集是针对深色物体进行优化的,所以场景中最亮的物体(香蕉)是饱和的。饱和度可能会导致问题,例如,如果我们想根据颜色对对象进行分类。为了克服这个问题,我们可以重新排列采集设置。我们将为场景中最亮的物体(香蕉)优化的采集设置为第一次采集。第二个采集项则针对深色物体(梨)进行优化。现在,我们看到颜色的一致性通过一起和单独捕获的明亮的和深色的对象得以保留。而且最亮的物体(香蕉)没有饱和。
HDR capture of a dark scene (Color Mode: UseFirstAcquisition) |
HDR capture with the same settings of the same scene but with an additional bright object added |
HDR capture with the same settings of the same scene but only with the bright object |
备注
有一个能够提供最佳颜色的单个采集项是最佳的状况。该采集项针对场景中最亮的物体进行了优化,因此在这些物体也具备非常好的SNR。该采集可能已经是您的HDR采集设置的一部分,那么久不需要额外的采集来处理HDR中的颜色不一致的问题。
如果彩色图像显得太暗,可以使 用 Gamma 进行设置。
小心
Capture Assistant返回的第一个采集可能无法提供最佳的彩色图像。因此,如果使用Capture Assistant和UseFirstAcquisition彩色模式,您可能需要重新调整采集的顺序。
提示
在Zivid Studio的采集设置中依次点击 … → Move to top 即可将选定的采集项移动到序列中的第一个位置。
额外捕获
备注
仅当您必须使用自动或色调映射颜色模式进行 HDR 捕获时,才应使用此解决方案。
克服HDR色彩不一致的替代解决方案是在主捕获之外进行单独捕获。这种方法假设用户使用主捕获来获取点云数据,并使用附加捕获来获取彩色图像。附加捕获可以是2D或3D捕获,启用或关闭投影仪。无论使用哪种捕获模式,都必须关闭色调映射(Color Mode设置为UseFirstAcquisition)。
Single acquisition capture of a dark scene with Color Mode set to UseFirstAcquisition or Automatic |
Single acquisition capture with the same settings of the same scene but with an additional bright object added (Color Mode set to UseFirstAcquisition or Automatic) |
进一步阅读
继续阅读 如何在目标像素上获得良好的3D数据。