在github上搜索代码Auto Gamma Correction,找到一个比较古老的代码,详见:https://github.com/PedramBabakhani/Automatic-Gamma-Correction,配套的代码使用VHDL语言写的,看了半天一个for循环没有,是在看不懂,幸好里面有篇算法对应的论文下载,论文名字叫《ASIC implementation of automatic gamma correction based on average of brightness 》,下载看了下,大概搞明白了他的大概意思。

  文章的核心思想很简单,就是他假定一幅合理的图像应该所有像素的平均值应该是0.5左右(归一化后的),所以那么自动伽马校正的伽马值就要使得目标图像向这个目标前进。

  假定X是图像的平均值,那么自动伽马需符合下述要求:

      

  一步一步的往下推导,有:

        -----》       --------》

  就是这么简单哪,如果写个代码也就是几分钟的事情。

int IM_AutoGammaCorrection(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride)
{
int Channel = Stride / Width;
if ((Src == NULL) || (Dest == NULL)) return IM_STATUS_NULLREFRENCE;
if ((Width <= 0) || (Height <= 0)) return IM_STATUS_INVALIDPARAMETER;
if ((Channel != 1) && (Channel != 3) && (Channel != 4)) return IM_STATUS_NOTSUPPORTED;
int AvgB, AvgG, AvgR, AvgA;
int Status = IM_GetAverageValue(Src, Width, Height, Stride, AvgB, AvgG, AvgR, AvgA);
if (Status != IM_STATUS_OK) return Status;
if (Channel == 1)
{
float Gamma = -0.3 / (log10(AvgB / 256.0f));
unsigned char Table[256];
for (int Y = 0; Y < 256; Y++) // 另外一种方式是:pow(Y / 255.0, 1.0 / Gamma)
{
Table[Y] = IM_ClampToByte((int)(pow(Y / 255.0f, Gamma) * 255.0f));
}
return IM_Curve(Src, Dest, Width, Height, Stride, Table, Table, Table);
}
else
{
float GammaB = -0.3 / (log10(AvgB / 256.0f));
float GammaG = -0.3 / (log10(AvgG / 256.0f));
float GammaR = -0.3 / (log10(AvgR / 256.0f)); unsigned char TableB[256], TableG[256], TableR[256];
for (int Y = 0; Y < 256; Y++) // 另外一种方式是:pow(Y / 255.0, 1.0 / Gamma)
{
TableB[Y] = IM_ClampToByte((int)(pow(Y / 255.0f, GammaB) * 255.0f));
TableG[Y] = IM_ClampToByte((int)(pow(Y / 255.0f, GammaG) * 255.0f));
TableR[Y] = IM_ClampToByte((int)(pow(Y / 255.0f, GammaR) * 255.0f));
}
return IM_Curve(Src, Dest, Width, Height, Stride, TableB, TableG, TableR);
}
}

  效果似乎还是很不错的。

    

  对于正常的图像,基本上没有啥变化,这也是必须要有的特性。

       

  论文里提出了另外一种更适合于硬件实现的方式。

  他把图像分成很多个16*16的小块,比如N*M个(文章中固定死了,也是16*16个),然后对16*16的小块,每次提取对应位置的一个像素,共计N*M个像素,计算这N*M像素的平均值,然后依据这个平均值计算出伽马值,这样就能计算出16*16个Gamma值,这些Gamma值肯定不会是完全相同的,文章中也统计了他们的差异大小,最后用这个256个gamma的平均值作为最后的正副图像的平均值。

  这代码写的有点狗屎 ......

  注意上面的取样是全部平均取样,不是某一个块集中取样。

  这样写的结果和全图取平均还是有一定区别的,不过效果基本上差不多。

  整个过程就这么简单,不过对于彩色图像,如果直接分通道实现,似乎会出现一定的偏色现象,我想这个不应该是Gamma调整该出现的作用,应该予以消除,如下所示:

   

  解决方法有把三通道求得的Gamma值再求平均值,作为每个通道的Gamma值,也可以对亮度通道做Gamma,然后在返回到RGB空间等等。

   

  如上所示,基本没有这个现象。

  当然,这种全局的Gamma校正还是有很多问题,比如容易出现块状,容易增强噪音等等,需要和某些局部算法结合在一起来实现更好的结果。

本文Demo下载地址:  http://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar,见其中的Adjust-> Auto Gamma Correction菜单。

【短道速滑二】古老的基于亮度平均值的自动Gamma校正算法。的更多相关文章

  1. SSE图像算法优化系列二十四: 基于形态学的图像后期抗锯齿算法--MLAA优化研究。

    偶尔看到这样的一个算法,觉得还是蛮有意思的,花了将近10天多的时间研究了下相关代码. 以下为百度的结果:MLAA全称Morphological Antialiasing,意为形态抗锯齿是AMD推出的完 ...

  2. 【计算机视觉】基于局部二值相似性模式(LBSP)的运动目标检测算法

    基于局部二值相似性模式(LBSP)的运动目标检测算法 kezunhai@gmail.com http://blog.csdn.net/kezunhai 本文根据论文:Improving backgro ...

  3. NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))

    NX二次开发API里没有对EXCAL读写操作的相关函数,市面上有很多种方法去实现,比如UFUN调KF,ODBC,OLE(COM组件)等等.这里我是用的OLE(COM组件)方式去做的,这种在VC上创建的 ...

  4. NX二次开发-基于NX开发向导模板的NX对Excel读写操作(OLE方式(COM组件))

    在看这个博客前,请读者先去完整看完:NX二次开发-基于MFC界面的NX对Excel读写操作(OLE方式(COM组件))https://ufun-nxopen.blog.csdn.net/article ...

  5. (二)基于商品属性的相似商品推荐算法——Flink SQL实时计算实现商品的隐式评分

    系列随笔: (总览)基于商品属性的相似商品推荐算法 (一)基于商品属性的相似商品推荐算法--整体框架及处理流程 (二)基于商品属性的相似商品推荐算法--Flink SQL实时计算实现商品的隐式评分 ( ...

  6. 基于Matlab的MMSE的语音增强算法的研究

    本课题隶属于学校的创新性课题研究项目.2012年就已经做完了,今天一并拿来发表.   目录: --基于谱减法的语音信号增强算法..................................... ...

  7. 基于OpenSLL的RSA加密应用(非算法)

    基于OpenSLL的RSA加密应用(非算法) iOS开发中的小伙伴应该是经常用der和p12进行加密解密,而且在通常加密不止一种加密算法,还可以加点儿盐吧~本文章主要阐述的是在iOS中基于openSL ...

  8. 基于模糊Choquet积分的目标检测算法

    本文根据论文:Fuzzy Integral for Moving Object Detection-FUZZ-IEEE_2008的内容及自己的理解而成,如果想了解更多细节,请参考原文.在背景建模中,我 ...

  9. 基于OpenSSL的RSA加密应用(非算法)

    基于OpenSSL的RSA加密应用(非算法) iOS开发中的小伙伴应该是经常用der和p12进行加密解密,而且在通常加密不止一种加密算法,还可以加点儿盐吧~本文章主要阐述的是在iOS中基于openSL ...

  10. 基于搜索的贝叶斯网络结构学习算法-K2

    基于搜索的贝叶斯网络结构学习算法-K2 2018-04-05 19:34:18 ItsBlue 阅读数 3172更多 分类专栏: 贝叶斯网络 网络结构学习   版权声明:本文为博主原创文章,遵循CC ...

随机推荐

  1. 如何优雅使用 vuex

    大纲 本文内容更多的是讲讲使用 vuex 的一些心得想法,所以大概会讲述下面这些点: Q1:我为什么会想使用 vuex 来管理数据状态交互? Q2:使用 vuex 框架有哪些缺点或者说副作用? Q3: ...

  2. C/C++ 运用VMI接口查询系统信息

    Windows Management Instrumentation(WMI)是一种用于管理和监视Windows操作系统的框架.它为开发人员.系统管理员和自动化工具提供了一种标准的接口,通过这个接口, ...

  3. 思科4331 语音网关配置, cisco 4331 router 配置文件

    GW01#cisco_ROUTER01#cisco_ROUTER01#sh clocisco_ROUTER01#cisco_ROUTER01#cisco_ROUTER01#cisco_ROUTER01 ...

  4. 【结对作业】 第一周 | 学习体会day05

    实现了单条地铁线路的直达 进行了页面的优化,实现了侧边栏功能 并且对第二天(今天)的任务进行了规划.

  5. Git使用(GitEE)

    Git分布式版本控制工具 1. Git概述 1.1 Git历史 Git 诞生于一个极富纷争大举创新的年代.Linux 内核开源项目有着为数众多的参与者. 绝大多数的 Linux 内核维护工作都花在了提 ...

  6. 【eBPF-01】初见:基于 BCC 框架的第一个 eBPF 程序

    闲言少叙,本文记录了如何零基础通过 BCC 框架,入门 eBPF 程序的开发,并实现几个简易的程序. 有关 eBPF 的介绍,网络上的资料有很多,本文暂且先不深入讨论,后面会再出一篇文章详细分析其原理 ...

  7. 香橙派5plus从ssd启动Ubuntu

    官方接口图 我实际会用到的就几个接口,背面的话就一个M.2固态的位置: 其中WIFI模块的接口应该也可以插2230的固态,不过是pcie2.0的速度,背面的接口则是pcie3.0*4的速度,差距还是挺 ...

  8. aspnetcore使用websocket实时更新商品信息

    先演示一下效果,再展示代码逻辑. 中间几次调用过程省略... 暂时只用到了下面四个项目 1.产品展示页面中第一次通过接口去获取数据库的列表数据 /// <summary> /// 获取指定 ...

  9. 《An End-to-end Model for Entity-level Relation Extraction using Multi-instance Learning》阅读笔记

    代码   原文地址   预备知识: 1.什么是MIL? 多示例学习(MIL)是一种机器学习的方法,它的特点是每个训练数据不是一个单独的实例,而是一个包含多个实例的集合(称为包).每个包有一个标签,但是 ...

  10. String 类和 STL (Standard Template Library)

    目录 一. string 类 1. 构造字符串 2. string类输入 3. 使用字符串 4. 其他string类方法 5. 字符串种类 一. string 类 很多应用程序都需要处理字符串.C语言 ...