Goal
- Initialize a matrix with zeros(零初始化矩阵))
- Access pixel values (获取像素)
- Learn what cv::saturate_cast does and why it is useful(使用saturate_cast避免超出范围)
- Get some cool info about pixel transformations(像素变换?)
- Improve the brightness of an image on a practical example(提高图片的亮度)
Theory
- 来源于《计算机视觉:算法以及应用》
Image Processing
- 通常是一个或者几个图像产生几个图像
- 图像变换:
- 点运算
- 邻域运算
Brightness and contrast adjustments
f(x):source image pixel,g(x):destination image pixel: 公式如下:很容易理解,不过多解释
Code
#include "opencv2/imgcodecs.hpp"#include "opencv2/highgui.hpp"
#include <iostream>
// we're NOT "using namespace std;" here, to avoid collisions between the beta variable and std::beta in c++17
using std::cin;
using std::cout;
using std::endl;
using namespace cv;
int main( int argc, char** argv )
{
double alpha = 1.0; /*< Simple contrast control */ //gain
int beta = 0; /*< Simple brightness control */ //bias
String imageName("lena.jpg"); // 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;
alpha = 2.2;
cout << "* Enter the beta value [0-100]: ";
//cin >> beta;
beta = 50;
//遍历所有的像素
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;
}
代码没有什么好解释的,挺简单的!
CMakeLists.txt文件
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(VMAKE_BUILD_TYPE "Debug")
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
install(TARGETS DisplayImage RUNTIME DESTINATION bin)
测试结果如下:
Brightness and contrast adjustments
bias可以提高图片的亮度,但同时由于对比度的降低,图片会略模糊(veil),这时候使用gain>=1解决(deminue)这个问题,也会损失一部分原图像的信息。
Gamma correction
gamma correction是一个非线性变换,会让黑色区域更亮,而较亮区域相对变黑。公式如下和图如下:
When γ<1, the original dark regions will be brighter and the histogram will be shifted to the right whereas it will be the opposite with γ>1.
Code
#include <iostream>#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
// we're NOT "using namespace std;" here, to avoid collisions between the beta variable and std::beta in c++17
using namespace cv;
namespace
{
/** Global Variables */
int alpha = 100;
int beta = 100;
int gamma_cor = 100;
Mat img_original, img_corrected, img_gamma_corrected;
void basicLinearTransform(const Mat &img, const double alpha_, const int beta_)
{
Mat res;
img.convertTo(res, -1, alpha_, beta_); //res = alpha*img+bata,其中-1表示尺寸相同
hconcat(img, res, img_corrected);
}
void gammaCorrection(const Mat &img, const double gamma_)
{
CV_Assert(gamma_ >= 0);
//![changing-contrast-brightness-gamma-correction]
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); //gamma transform table
Mat res = img.clone();
LUT(img, lookUpTable, res);
//![changing-contrast-brightness-gamma-correction]
hconcat(img, res, img_gamma_corrected);
}
void on_linear_transform_alpha_trackbar(int, void *)
{
double alpha_value = alpha / 100.0;
int beta_value = beta - 100;
basicLinearTransform(img_original, alpha_value, beta_value);
}
void on_linear_transform_beta_trackbar(int, void *)
{
double alpha_value = alpha / 100.0;
int beta_value = beta - 100;
basicLinearTransform(img_original, alpha_value, beta_value);
}
void on_gamma_correction_trackbar(int, void *)
{
double gamma_value = gamma_cor / 100.0;
gammaCorrection(img_original, gamma_value);
}
}
int main( int argc, char** argv )
{
String imageName("lena.jpg"); // by default,读取图片
if (argc > 1)
{
imageName = argv[1];
}
img_original = imread( imageName );
img_corrected = Mat(img_original.rows, img_original.cols*2, img_original.type()); //两个矩阵,需要容纳两个图片
img_gamma_corrected = Mat(img_original.rows, img_original.cols*2, img_original.type());
hconcat(img_original, img_original, img_corrected); //第一和第二个生成第三个
hconcat(img_original, img_original, img_gamma_corrected); //地一个和第二个生成第三个
namedWindow("Brightness and contrast adjustments", WINDOW_AUTOSIZE);
namedWindow("Gamma correction", WINDOW_AUTOSIZE);
createTrackbar("Alpha gain (contrast)", "Brightness and contrast adjustments", &alpha, 500, on_linear_transform_alpha_trackbar);
createTrackbar("Beta bias (brightness)", "Brightness and contrast adjustments", &beta, 200, on_linear_transform_beta_trackbar);
createTrackbar("Gamma correction", "Gamma correction", &gamma_cor, 200, on_gamma_correction_trackbar);
while (true)
{
imshow("Brightness and contrast adjustments", img_corrected);
imshow("Gamma correction", img_gamma_corrected);
int c = waitKey(30); //ESC:27
if (c == 27)
break;
}
imwrite("linear_transform_correction.png", img_corrected);
imwrite("gamma_correction.png", img_gamma_corrected);
return 0;
}
CMakeLists.txt文件:
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(VMAKE_BUILD_TYPE "Debug")
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
install(TARGETS DisplayImage RUNTIME DESTINATION bin)运行结果如下,且表面: 当alpha>=1和bias>=0时,图片亮度增加;当gamma<1时,图片亮度增加!