图像亮度通俗理解便是图像的明暗程度,数字图像 f(x,y) = i(x,y) r(x, y) ,如果灰度值在[0,255]之间,则 f 值越接近0亮度越低,f 值越接近255亮度越高。而且我们也要把亮度和对比度区分开来,正如上述提的对比度指的是最高和最低灰度级之间的灰度差。
饱和度指的是图像颜色种类的多少, 上面提到图像的灰度级是[Lmin,Lmax],则在Lmin、Lmax 的中间值越多,便代表图像的颜色种类多,饱和度也就更高,外观上看起来图像会更鲜艳,调整饱和度可以修正过度曝光或者未充分曝光的图片。使图像看上去更加自然
对于数字图像变换,设原像素灰度为 f(i,j),转化后的像素灰度为 g(i,j),则常用的线性变换是 g(i,j)= af(i,j) + b, 其中系数 a 影响图像的对比度,系数 b 影响图像的亮度,具体如下:
(1) a=1时是原图;
(2) a>1时对比度增强,图像看起来更加清晰;
(3) a<1时对比度减弱,图像看起来变暗;
(4) b影响图像的亮度,随着增加b (b>0)和减小b (b>0),图像整体的灰度值上移或者下移, 也就是图像整体变亮或者变暗, 不会改变图像的对比度
常用代码:
在opencv中图像数据是存放在Mat数据类型中,我们知道一个像素有rgb构成,所以Mat是个三维数组,一下就是简单的获取mat中图像像素。
//三个for循环,执行运算 new_image(i,j) =a*image(i,j) + b for(int y = 0; y < image.rows; y++ ) { for(int x = 0; x < image.cols; x++ ) { for(int c = 0; c < 3; c++ ) { new_image.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (g_nContrastValue*0.01)*(image.at<Vec3b>(y,x)[c] ) + g_nBrightValue ); } } }
上述代码中image.at<Vec3b>(y,x)[c] 其中,y是像素所在的行, x是像素所在的列, c是R、G、B(对应0、1、2)其中之一。
saturate_cast为了安全转换,运算结果可能超出像素取值范围(溢出),还可能是非整数(如果是浮点数的话),用saturate_cast对结果进行转换,以确保它为有效值。
代码如下:
//-----------------------------------【头文件包含部分】--------------------------------------- // 描述:包含程序所依赖的头文件 //---------------------------------------------------------------------------------------------- #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "opencv2/imgproc/imgproc.hpp" #include <iostream> //-----------------------------------【命名空间声明部分】--------------------------------------- // 描述:包含程序所使用的命名空间 //----------------------------------------------------------------------------------------------- using namespace std; using namespace cv; //-----------------------------------【全局函数声明部分】-------------------------------------- // 描述:全局函数声明 //----------------------------------------------------------------------------------------------- static void ContrastAndBright(int, void *); //-----------------------------------【全局变量声明部分】-------------------------------------- // 描述:全局变量声明 //----------------------------------------------------------------------------------------------- int g_nContrastValue; //对比度值 int g_nBrightValue; //亮度值 Mat g_srcImage, g_dstImage; //-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始 //----------------------------------------------------------------------------------------------- int main() { //改变控制台前景色和背景色 system("color 2F"); // 读入用户提供的图像 g_srcImage = imread("E:\VS2015Opencv\vs2015\project\picture\cat.jpg"); if (!g_srcImage.data) { printf("读取g_srcImage图片错误~! "); return false; } g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type()); //设定对比度和亮度的初值 g_nContrastValue = 80; g_nBrightValue = 80; //创建窗口 namedWindow("【效果图窗口】", 1); //创建轨迹条 createTrackbar("对比度:", "【效果图窗口】", &g_nContrastValue, 300, ContrastAndBright); createTrackbar("亮 度:", "【效果图窗口】", &g_nBrightValue, 200, ContrastAndBright); //调用回调函数 ContrastAndBright(g_nContrastValue, 0); ContrastAndBright(g_nBrightValue, 0); //输出一些帮助信息 cout << endl << " 运行成功,请调整滚动条观察图像效果 " << " 按下“q”键时,程序退出 "; //按下“q”键时,程序退出 while (char(waitKey(1)) != 'q') {} return 0; } //-----------------------------【ContrastAndBright( )函数】------------------------------------ // 描述:改变图像对比度和亮度值的回调函数 //----------------------------------------------------------------------------------------------- static void ContrastAndBright(int, void *) { // 创建窗口 namedWindow("【原始图窗口】", 1); // 三个for循环,执行运算 g_dstImage(i,j) = a*g_srcImage(i,j) + b for (int y = 0; y < g_srcImage.rows; y++) { for (int x = 0; x < g_srcImage.cols; x++) { for (int c = 0; c < 3; c++) { g_dstImage.at<Vec3b>(y, x)[c] = saturate_cast<uchar>((g_nContrastValue*0.01)*(g_srcImage.at<Vec3b>(y, x)[c]) + g_nBrightValue); } } } // 显示图像 imshow("【原始图窗口】", g_srcImage); imshow("【效果图窗口】", g_dstImage); }
效果图: