OpenCV调整图像对比度和亮度

  • 一、学习目标
  • 二、原理理解
  • 三、对比度、亮度调整
  • 四、完整代码示例

一、学习目标

  • 理解图像对比度和亮度调整的原理
  • 对比三种不同亮度和对比度调整方法

二、原理理解

1、对比度
对比度指的是一幅图像中明暗区域最亮的白和最暗的黑之间不同亮度层级的测量,差异范围越大代表对比越大,差异范围越小代表对比越小,好的对比率120:1就可容易地显示生动、丰富的色彩,当对比率高达300:1时,便可支持各阶的颜色。但对比率遭受和亮度相同的困境,现今尚无一套有效又公正的标准来衡量对比率,所以最好的辨识方式还是依靠使用者眼睛。

对比度对视觉效果的影响非常关键,一般来说对比度越大,图像越清晰醒目,色彩也越鲜明艳丽;而对比度小,则会让整个画面都灰蒙蒙的。高对比度对于图像的清晰度、细节表现、灰度层次表现都有很大帮助。在一些黑白反差较大的文本显示、CAD显示和黑白照片显示等方面,高对比度产品在黑白反差、清晰度、完整性等方面都具有优势。相对而言,在色彩层次方面,高对比度对图像的影响并不明显。对比度对于动态视频显示效果影响要更大一些,由于动态图像中明暗转换比较快,对比度越高,人的眼睛越容易分辨出这样的转换过程。

2、亮度
图象亮度是指画面的明亮程度,单位是堪德拉每平米(cd/m2)或称nits。图象亮度是从白色表面到黑色表面的感觉连续体,由反射系数决定,亮度侧重物体,重在“反射”。亮度是一副图像给人的一种直观感受,如果是灰度图像,则跟灰度值有关,灰度值越高则图像越亮。在RGB图像中,亮度体现为每个点的像素值的大小,像素值越大,亮度越高。

3、对比度和亮度调整公式

参数α>0β通常被称为增益参数和偏置参数;有时这些参数被称为分别控制对比度和亮度。
可以认为 f(x) 是源图像像素,g(x) 是输出图像像素。然后,我们可以更方便地将表达式写成:

其中i和j表示像素位于第i行和第j列。α 作为系数乘以源像素值,会扩大最大像素值和最小像素值之间的差异,从而提升对比度。β 作为加数,直接增大源像素值,能提升亮度。

三、对比度、亮度调整

1、直接套用公式实现

for( int y = 0; y < image.rows; y++ ) {for( int x = 0; x < image.cols; x++ ) {for( int c = 0; c < image.channels(); c++ ) {new_image.at<Vec3b>(y,x)[c] =saturate_cast<uchar>( alpha*image.at<Vec3b>(y,x)[c] + beta );}}
}

执行操作 g(i,j) = α ⋅ f(i,j) + β ,访问图像中的每个像素。因为我们是在操作BGR图像,所以每个像素有三个值(B, G和R),所以我们需要分别访问它们。

2、使用 cv::Mat::convertTo() 函数
cv::Mat::convertTo 的函数原型为:

void cv::Mat::convertTo  (OutputArray    m,int           rtype,double        alpha = 1,double       beta = 0)  const
  • 参数 m:输出矩阵;如果在操作之前没有正确的大小或类型,则重新分配。
  • 参数 rtype:所需的输出矩阵类型,或者更确切地说,深度,通道的数量与输入相同;如果rtype为负,则输出矩阵将与输入矩阵具有相同的类型。
  • 参数 alpha:可选的比例因子,用于调整对比度。
  • 参数 beta:可选的缩放因子,用于调整亮度。
    该函数是Mat对象的一个方法,用于将Mat的数组转换为另一种可选伸缩的数据类型。
    该方法将源像素值转换为目标数据类型。其转换公式为:


satate_cast <> 应用于最后以避免可能的数值溢出。计算公式基本与对比度和亮度调整公式一致。

调用代码如下:

image.convertTo(new_image, -1, alpha, beta);

3、现有公式的问题分析及改进

  • 公式理解

增加(/减少) β 值将增加(/减少)一个常量值到每个像素。超过 [0,255] 范围的像素将过于饱和(即大于(或小于)255(/ 0)的像素值将被调整为255(/ 0))。

浅灰色为原始图像的像素值分布直方图,Gimp中亮度= 80时为深灰色

直方图表示每种颜色级别的像素数量。一个黑暗的图像将有许多低颜色值的像素,因此直方图将在其左侧呈现一个峰值。当添加一个恒定的偏置 β 时,直方图会向右移动,因为我们已经向所有像素添加了恒定的偏置。

α 参数将改变直方图的水平扩展。如果α<1,颜色级别将被压缩,结果将是一个对比度较低的图像。

浅灰色为原始图像的直方图,Gimp中对比度< 0时为深灰色

你会发现,调整β 偏置值将提高亮度,但同时图像会感觉蒙上了一层纱,因为对比度降低,α增益可以用来减小这种影响,但由于饱和,我们会丢失一些原始亮区的细节。

  • γ 校正

Gamma校正可以使用输入值和映射输出值之间的非线性转换来校正图像的亮度:

由于这种关系是非线性的,所有像素的效果将不相同,并将取决于它们的原始值。

绘制不同的伽玛值

γ<1 时,原始的暗区会变亮,直方图会向右移动,而γ>1 与之相反。

  • 使用查找表实现 γ校正
 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);
  • 效果对比

上图是直接套用公式调整对比度和亮度的效果,其中α=1.3 ,β=40。整体的亮度得到了提高,但是你可以注意到,由于存在数值饱和度(saturate_cast),云层已经非常饱和了。

上图是γ校正的效果,其中γ=0.4。gamma校正应该倾向于增加较少的饱和效应,因为映射是非线性的,而且不可能像在前一种方法中的数值饱和。

左:alpha, beta修正后直方图;中心:原始图像的直方图;右:gamma校正后的直方图

上图比较了三幅图的直方图(其中y的取值范围不同)。您可以注意到,大多数像素值都位于原始图像直方图的下方。经过α,β校正后,由于饱和和右移,我们可以在255处观察到一个大的峰值。经过伽马校正后,直方图向右移动,但黑暗区域的像素比明亮区域的像素移动更大(见伽马曲线图)。

四、完整代码示例

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;int main(int argc, char** argv)
{// 读入图像,判断读入是否成功string fileName = samples::findFile("O:\\CSDN\\7.jpg");Mat src = imread(fileName, IMREAD_COLOR);if (src.empty()){fprintf(stderr, "failed to load image: %s\n", fileName);system("pause");return EXIT_FAILURE;}Mat dst1, dst2, dst3;dst1 = Mat::zeros(src.size(), src.type());double alpha = 1.0;double beta = 0.0;double gama = 1.0;// 提示并输入 α  β  γ  的值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;cout << "* Enter the gama value [-1,1]: ";    cin >> gama;// 直接使用循环遍历每一个像素,应用公式double t1 = (double)getTickCount();for (int row=0;row<src.rows;++row)for(int col=0;col<src.cols;++col)for (int channel = 0; channel < src.channels(); ++channel){dst1.at<Vec3b>(row, col)[channel] = saturate_cast<uchar>(alpha * src.at<Vec3b>(row, col)[channel] + beta);}double time1 = ((double)getTickCount() - t1) / getTickFrequency();cout << "Method by pixel use time:" << time1 << "(ms)" << endl;// 调用 convertTo() 函数调整对比度和亮度double t2 = (double)getTickCount();src.convertTo(dst2, -1, alpha, beta);double time2 = ((double)getTickCount() - t2) / getTickFrequency();cout << "Method by pixel use time:" << time2 << "(ms)" << endl;// 构建查找表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, gama) * 255.0);// 使用查找表进行对比度亮度调整double t3 = (double)getTickCount();LUT(src, lookUpTable, dst3);double time3 = ((double)getTickCount() - t3) / getTickFrequency();cout << "Method by γ correct use time:" << time3 << "(ms)" << endl;// 调整窗体大小,显示调整效果namedWindow("original", WINDOW_NORMAL);resizeWindow("original", Size(src.cols / 2, src.rows / 2));imshow("original", src);namedWindow("pixel set", WINDOW_NORMAL);resizeWindow("pixel set", Size(src.cols / 2, src.rows / 2));imshow("pixel set", dst1);namedWindow("convertTo", WINDOW_NORMAL);resizeWindow("convertTo", Size(src.cols / 2, src.rows / 2));imshow("convertTo", dst2);namedWindow("γ correct", WINDOW_NORMAL);resizeWindow("γ correct", Size(src.cols / 2, src.rows / 2));imshow("γ correct", dst3);waitKey(0);system("pause");return EXIT_SUCCESS;
}

8、OpenCV调整图像对比度和亮度相关推荐

  1. OpenCV C++ 图像对比度和亮度

    目录 知识点 亮度和对比度调整原理 示例代码 reference 知识点 在本文中将了解到以下几个方面的内容: 1.C++ OpenCV访问像素值:2.用0初始化矩阵:3.saturate_cast起 ...

  2. OpenCV之图像对比度、亮度值调整

    先上代码 #include <iostream> #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> ...

  3. 【图像处理】OpenCV系列五 --- 图像对比度、亮度值调整

    今天呢,我们一起学习一下,如何调整图像的对比度以及亮度. 一.原理 调整图像亮度与对比度所用的公式 g(i,j) = a * f(i,j) + b 其中,i 和 j 表示像素位于第i行 和 第j列 . ...

  4. opencv计算图像亮度调节_OpenCV教程创建Trackbar图像对比度、亮度值调整

    这篇文章中我们一起学习了如何在OpenCV中用createTrackbar函数创建和使用轨迹条,以及图像对比度.亮度值的动态调整. 文章首先详细讲解了OpenCV2.0中的新版创建轨迹条的函数crea ...

  5. 【OpenCV】OpenCV实战从入门到精通之 -- 图像对比度、亮度值调整

    理论依据 首先了解一下算子的概念.一般的图像处理算子都是一个函数,它接受一个或多个输入图像,并产生输出图像.下面是算子的一般形式: 或者 图像亮度和对比度的次奥做属于图像变换中比较简单的点操作(poi ...

  6. 《OpenCV3编程入门》学习笔记5 Core组件进阶(四)图像对比度、亮度值调整

    第5章 Core组件进阶 5.4 图像对比度.亮度值调整 5.4.1 理论依据 1.算子:一般图像处理算子都是一个函数,接受一个或多个输入图像,并产生输出图像 2.算子一般形式: 3.点操作(poin ...

  7. OpenCV调整图像的亮度

    OpenCV调整图像的亮度 像素越靠近0图像越按,越靠近255,图像越亮,所以调整图片的亮度也就是调整每个像素点数值的大小. 原图 代码 public class DemoMat {static{Sy ...

  8. 提升图像对比度和亮度

    目录 一 提升图像对比度和亮度 二 代码实现 三 实现效果 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 提升图像对比度和亮度 一般来说图像的变换可以分成以下两类: (1)像素变换 在像素 ...

  9. OpenCV之图像对比度与亮度调整(C++实现)

    图像对比度和亮度的调整,属于图像处理中的点操作,其有一个特点:仅仅根据输入像素的值,来计算相应的输出像素值.这列蒜子包括亮度和对比度调整.颜色校正和变换. 最常用的点操作是乘以一个常数,再加上一个常数 ...

  10. python3-opencv库(4)--图片像素运算,利用加权叠加调节图像对比度和亮度

    版权声明:转载请注明原作者及出处 本文所涉及的一切图像像素运算,前提都是两张图尺寸相同,通道数相同 import numpy as np from cv2 import cv2"" ...

最新文章

  1. 找回丢失的mysql root 用户密码
  2. EntityFramework之原始查询及性能优化(六)
  3. DCMTK:测试图像像素模块功能
  4. 准备写个nhibernate的学习笔记
  5. 聊一聊声明式接口调用与Nacos的结合使用
  6. Android 下拉式抽屉折叠动画
  7. Vue中数组变动监听
  8. java 定时任务spring_Spring实现定时任务调度
  9. Linux MySQL单实例源码编译安装5.6
  10. PHP:打造一个无限极评论模块
  11. c#命名规范(转载)
  12. top conference in AI
  13. Xshell免费版安装 常用连接linux工具
  14. PCS7 入门指南 v9.0 SP3 v9.1 中文版 学习资料 (官方公开可用资料)
  15. Ubuntu下.tar.bz2和.tar.gz文件的解压命令
  16. 【U8+】去掉填制凭证界面金额中的网格
  17. 【“计算机科学与技术”专业小白成长系列】 计算机操作系统简介
  18. 25个Java机器学习工具和库
  19. Windows11 ISO原版系统镜像
  20. 《前端》eval函数

热门文章

  1. 短视频剪辑的九大技巧分享
  2. Excel密码解除方法 破解
  3. 艺术留学|工业设计专业2019大学新排名
  4. 计算机策略组怎么设置,怎么设置win7系统中的组策略
  5. word整个表格首行缩进_word表格怎么首行缩进 word表格内容缩进
  6. 新员工来到项目组的愿景_为您的项目设定愿景
  7. 夜神模拟器+Burp抓包(简直是后端复现调试的福音)
  8. BLDC (无刷直流电机) 六步式控制方法
  9. go和python哪个好就业_python就业方向哪个好?没基础学python
  10. 【C语言】 文件指针编程应用