OpenCV图像亮度与对比度调整
1. Mat类和图像基本操作
在OpenCV中,图像是通过Mat类(Matrix)表示的,这实际上是一个二维的矩阵,矩阵中的每个元素对应图像中的一个像素。一个图像的每个像素值都有多个通道,例如BGR图像每个像素包含三个值(蓝色、绿色和红色)。
-
src:输入图像。 -
dst:处理后的输出图像。 -
m:用于调整亮度或对比度的辅助矩阵。
2. 亮度调整的原理
亮度调整实际上是对每个像素值增加一个常数。例如,增加某个值会让所有像素变亮,减少某个值会让图像变暗。
代码中的亮度调整是通过add()函数实现的,它的作用是将输入图像src和一个辅助矩阵m按像素加和。
代码解析:
m = Scalar(lightness, lightness, lightness); // 创建一个与src同大小的矩阵m,每个元素的值为lightness
add(src, m, dst); // 将src和m相加,结果存入dst,实现亮度调整
-
Scalar(lightness, lightness, lightness):创建一个常量矩阵m,每个通道的值都为lightness。这个矩阵的作用是调整亮度。 -
add(src, m, dst):add函数会将图像src和矩阵m中的每个像素相加,结果保存在dst中。如果m的值是正的,图像就会变亮,负的则变暗。
3. 对比度调整的原理
对比度调整是通过放大或缩小像素值之间的差异来实现的。如果图像的像素差异被放大,对比度就增加;如果被缩小,对比度就降低。
代码解析:
addWeighted(image, 1.0, m, 0, b, dst); // 使用加权和来调整亮度
-
addWeighted():是OpenCV中用于加权合并两幅图像的函数。其公式为:
-
image是原始图像。 -
m是辅助矩阵,通常是零矩阵。 -
alpha和beta分别控制图像和矩阵的权重。 -
gamma是一个常数,用于调整亮度。
-
在这里,addWeighted(image, 1.0, m, 0, b, dst) 实现了通过加权合成图像来调整亮度,其中b代表亮度调整的值。
4. 滑动条(Trackbar)的使用
OpenCV中的**滑动条(Trackbar)**允许用户通过GUI界面实时控制图像的亮度和对比度。当滑动条的值发生变化时,会触发一个回调函数,从而实时更新图像。
代码解析:
createTrackbar("Value Bar:", "亮度调整", &lightness, max_value, on_track);
-
createTrackbar:用于创建一个滑动条控件,用来调整图像的参数(如亮度和对比度)。-
"Value Bar:":滑动条的标签。 -
"亮度调整":滑动条所在的窗口名称。 -
&lightness:指向亮度值的指针,滑动条的当前值会存储在lightness变量中。 -
max_value:滑动条的最大值,表示亮度的最大调整值。 -
on_track:当滑动条值发生变化时,会调用的回调函数。
-
5. 回调函数(Callback Function)
回调函数on_lightness和on_contrast在滑动条的值发生变化时被调用。每当用户调整滑动条时,on_track函数会被触发,它会重新计算亮度或对比度,并更新图像。
代码解析:
static void on_lightness(int b, void* userdata) {Mat image = *((Mat*)userdata); // 将用户数据(图像)转换为Mat类型Mat dst = Mat::zeros(image.size(), image.type()); // 创建一个空的目标图像Mat m = Mat::zeros(image.size(), image.type()); // 创建一个空的矩阵,用于亮度调整addWeighted(image, 1.0, m, 0, b, dst); // 调整亮度imshow("亮度与对比度调整", dst); // 显示调整后的图像
}
-
int b:表示当前滑动条的值,控制亮度。 -
(void* userdata):传递给回调函数的用户数据,这里是图像数据。 -
addWeighted(image, 1.0, m, 0, b, dst):通过加权合成图像来调整亮度。 -
imshow("亮度与对比度调整", dst):显示处理后的图像。
6. 总结:如何使用滑动条调整亮度和对比度
-
创建窗口:使用
namedWindow创建一个窗口来显示图像。 -
创建滑动条:通过
createTrackbar函数创建滑动条,用于调节图像的亮度和对比度。 -
回调函数:每当滑动条的值发生变化时,
on_lightness或on_contrast回调函数会被调用,重新计算图像的亮度和对比度,并更新显示的图像。 -
图像更新:通过
imshow实时显示调整后的图像。
7. 相关知识点总结
-
Mat类:OpenCV的图像表示方式,每个像素包含多个通道(例如BGR图像有三个通道)。 -
图像加法(
add):可以用来调整图像的亮度。 -
加权合成(
addWeighted):用于调整图像的亮度和对比度,通过设置权重和常数来加权合并两幅图像。 -
滑动条(Trackbar):提供一种交互方式,让用户实时调整图像的参数。
-
回调函数:当滑动条的值变化时触发回调函数,更新图像。
8. 代码演示
#include<opencv2/opencv.hpp>
#include <string.h>
using namespace cv;
const std::string picpath = "C:\\Users\\ZZM\\Pictures\\豆绘AI_3711794.jpg";Mat src, dst, m;
int lightness = 50; // 初始亮度值// 亮度调整的回调函数
static void on_lightness(int b, void* userdata) {Mat image = *((Mat*)userdata); // 获取用户传递的图像数据Mat dst = Mat::zeros(image.size(), image.type()); // 创建目标图像Mat m = Mat::zeros(image.size(), image.type()); // 创建一个零矩阵,用于亮度调整// 调整亮度addWeighted(image, 1.0, m, 0, b, dst);imshow("亮度与对比度调整", dst); // 显示调整后的图像
}// 对比度调整的回调函数
static void on_contrast(int b, void* userdata) {Mat image = *((Mat*)userdata); // 获取用户传递的图像数据Mat dst = Mat::zeros(image.size(), image.type()); // 创建目标图像Mat m = Mat::zeros(image.size(), image.type()); // 创建一个零矩阵,用于对比度调整double contrast = b / 100.0; // 将对比度值映射到[0, 2]范围addWeighted(image, contrast, m, 0, 0, dst); // 调整对比度imshow("亮度与对比度调整", dst); // 显示调整后的图像
}int main() {// 加载图像Mat image = imread(picpath);if (image.empty()) {std::cout << "无法加载图像!" << std::endl;return -1;}// 创建窗口namedWindow("亮度与对比度调整", WINDOW_NORMAL);resizeWindow("亮度与对比度调整", image.cols, image.rows);// 创建亮度滑动条int lightness = 50;int max_value = 250;createTrackbar("亮度:", "亮度与对比度调整", &lightness, max_value, on_lightness, (void*)(&image));// 创建对比度滑动条int contrast_value = 100;createTrackbar("对比度:", "亮度与对比度调整", &contrast_value, 200, on_contrast, (void*)(&image));// 初始亮度和对比度调整on_lightness(50, &image);on_contrast(100, &image);waitKey(0); // 等待用户按键return 0;
}

