一、亮度和对比度调整的理论依据
首先我们给出算子的概念。一般的图像处理算子都是一个函数,它接受一个或多个输入图像,并产生输出图像。下式给出了算子的一般形式:
或者
今天我们所讲解的图像亮度和对比度的调整操作,其实属于图像处理变换中比较简单的一种——点操作(pointoperators)。点操作有一个特点,仅仅根据输入像素值(有时可加上某些全局信息或参数),来计算相应的输出像素值。这类算子包括亮度(brightness)和对比度(contrast)调整,以及颜色校正(colorcorrection)和变换(transformations)。
最两种常用的点操作(或者说点算子),很显然,是乘上一个常数(对应对比度的调节)以及加上一个常数(对应亮度值的调节)。用公式表示出来就是这样:
看到这个式子,我们关于图像亮度和对比度调整的策略就呼之欲出了。
其中:
- 参数f(x)表示源图像像素。
- 参数g(x) 表示输出图像像素。
- 参数a(需要满足a>0)被称为增益(gain),常常被用来控制图像的对比度。
- 参数b通常被称为偏置(bias),常常被用来控制图像的亮度。
而更近一步,我们这样改写这个式子:
其中,i 和 j 表示像素位于第i行 和 第j列 。
那么,这个式子就可以用来作为我们在OpenCV中控制图像的亮度和对比度的理论公式,其实现方法可以通过addWeighted函数或for逐个访问图像像素实现。
例程:
// Bright_and_Contrast.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat srcImage;
int bright_init=1;
int contrast_init=1;
void bright_track(int,void*)
{
Mat dstImage;
//调用函数实现
addWeighted(srcImage,1,srcImage,0,bright_init,dstImage);
/************************************************************************/
/*
访问图像中像素实现三个for循环,执行运算 new_image(i,j) =a*image(i,j) + b
Mat dstImage(srcImage.rows,srcImage.cols,srcImage.type());
for(int y = 0; y < srcImage.rows; y++ )
{
for(int x = 0; x < srcImage.cols; x++ )
{
for(int c = 0; c < 3; c++ )
{
//使用saturate_cast防止像素值超值或者为浮点数
dstImage.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (contrast_init*0.01)*(srcImage.at<Vec3b>(y,x)[c] ) + bright_init );
} } } */
/************************************************************************/
imshow("Image",dstImage);
}
void contrast_track(int,void*)
{
Mat dstImage;
addWeighted(srcImage,contrast_init*0.02,srcImage,0,0,dstImage);
/************************************************************************/
/*
访问图像中像素实现三个for循环,执行运算 new_image(i,j) =a*image(i,j) + b
Mat dstImage(srcImage.rows,srcImage.cols,srcImage.type());
for(int y = 0; y < srcImage.rows; y++ )
{
for(int x = 0; x < srcImage.cols; x++ )
{
for(int c = 0; c < 3; c++ )
{
//使用saturate_cast防止像素值溢出或者为浮点数
dstImage.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (contrast_init*0.01)*(srcImage.at<Vec3b>(y,x)[c] ) + bright_init );
} } } */
/************************************************************************/
imshow("Image",dstImage);
}
int _tmain(int argc, _TCHAR* argv[])
{
srcImage=imread("1.jpg",1);
if (srcImage.empty())
{
cout<<"读入文件错误"<<endl;
return -1;
}
namedWindow("Image",CV_WINDOW_NORMAL);
imshow("Image",srcImage);
createTrackbar("亮度","Image",&bright_init,100,bright_track);
createTrackbar("对比度","Image",&contrast_init,100,contrast_track);
waitKey(0);
return 0;
}