OpenCV 4.11.0
开源计算机视觉库
加载中…
搜索中…
无匹配项
更改图像的对比度和亮度!

上一教程: 使用 OpenCV 添加(混合)两张图像
下一教程: 离散傅里叶变换

原作者Ana Huamán
兼容性OpenCV >= 3.0

目标

在本教程中,您将学习如何:

  • 访问像素值
  • 用零初始化矩阵
  • 了解cv::saturate_cast的作用及其用途
  • 获取一些关于像素变换的实用信息
  • 通过实际示例改进图像亮度

理论

注意
以下解释来自 Richard Szeliski 编著的书籍 Computer Vision: Algorithms and Applications

图像处理

  • 一般的图像处理算子是一个函数,它接受一个或多个输入图像并产生一个输出图像。
  • 图像变换可以看作:
    • 点算子(像素变换)
    • 邻域(基于区域)算子

像素变换

  • 在这种图像处理变换中,每个输出像素的值仅取决于相应的输入像素值(加上可能的一些全局收集的信息或参数)。
  • 此类算子的示例包括亮度和对比度调整以及颜色校正和变换。

亮度和对比度调整

  • 两个常用的点过程是与常数的乘法加法

    \[g(x) = \alpha f(x) + \beta\]

  • 参数\(\alpha > 0\)和\(\beta\)通常被称为增益偏差参数;有时这些参数分别被称为控制对比度亮度
  • 您可以将\(f(x)\)视为源图像像素,将\(g(x)\)视为输出图像像素。然后,我们可以更方便地将表达式写成

    \[g(i,j) = \alpha \cdot f(i,j) + \beta\]

    其中\(i\)和\(j\)表示像素位于第i行和第j列。

代码

解释

  • 我们使用 cv::imread 加载图像并将其保存在 Mat 对象中
  • 现在,由于我们将对该图像进行一些变换,因此我们需要一个新的 Mat 对象来存储它。此外,我们希望它具有以下特性:
    • 初始像素值等于零
    • 与原始图像大小和类型相同

我们观察到 cv::Mat::zeros 基于 image.size()image.type() 返回一个 Matlab 风格的零初始化器

  • 我们现在要求用户输入 \(\alpha\) 和 \(\beta\) 的值
  • 现在,为了执行操作 \(g(i,j) = \alpha \cdot f(i,j) + \beta\),我们将访问图像中的每个像素。由于我们使用的是 BGR 图像,每个像素将有三个值 (B、G 和 R),因此我们也将分别访问它们。以下是代码片段:

注意以下几点 (**仅限 C++ 代码**)

  • 访问图像中每个像素点,我们使用以下语法:image.at<Vec3b>(y,x)[c],其中y表示行,x表示列,c表示B、G或R通道(0、1或2)。
  • 由于运算\(\alpha \cdot p(i,j) + \beta\)可能产生超出范围的值或非整数(如果\(\alpha\)为浮点数),我们使用cv::saturate_cast来确保值有效。
  • 最后,我们以通常的方式创建窗口并显示图像。
注意
无需使用for循环访问每个像素,我们可以简单地使用以下命令:

其中cv::Mat::convertTo将有效地执行*new_image = a*image + beta*。但是,我们想向您展示如何访问每个像素。无论哪种方法,结果都相同,但convertTo方法经过优化,速度更快。

结果

  • 运行我们的代码,使用\(\alpha = 2.2\)和\(\beta = 50\)
    $ ./BasicLinearTransforms lena.jpg
    基本线性变换
    -------------------------
    * 输入alpha值 [1.0-3.0]:2.2
    * 输入beta值 [0-100]:50
  • 我们得到:

实践示例

在本段中,我们将运用所学知识,通过调整图像的亮度和对比度来校正曝光不足的图像。我们还将看到另一种校正图像亮度的技术,称为伽马校正。

亮度和对比度调整

增加/减少\(\beta\)值将向每个像素添加/减去一个常数值。像素值超出[0;255]范围将被饱和(即,高于255/低于0的像素值将被钳位到255/0)。

浅灰色表示原始图像的直方图,深灰色表示在GIMP中亮度为80时的直方图。

直方图表示对于每个颜色级别,具有该颜色级别的像素数量。暗图像将有很多具有低颜色值的像素,因此直方图在其左侧将出现峰值。添加常数偏差时,直方图将向右移动,因为我们已向所有像素添加了常数偏差。

\(\alpha\)参数将修改级别的扩展方式。如果\( \alpha < 1 \),颜色级别将被压缩,结果将是对比度较低的图像。

浅灰色表示原始图像的直方图,深灰色表示在GIMP中对比度< 0时的直方图。

请注意,这些直方图是使用GIMP软件中的亮度-对比度工具获得的。亮度工具应与\(\beta\)偏差参数相同,但对比度工具似乎与\(\alpha\)增益不同,其中输出范围在GIMP中似乎居中(正如您在上一个直方图中注意到的那样)。

使用\(\beta\)偏差可能会改善亮度,但同时图像可能会出现轻微的薄雾,因为对比度会降低。\(\alpha\)增益可用于减少这种影响,但由于饱和度,我们将丢失原始明亮区域中的某些细节。

伽马校正

伽马校正可用于通过使用输入值和映射输出值之间的非线性变换来校正图像的亮度。

\[O = \left( \frac{I}{255} \right)^{\gamma} \times 255\]

由于此关系是非线性的,因此对所有像素的影响将不同,并且取决于它们的原始值。

不同伽马值的曲线图

当\( \gamma < 1 \)时,原始暗区将更亮,直方图将向右移动,而当\( \gamma > 1 \)时则相反。

校正曝光不足的图像

下图已使用以下参数进行校正:\( \alpha = 1.3 \) 和 \( \beta = 40 \)。

By Visem (Own work) [CC BY-SA 3.0], via Wikimedia Commons

整体亮度得到了改善,但是您可以注意到,由于所用实现的数值饱和度(在摄影中称为高光剪切),云现在严重饱和。

下图已使用以下参数进行校正:\( \gamma = 0.4 \)。

By Visem (Own work) [CC BY-SA 3.0], via Wikimedia Commons

伽马校正应倾向于减少饱和度效应,因为映射是非线性的,并且与之前的方法不同,不存在数值饱和的可能性。

左:alpha、beta校正后的直方图;中:原始图像的直方图;右:伽马校正后的直方图

上图比较了三张图像的直方图(三个直方图之间的y范围不同)。您可以注意到,对于原始图像,大多数像素值位于直方图的下部。经过\(\alpha\),\(\beta\)校正后,我们可以观察到由于饱和度而在255处出现一个大峰值,以及向右的偏移。伽马校正后,直方图向右移动,但暗区中的像素移动得更多(参见伽马曲线)比亮区中的像素。

在本教程中,您已经看到了两种调整图像对比度和亮度的简单方法。这些是基本技术,并非旨在替代光栅图形编辑器!

代码

伽马校正代码

使用查找表可以提高计算性能,因为只需要计算一次256个值。

额外资源