一、原理
1、图像变换:(1)像素变换---点操作
(2)领域操作---区域
调整图像亮度和对比度属于像素变换---点操作。
2、亮度与对比度的调节主要基于下面的公式,其中g(i,j)为处理前的图像,f(i,j)为处理后的图像:
g(i,j) = alpha * f(i,j) + beta,其中alpha>0,beta是增益变量。
这个公式是一个线性的变换,通过调整alpha和beta的值就会得到不同的效果。基本原理是这样的,图像f(i,j)乘以一个大于1的alpha值的时候,图像f(i,j)中的像素值之间的差异就会变大,因此对比度就会增强,如果alpha值在0~1之间对比度就会减小。后面的beta是一个增益变量,如果beta取正数的话,图像亮度就会变大,取负数的话图像亮度就会减小。
二、API
1、Mat new_image = Mat::zero(image.size(), image.type);
创建一张跟原图大小和类型一致的空白图像、像素初始为0。
2、image.at<uchar>(i,j):取出灰度图像中i行j列的点。
image.at<Vec3b>(i,j)[k]:取出彩色图像中i行j列第k通道的颜色点。其中uchar,Vec3b都是图像像素值的类型,不要对Vec3b这种类型感觉害怕,其实在core里它是通过typedef Vec<T,N>来定义的,N代表元素的个数,T代表类型。
3、saturate_cast<uchar>(value);
确保值大小为0~255。
三、代码
#include<opencv2/opencv.hpp>
#include<highgui.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc,char**argv)
{
Mat src,dst;
//输入并验证是否有数据
src=imread("1.jpg");
if(!src.data )
{
printf("could not load image../n");
return -1;
}
char input_win[]="input image";
//另一种定义图片框名字方法
namedWindow(input_win,CV_WINDOW_AUTOSIZE);
imshow(input_win,src);
int height=src.rows;
int width=src.cols ;
dst = Mat::zeros(src.size(), src.type());//创建一张与输入图像大小相等、类型相同的空白图片
float alpha=1.5,beta=10;//定义系数
for(int row=0; row<height;row++)//利用for函数保证不越界
{
for(int col=0;col<width;col++)
{
//分情况对对比度和亮度进行操作
if (src.channels()==3)//三通道
{
float b=src.at <Vec3b>(row,col)[0];//注意格式和数据类型
float g=src.at <Vec3b>(row,col)[1];
float r=src.at <Vec3b>(row,col)[2];
dst.at <Vec3b>(row,col)[0]=saturate_cast<uchar>(b*alpha+beta);
dst.at <Vec3b>(row,col)[1]=saturate_cast<uchar>(g*alpha+beta);
dst.at <Vec3b>(row,col)[2]=saturate_cast<uchar>(r*alpha+beta);
}
else if(src.channels()==1)//单通道
{
float v=src.at<uchar>(row,col);
dst.at <uchar>(row,col)=saturate_cast<uchar>(v*alpha+beta);
}
}
}
char output_title[]=("contrast and brightness chage demo");
namedWindow(output_title,CV_WINDOW_AUTOSIZE);
imshow(output_title,dst);
waitKey(0);
return(0);
}
四、调试结果