原理:
在opencv改变图像的对比度和亮度本质是对像素点的操作,一个像素映射到另一个像素,用数学表示就是f(x,y)--->g(x,y),改变对比度和亮度的公式是g(i,j)=α⋅f(i,j)+β。其中α控制对比度,β控制亮度。有几种实现方法。
1.遍历图像访问每个像素并改变像素,为了提高遍历效率最好使用指针来遍历,用函数cv::ptr(x)或cv::ptr(x,y)。
//部分代码
uchar *p, *pt;
float a = 1.2;//对比度
int b = 50;//亮度
//对通道数量不同的图像做不同处理
if (channel == 1)
{
for (int i = 0; i < src.rows; i++)
{
pt = src.ptr(i);
p = dst.ptr(i);
for (int j = 0; j < src.cols; j++)
{
p[j] = saturate_cast<uchar>(a * pt[j] + b);
}
}
}
else
{
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
pt = src.ptr(i,j);
p = dst.ptr(i,j);
for (int c = 0; c < src.channels(); c++)
{
p[c] = saturate_cast<uchar>(a * pt[c] + b);
}
}
}
}
由于操作可以使结果超出范围或不是整数(如果是float),我们使用cv :: saturate_cast函数来确保值是有效的。
2.直接用矩阵的运算:new_image = a * image + b
注意image和new_image的大小(长宽)、类型要一样
//部分代码
src = imread("./src/img4.jpg", IMREAD_UNCHANGED);
dst = Mat::zeros(src.size(), src.type());
float a = 1.2;//对比度
int b = 50;//亮度
dst = a * src + b;
3.高效率的方法:cv :: Mat :: convertTo(out, rtype, alpha, beta)
out是转换的图像,rtype是输出矩阵的类型, alpha和beta分别是对比度和亮度。该函数是经过优化的opencv函数,所以运算效率要快的多。
//部分代码
src = imread("./src/img4.jpg", IMREAD_UNCHANGED);
dst = Mat::zeros(src.size(), src.type());
float a = 1.2;//对比度
int b = 50;//亮度
src.convertTo(dst, -1, a, b);