目标:
在这个教程中你将学会如何去:
获取像素值;
用0去初始化一个矩阵;
Saturate_cast是做什么的以及为什么它很有用;
得到像素转换的一些参数;
理论:
图像处理:
一般通用的图像处理操作是这样一个函数:有一个或多个输入并且产生一个输出图像;
图像变换可以被看作:
点操作(像素转换);
领域操作(基于区域的);
像素转换:
在这种图像处理转换中,每一个输出像素的值取决于相应的输入的像素值;
这种操作的例子包括亮度和对比度的调整,以及颜色的修正和转换;
亮度和对比度的调整:
两种比较常用的点操作就是乘法以及和加上一个常数:
参数阿尔法大于零并且贝塔通常被称为增益以及偏差;有时这些参数被叫做控制相对地控制对比度和亮度的参数。
你可以认为f(X)是源操作图像,g(x)是输出图像。然后,更方便地,我们可以把表达式写成:
在这里,I,j表示第i行和第j列的像素值。
代码:
下面的代码就是应用上述的公式:
/***************************************************
****** Translator:York
****** Email:y_zhou1991@163.com
****** Date:2016/03/02
*****************************************************/
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace cv;
double alpha; /**< Simple contrast control */
int beta; /**< Simple brightness control */
int main(int argc, char** argv)
{
/// Read image given by user
Mat image = imread("F:/Photo/OpenCV_Photo/baboon.jpg");
Mat new_image = Mat::zeros(image.size(), image.type());
/// Initialize values
std::cout << " Basic Linear Transforms " << std::endl;
std::cout << "-------------------------" << std::endl;
std::cout << "* Enter the alpha value [1.0-3.0]: "; std::cin >> alpha;
std::cout << "* Enter the beta value [0-100]: "; std::cin >> beta;
/// Do the operation new_image(i,j) = alpha*image(i,j) + 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);
}
}
}
/// Create Windows
namedWindow("Original Image", 1);
namedWindow("New Image", 1);
/// Show stuff
imshow("Original Image", image);
imshow("New Image", new_image);
/// Wait until user press some key
waitKey();
return 0;
}
解释:
1、 我们通过创建参数让用户输入阿尔法和β来保存:
2、 使用imread载入图像,并且把它保存在一个Mat对象中:
3、 现在,因为我们将要对这幅图像做一些变换,所以我们需要一个新的Mat对象来保存它。同时,我们想要它具有以下特征:
a) 以0来初始化Mat对象;
b) 和源图像保持同样的尺寸和类型;
4、 现在,就是去应用最开始的那个公式去得到每一个像素值。因为我们是处理BGR图像,每一个像素我们将有三个值(B,G和R),所以我们将单独得到这些值。就是用下面一段代码实现:
注意下面的一些事项:
去得到图像中的每一个像素,我们使用这样的语法:image.at<Vec3b>(y,x)[c] ,其中y是行,x是列,c是R,G或B(0,1或2).
因为这个操作计算的结果可能超出整数的范围,我们可以使用saturate_cast来确保这个值是有效的。
1、 最后,我们创建窗口来显示图像。
注意:除了使用for循环来遍历每一个像素,我们还可以有一种更简单的命令:
image.convertTo(new_image, -1, alpha, beta);
这个函数就是这个公式:new_image = a*image + beta。然而,之所以用上面的方法是像让你知道如何去遍历每一个像素。在任何情况下,两个方法都是得到同样的结果,然而convertTo函数却更加地有效率且是经过优化了的。