目标
在本教程中,将学习如何:
-
访问像素值
-
用零初始化矩阵
-
获取关于像素变换的一些很酷的信息
-
在实际的例子中提高图像的亮度
理论
图像处理
-
一般的图像处理算子是采用一个或多个输入图像并产生输出图像的函数。
-
图像变换可以看作:
-
点运算(像素变换)
-
邻域(区域)运算
像素变换
-
在这种图像处理变换中,每个输出像素的值只取决于相应的输入像素值(可能是一些全局采集的信息或参数)。
-
这些操作的示例包括亮度和对比度调整以及颜色校正和变换。
亮度和对比度调整
- 两个常用的点处理过程是乘法和加法:
- 参数α > 0和β通常被称为增益和偏置参数; 有时这些参数据分别控制对比度和亮度。
- 你可以想到f(x )作为源图像像素和g(x )作为输出图像像素。然后,我们可以更方便地将表达式写成:
i 和 j 表示像素位于第i行和第j列。
代码实现
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
double alpha = 1.0; /*< Simple contrast control */
int beta = 0; /*< Simple brightness control */
String imageName("lena.bmp"); // by default
if (argc > 1)
{
imageName = argv[1];
}
Mat image = imread(imageName);
Mat new_image = Mat::zeros(image.size(), image.type());
cout << " Basic Linear Transforms " << endl;
cout << "-------------------------" << endl;
cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
cout << "* Enter the beta value [0-100]: "; cin >> beta;
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>(alpha*(image.at<Vec3b>(y, x)[c]) + beta);
}
}
}
namedWindow("Original Image", WINDOW_AUTOSIZE);
namedWindow("New Image", WINDOW_AUTOSIZE);
imshow("Original Image", image);
imshow("New Image", new_image);
waitKey();
return 0;
}
解释
- 要访问图像中的每个像素,使用这种语法:image.at <Vec3b>(y,x)[c]其中y是行,x是列,c是R,G或B(0,1或2)。
- 由于操作α·p(i,j)+β可以给出值超出范围或不是整数(如果α是float),我们使用来确保这些值是有效的。
- 如果不使用for循环访问每个像素,我们可以简单地使用这个命令:
image.convertTo(new_image,-1,alpha,beta);
结果
image.png联系实际
在本段中,将通过调整图像的亮度和对比度来实践我们所学到的来校正曝光不足的图像。我们还将看到另一种技术来校正称为伽玛校正图像亮度。
亮度和对比度调整
增加(/减少)β值将为每个像素添加(/减少)常量值。像素值超出[0; 255]范围将饱和(即像素值高于0-255)将被钳位到0-255中。
浅灰色,原始图像的直方图;深灰色,在Gimp亮度= 80时直方图表示每个颜色级别具有该颜色级别的像素数。黑暗的图像将具有许多具有低颜色值的像素,因此直方图将在其左部分呈现峰值。当添加恒定偏差时,直方图向右移动,因为我们向所有像素添加了一个恒定的偏置。
该α参数将修改水平如何传播。如果α < 1,颜色级别将被压缩,结果将是对比度较小的图像。
浅灰色,原始图像的直方图;在Gimp中对比度<0时,呈深灰色请注意,这些直方图是使用Gimp软件中的Brightness-Contrast工具获得的。亮度工具应与β相同偏差参数,但对比度工具似乎不同于α 输出范围似乎以Gimp为中心的增益(可以注意到先前的直方图)。
可以发生的是修改β偏差将提高亮度,但是同时,随着对比度的降低,图像会出现轻微的面纱。该α 增益可以用来减少这种影响,但由于饱和度,我们将在原来的明亮区域中丢失一些细节。
伽玛校正
由于该关系是非线性的,因此对于所有像素的效果将不同,并且将取决于它们的原始值。
绘制不同的伽玛值当γ< 1,原始的黑暗区域会更亮,直方图将向右移动,而与γ相反> 1。
纠正曝光不足的图像
以下图像已更正:α = 1.3,β= 40
伽马校正应倾向于增加较少的饱和效应,因为映射是非线性的,并且没有像以前的方法那样的数值饱和。
左:直方图alpha,β校正; 中心:原始图像的直方图; 右:伽马校正后的直方图伽马校正代码:
Mat LookUpTable(1,256,CV_8U);
uchar * p = lookUpTable.ptr();
for(int i = 0; i <256; ++i)
p[i] = saturate_cast <uchar>(pow(i / 255.0,gamma_)* 255.0);
Mat res = img.clone();
LUT(img,lookUpTable,res);
查询表用于提高计算性能,因为只需要计算256个值。