【算法随记四】自动色阶、对比度、直方图均衡等算法的一些小改进。
自动色阶、自动对比度以及直方图均衡这三个算法虽然很普通,也很简单,但是在实际应用中有着非常高的使用率,特别是在修图中,很多设计师打开一幅图,首先的的操作就是Shift+Ctrl+L(自动色阶)。在原理实现上,他们都属于基于直方图统计方面的算法,执行效率都非常之高。我在调整图像- 自动对比度、自动色阶算法一文中对他们的过程进行了详细的分析和解读,这里不在详述。
但是有的时候我们发现自动色阶或对比度等等会过调整或欠调整,在某个软件(不记得是那个了)中我发现了对他们的一些改进方式,其核心改进如下:
普通的方式:
for (int Y = 0; Y < 256; Y++) { if (Y < Min) Table[Y] = 0; else if (Y > Max) Table[Y] = 255; else Table[Y] = IM_ClampToByte((float)(Y - Min) / (Max - Min) * 255); }
改进后的方式:
float Avg = 0, Mean = 0, Sum = 0; for (int Y = 0; Y < 256; Y++) { Sum += Histgram[Y]; Avg += Y * Histgram[Y]; } Mean = Avg / Sum; float Gamma = log(0.5f) / log((float)(Mean - Min) / (Max - Min)); if (Gamma < 0.1f) Gamma = 0.1f; else if (Gamma > 10) Gamma = 10; for (int Y = 0; Y < 256; Y++) { if (Y < Min) Table[Y] = 0; else if (Y > Max) Table[Y] = 255; else Table[Y] = IM_ClampToByte(pow((float)(Y - Min) / (Max - Min), Gamma) * 255); }
其中的Max和Min的意思请参考其他的文章。
改进后的查找表考虑到全图的一个平均值信息,根据这个平局值来决定调整的一个Gamma值,相当于他同时结合了Gamma校正和自动色阶的思想,普通的自动色阶对应Gamma=1,还是拿一些我常用的测试图举例吧。
原图 标准的自动色阶 改进后的自动色阶
似乎改进后的更为合理。
对于直方图均衡化的改进,我在ImageJ的代码中找到这样一段话:
// Changes the tone curves of images. // It should bring up the detail in the flat regions of your image. // Histogram Equalization can enhance meaningless detail and hide important but small high-contrast features. This method uses a // similar algorithm, but uses the square root of the histogram values, so its effects are less extreme. Hold the alt key down // to use the standard histogram equalization algorithm. This code was contributed by Richard Kirk (rak@cre.canon.co.uk). // ImageJ\source\ij\plugin\ContrastEnhancer.java
他的核心代码修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private void equalize(ImageProcessor ip, int [] histogram) { ip.resetRoi(); if (ip instanceof ShortProcessor) { // Short max = 65535; range = 65535; } else { //bytes max = 255; range = 255; } double sum; sum = getWeightedValue(histogram, 0); for ( int i=1; i<max; i++) sum += 2 * getWeightedValue(histogram, i); sum += getWeightedValue(histogram, max); double scale = range/sum; int [] lut = new int [range+1]; lut[0] = 0; sum = getWeightedValue(histogram, 0); for ( int i=1; i<max; i++) { double delta = getWeightedValue(histogram, i); sum += delta; lut[i] = ( int )Math.round(sum*scale); sum += delta; } lut[max] = max; applyTable(ip, lut); } |
1 2 3 4 5 | private double getWeightedValue( int [] histogram, int i) { int h = histogram[i]; if (h<2 || classicEqualization) return ( double )h; return Math.sqrt(( double )(h)); } |
他这里主要是对直方图的数据进行了开根号,这样可以减少有些色阶特别集中的直方图对修正后的图像的影响,他可以解决普通的直方图均衡化有时候处理起来图像变换太大的问题,我们同样以上述两幅图来做示范。
原图 标准的直方图均衡化 改进后的直方图均衡化
可以明显的看到,标准的直方图均衡化对两幅图的处理都太过分,而改进后的则效果要和谐和自然很多。
这种改进还可以嵌入到很多其他的和直方图有关的算法中,比如CLAHE等等,也可以有效的改进他们的效果。
本人的SSE算法优化合集DEMO: https://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)