知识点
理论;
代码演示;
理论
图像变换可以分为点操作和区域操作,区域操作用于做图像卷积,特征提取,角点检测,平滑…;点操作即像素变换,直接操作像素,调整图像亮度和对比度属于像素变换-点操作;
f(i,j)----输入图像像素点;
g(i,j)----输出图像像素点;
α----增益变量,α越大,亮度,对比度越强;
常见的RGB数据格式,像素值(0-255)(tif等格式像素可能小于0);
亮度即灰度,亮度越大,灰度值越大(0最黑,255最白)
API
//创建一张与原图像大小和类型一致的空白图像,像素值初始化为0
Mat new_image = Mat::zeros(image.size(),image.type());
//确保RGB像素值在正确范围内
saturate_cast<uchar>(value);
//给每个像素点每个通道赋值
Mat.at<Vec3b>(x,y)[index] = value;
Demo
编程实现对每个像素点的线性变换操作
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src, dst;
src = imread("C:\\Users\\hello\\Desktop\\2.jpg");
if (!src.data)
{
cout << "could not load the image" << endl;
return - 1;
}
cvtColor(src, src, CV_BGR2GRAY); //转换色彩空间为灰度图像
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.2;
float beta = 30;
Mat m1;
src.convertTo(m1, CV_32F); // 转换数据类型
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
//判断是单通道还是多通道
if (src.channels() == 3)
{
float b = m1.at<Vec3f>(row, col)[0]; //blue
float g = m1.at<Vec3f>(row, col)[1]; //green
float r = m1.at<Vec3f>(row, col)[2]; //red
//调整图像亮度,对比度
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(alpha * b + beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(alpha * g + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(alpha * r + beta); //保证像素在合理范围内
}
else if(src.channels() == 1)
{
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(alpha * v + beta);
}
}
}
char output_title[] = "contrast and brightness change demo";
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(output_title, dst);
waitKey(0);
return 0;
}