OpenCV 4.13.0
开源计算机视觉库 (Open Source Computer Vision)
正在加载...
正在搜索...
未找到匹配项
更改图像的对比度和亮度!

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

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

目标

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

  • 访问像素值
  • 使用零初始化矩阵
  • 了解 cv::saturate_cast 的作用及其重要性
  • 获取有关像素变换的一些有用的信息
  • 在实际示例中提高图像的亮度

理论

注意
以下解释来自 Richard Szeliski 的著作《计算机视觉:算法与应用

图像处理

  • 通用的图像处理算子是接收一个或多个输入图像并生成输出图像的函数。
  • 图像变换可以看作是
    • 点算子(像素变换)
    • 邻域(基于区域)算子

像素变换

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

亮度与对比度调整

  • 两个常用的点过程是乘以常数和加上常数

    \[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 值的图

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

校正曝光不足的图像

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

由 Visem(自创)[CC BY-SA 3.0],来自 Wikimedia Commons

整体亮度有所提高,但您会注意到云层现在严重饱和,这是由于使用的实现的数值饱和(摄影中的高光剪辑)。

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

由 Visem(自创)[CC BY-SA 3.0],来自 Wikimedia Commons

伽马校正应倾向于产生较少的饱和效果,因为映射是非线性的,并且不像上一种方法那样存在数值饱和。

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

上图比较了三张图像的直方图(三张直方图的 y 轴范围不尽相同)。您可以注意到,原始图像的大多数像素值都位于直方图的较低部分。在 \(\alpha\)、\(\beta\) 校正后,我们可以观察到 255 处有一个大的峰值,这是由于饱和以及向右的移动。伽马校正后,直方图向右移动,但暗部区域的像素比亮部区域的像素移动更多(请参阅伽马曲线)。

在本教程中,您已经了解了两种调整图像对比度和亮度的简单方法。**它们是基本技术,不应取代光栅图形编辑器!**

代码

伽马校正的代码

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

其他资源