图像的对比度和亮度
目标
- 访问像素值
- 用0来初始化矩阵
- cv::saturate_cast
- 像素转换
- 提高一张图像的亮度
原理
图像处理
图像变换可以被视作两个步骤:
- 点操纵(像素转换)
- 相邻区域转换(以面积为基础)
像素转换
- 在这种图像处理的转换过程中,每个输出的像素的值都取决于相对应的输入的像素的值。
- 此类操作的示例包括亮度和对比度调整以及颜色校正和转换。
亮度和对比度的调整
- 两种常用的点处理是带常数的乘法和加法:

- 参数α > 0 和 β 通常被叫做gain和bias参数,该参数将被用来控制对比度和亮度。
- 你可以简单地把f(x)当作原图像素,g(x)当作输出图像的像素,那么我们可以将表达式写成:

此处的i和j代表像素点的位置,i行j列
源码
#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 )
{
// 加载图像CommandLineParser parser( argc, argv, "{@input | lena.jpg | input image}" );Mat image = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( image.empty() ){cout << "Could not open or find the image!\n" << endl;cout << "Usage: " << argv[0] << " <Input image>" << endl;return -1;}// 构建一个新的与原图相同(大小和类型)的像素为零的图像Mat new_image = Mat::zeros( image.size(), image.type() );// 获取参数 α和βdouble alpha = 1.0; /*< Simple contrast control */int beta = 0; /*< Simple brightness control */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;// 遍历图像,应用线性变化// 需注意一个像素点有三个通道(B,G,R or 0, 1, 2)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 );}}}imshow("Original Image", image);imshow("New Image", new_image);waitKey();return 0;
}
此外,除了使用上述的for循环来遍历图片的每一个像素点,我们还可以使用cv::Mat::convertTo来实现,只是上述代码用来更加详细的展示其应用过程。
image.convertTo(new_image, -1, alpha, beta);
α和β参数
伽马矫正是另一个用来矫正图片亮度的技术。增加或减少β值将会为每一个像素增加或减少一个固定的常量值。像素值不在[0,255]范围内的将会被饱和,超过255的被压缩到255,小于0的被压缩到0。

浅灰色为原始图像的直方图,Gimp中亮度= 80时为深灰色。(GIMP(GNU Image Manipulation Program)是一款自由和开源的图像编辑软件,用于图像的润色、编辑和制作。)
直方图表示每个颜色级别具有该颜色级别的像素数。深色图像会有许多低颜色值的像素,因此直方图会在其左侧呈现一个峰值。当添加恒定偏差时,直方图向右移动,因为我们已经向所有像素添加了恒定偏差。
α参数将会修改色阶分布的方式。如果α小于1,色阶将被压缩,结果将是一个对比度较低的图像。

浅灰色为原始图像的直方图,Gimp中对比度< 0时为深灰色。
请注意,这些直方图是使用Gimp软件中的亮度-对比度工具获得的。亮度工具应该与β偏置参数相同,但对比度工具似乎与α增益不同,其中输出范围似乎以Gimp为中心(正如您可以在前面的直方图中注意到的那样)。
简单来说,β和亮度相关,但在提高亮度的同时,对比度也会降低,图像会出现轻微的模糊。α增益可以用来通过调整对比度减少这种影响,但由于过于饱和,我们也可能失去一些原来明亮区域的细节。具体两个参数的值设置成多少要看具体需求。
伽马矫正
伽马矫正可以通过使用一个从输入的值到映射的输出值的非线性转换来矫正一个图像的亮度。如下所示:

由于联系的非线性,对于所有的像素的影响并不相同,且受限于其的原本的值。

当γ<1时,原本的黑暗区域将会变得更亮,直方图会向右平移,代表亮度的提高。这种情况适用于增强图像中暗处的细节。
当γ>1时,原本的明亮区域将会变得更暗,直方图会向左平移,代表亮度的减少。这种情况适用于则增强图像中亮部的细节或整体实现较暗的色调。
通过调整γ值,可以有效地根据需求来突出不同的特征。
实际的例子 link
举一个实际的例子,来矫正一个曝光不足的图片,参数为α=1.3,β=40

尽管整体亮度得到了提高,但是你仍然可以注意到,丢失了一些信息,比如图中的云,由于过度饱和失去了相应的细节。
当我们应用伽马矫正来进行相应的图片矫正,γ=0.4

由于映射是非线性的,并且不像以前的方法那样可能存在数值饱和,因此伽马校正能够添加较少的饱和效应,也就是说伽马矫正能够保留更多的细节,无论是原图中黑暗的区域还是明亮的区域。但是具体的γ值需要在使用中去实践。

上图比较了三个图像的直方图(三个直方图之间的y范围不相同)。您可以注意到,大多数像素值位于原始图像直方图的下部。校正后,我们可以在255处观察到一个大的峰值,这是由于饱和度以及右边的偏移。经过伽玛校正后,直方图向右偏移,但暗区像素比亮区像素偏移更大(见伽玛曲线图)。
代码部分
伽马矫正的代码如下:
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);
查询表被用来提高计算性能,伽马校正(LUT)的计算通常涉及到对每个像素进行幂运算,而查找表方法只需要预先计算出256个值,然后在实际处理图像时快速查找和应用这些预先计算的值,从而加快处理速度。
额外资源
- CRT显示器上的伽玛校正和图像
- 图形渲染中的伽马矫正
- 数码曝光技术
相关文章:
图像的对比度和亮度
目标 访问像素值用0来初始化矩阵cv::saturate_cast像素转换提高一张图像的亮度 原理 图像处理 图像变换可以被视作两个步骤: 点操纵(像素转换)相邻区域转换(以面积为基础) 像素转换 在这种图像处理的转换过程中…...
手撕设计模式——计划生育之单例模式
1.业务需求 大家好,我是菠菜啊。80、90后还记得计划生育这个国策吗?估计同龄的小伙伴们,小时候常常被”只生一个好“”少生、优生“等宣传标语洗脑,如今国家已经放开并鼓励生育了。话说回来,现实生活中有计划生育&…...
Mac M3 Pro 部署Flink-1.16.3
目录 1、下载安装包 2、解压及配置 3、启动&测试 4、测试FlinkSQL读取hive数据 以上是mac硬件配置 1、下载安装包 官网:Downloads | Apache Flink 网盘: Flink 安装包 https://pan.baidu.com/s/1IN62_T5JUrnYUycYMwsQqQ?pwdgk4e Flink 已…...
Mysql 的分布式策略
1. 前言 MySQL 作为最最常用的数据库,了解 Mysql 的分布式策略对于掌握 MySQL 的高性能使用方法和更安全的储存方式有非常重要的作用。 它同时也是面试中最最常问的考点,我们这里就简单总结下 Mysq 的常用分布式策略。 2. 复制 复制主要有主主复制和…...
记录一个利用winhex进行图片隐写分离的
前提 是一次大比武里面的题目,属实给我开了眼,跟我之前掌握的关于隐写合并的操作都不一样。 它不是直接在文件里面进行输入文件隐写,叫你输入密码,或者更改颜色,或者偏移位置; 它不是单纯几个文件合并&a…...
压缩映射定理证明
收缩映射定理(又称Banach不动点定理)是一个重要的结果,特别是在分析和应用数学中。 定理(收缩映射定理):假设是一个从度量空间 (X,d) 到自身的函数,如果 是一个收缩映射,即存在常数 …...
Ubuntu20.04.6操作系统安装教程
一、VMware Workstation16安装 选择安装VMware Workstation,登录其官网下载安装包,链接如下: 下载 VMware Workstation Pro 下载后运行安装向导,一直Next即可。 二、Ubuntu镜像下载 ubuntu20.04 选择需要下载的镜像类型下载即…...
(分治算法3)leecode 53 最大子数组和(最大子段和)
题目描述 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组是数组中的一个连续部分。 分治解法 这个问题可以分成从左半边数组找最大子段和从右半部分找最大子段和…...
【C++】模板初级
【C】模板初级 泛型编程函数模板函数模板的概念函数模板格式函数模板的原理函数模板的实例化模板参数的匹配原则 类模板类模板格式类模板的实例化 泛型编程 当我们之前了解过函数重载后可以知道,一个程序可以出现同名函数,但参数类型不同。 //整型 voi…...
eslint 使用单引号,Prettier使用双引号冲突
当 ESLint 规则要求使用单引号 (quotes: single) 而 Prettier 默认使用双引号时,会发生配置冲突。为了解决这个问题,你需要统一这两个工具的配置,确保它们遵循相同的规则。这里推荐两种解决方案: 解决方案 1: 修改 ESLint 配置以…...
进化生物学的数学原理 知识点总结
1、进化论与自然选择 1.1 进化论 1、进化论 过度繁殖 -> 生存竞争 -> 遗传和变异 -> 适者生存 2、用进废退学说与自然选择理论 用进废退:一步适应:变异 适应 自然选择:两步适应:变异 选择 适应 3、木村资生的中性…...
如何挑到高质量的静态IP代理?
在数字化时代,静态住宅IP代理已成为网络活动中不可或缺的一部分。无论是数据采集、网站访问,还是其他需要隐藏真实IP地址的在线活动,高质量的静态住宅IP代理都发挥着至关重要的作用。今天IPIDEA代理IP将详细介绍如何获取高质量的静态住宅IP代…...
vagrant putty错误的解决
使用Vagrant projects for Oracle products and other examples 新创建的虚机,例如vagrant-projects/OracleLinux/8。 用vagrant ssh可以登录: $ vagrant ssh > vagrant: Getting Proxy Configuration from Host...Welcome to Oracle Linux Server …...
图像分割——U-Net论文介绍+代码(PyTorch)
0、概要 原理大致介绍了一下,后续会不断精进改的更加详细,然后就是代码可以对自己的数据集进行一个训练,还会不断完善,相应其他代码可以私信我。 一、论文内容总结 摘要:人们普遍认为,深度网络成功需要数…...
C#进阶-ASP.NET的WebService跨域CORS问题解决方案
在现代的Web应用程序开发中,跨域资源共享(Cross-Origin Resource Sharing, CORS)问题是开发者经常遇到的一个挑战。特别是当前端和后端服务部署在不同的域名或端口时,CORS问题就会显得尤为突出。在这篇博客中,我们将深…...
如何利用TikTok矩阵源码实现自动定时发布和高效多账号管理
在如今社交媒体的盛行下,TikTok已成为全球范围内最受欢迎的短视频平台之一。对于那些希望提高效率的内容创作者而言,手动发布和管理多个TikTok账号可能会是一项繁琐且耗时的任务。幸运的是,通过利用TikTok矩阵源码,我们可以实现自…...
Java高级编程技术详解:从多线程到算法优化的全面指南
复杂度与优化 复杂度与优化在算法中的应用 算法复杂度是衡量算法效率的重要指标。了解和优化算法复杂度对提升程序性能非常关键。本文将介绍时间复杂度和空间复杂度的基本概念,并探讨一些优化技术。 时间复杂度和空间复杂度 时间复杂度表示算法执行所需时间随输…...
Redis 分布式锁过期了,还没处理完怎么办?
为了防止死锁,我们会给分布式锁加一个过期时间,但是万一这个时间到了,我们业务逻辑还没处理完,怎么办? 这是一个分布式应用里很常见到的需求,关于这个问题,有经验的程序员会怎么处理呢ÿ…...
Vue2+Element-ui后台系统常用js方法
el-dialog弹框关闭清空form表单并清空验证 cancelDialog(diaLog, formRef) {this[diaLog] falseif (formRef) {this.$refs[formRef].resetFields()} }页面使用: <el-dialog :visible.sync"addSubsidyDialog.dialog" close"cancelDialog(addSub…...
Kafka高频面试题整理
文章目录 1、什么是Kafka?2、kafka基本概念3、工作流程4、Kafka的数据模型与消息存储机制1)索引文件2)数据文件 5、ACKS 机制6、生产者重试机制:7、kafka是pull还是push8、kafka高性能高吞吐的原因1)磁盘顺序读写:保证了消息的堆积2)零拷贝机…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
