OpenCV(C++)图像处理基础05:图像的亮度与对比度
Posted 源代码杀手
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV(C++)图像处理基础05:图像的亮度与对比度相关的知识,希望对你有一定的参考价值。
0、知识点
案例: 像素值越接近255越白。两参数则是调整像素和对比度。
Api接口:
复习Vec3f :
Vec3f表示的是3通道float类型的 Vect,就相当于3通道float类型的图像(这是其中一个具体化),解释可以从源代码中看出来。
下面给出一个具体的例子:
Vec3f point = Vec3f(10,10,3.2);//Float, 3 components
Mat mat(3,3,CV_32FC3,);//3 channel matrix
Vec3f v3f = mat.at(y, x);//read color values for pixel (y,x)
这里注释一下:Vec3f是一种数据类型,其是3通道的float,后面的mat.at(y, x)是访问图像的一种方式。(可以从定义形式上看出来 int a=…)
对于mat的理解,可以认为mat.at是mat的一种访问形式,其有点类似vector。
复习Vec3b:
Vec3b可以看作是vector<uchar, 3>。
简单而言就是一个uchar类型的,长度为3的vector向量。
由于在OpenCV中,使用imread读取到的Mat图像数据,都是用uchar类型的数据存储,对于RGB三通道的图像,每个点的数据都是一个Vec3b类型的数据。使用at定位方法如下:
img.at(row, col)[0] = 255; // 这是指修改B通道数据
img.at(row, col)[1] = 255; // 这是指修改G通道数据
img.at(row, col)[2] = 255; // 这是指修改R通道数据
1、测试代码
创建一张跟原图像大小和类型一致的空白图像,像素值初始化为0;
saturate_cast(value)确保值在0-255之间;
Mat.at(y,x)[index] = value每个像素点每个通道赋值
测试图像:
测试代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
#if 1
int main(int argc, char** argv) {
Mat src, dst;
//图片路径
src = imread("D:/CV2021/opencv_test0/Project1/test_img/40c.png");
if (!src.data) {
printf("could not load image...\\n");
return -1;
}
char input_win[] = "input image";
//cvtColor(src, src, CV_BGR2GRAY); //灰度
namedWindow(input_win, CV_WINDOW_AUTOSIZE);
imshow(input_win, src);
// contrast and brigthtness changes
int height = src.rows;
int width = src.cols;
dst = Mat::zeros(src.size(), src.type());//图像初始化 BGR
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) {
//RGB三通道
float b = src.at<Vec3b>(row, col)[0];// blue
float g = src.at<Vec3b>(row, col)[1]; // green
float r = src.at<Vec3b>(row, col)[2]; // red
// output:亮度和对比度处理
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r * alpha + beta);
}
else if (src.channels() == 1) {
//灰度值
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);
}
}
}
char output_title[] = "contrast and brightness change demo";
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(output_title, dst);
waitKey(0);
return 0;
}
#endif
测试结果:
2、补充:convertTo的用法
函数原型:
void Mat::convertTo( Mat& m, int rtype, double alpha=1, double beta=0 )
参数解释:
m 目标矩阵。如果m的大小与原矩阵不一样,或者数据类型与参数不匹配,那么在函数convertTo内部会先给m重新分配空间。
rtype 指定从原矩阵进行转换后的数据类型,即目标矩阵m的数据类型。当然,矩阵m的通道数应该与原矩阵一样的。如果rtype是负数,那么m矩阵的数据类型应该与原矩阵一样。
alpha 缩放因子。默认值是1。即把原矩阵中的每一个元素都乘以alpha。
beta 增量。默认值是0。即把原矩阵中的每一个元素都乘以alpha,再加上beta。
功能
把一个矩阵从一种数据类型转换到另一种数据类型,同时可以带上缩放因子和增量,公式如下:
m(x,y)=saturate_cast(alpha*(*this)(x,y)+beta);
由于有数据类型的转换,所以需要用saturate_cast来处理数据的溢出。
三通道测试,测试代码:
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) {
//RGB三通道
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
// output:亮度和对比度处理
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r * alpha + beta);
测试结果:
在灰度基础上,测试代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
#if 1
int main(int argc, char** argv) {
Mat src, dst;
//图片路径
src = imread("D:/CV2021/opencv_test0/Project1/test_img/40c.png");
if (!src.data) {
printf("could not load image...\\n");
return -1;
}
char input_win[] = "input image";
cvtColor(src, src, CV_BGR2GRAY);
namedWindow(input_win, CV_WINDOW_AUTOSIZE);
imshow(input_win, src);
// contrast and brigthtness changes
int height = src.rows;
int width = src.cols;
dst = Mat::zeros(src.size(), src.type());//图像初始化 BGR
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) {
//RGB三通道
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
// output:亮度和对比度处理
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r * alpha + beta);
}
else if (src.channels() == 1) {
//灰度值
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);
}
}
}
char output_title[] = "contrast and brightness change demo";
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(output_title, dst);
waitKey(0);
return 0;
}
#endif
测试结果:
去掉灰度,进行降低对比度的操作: float alpha = 0.2;测试结果:
参考文献
https://www.cnblogs.com/suubai/p/12485417.html
http://www.360doc.com/content/16/1202/09/35269117_611224795.shtml
https://blog.csdn.net/xiongwen_li/article/details/78523670
https://www.bbsmax.com/A/GBJrKeQK50/
以上是关于OpenCV(C++)图像处理基础05:图像的亮度与对比度的主要内容,如果未能解决你的问题,请参考以下文章