专栏首页一心无二用,本人只专注于基础图像算法的实现与优化。【算法随记四】自动色阶、对比度、直方图均衡等算法的一些小改进。

【算法随记四】自动色阶、对比度、直方图均衡等算法的一些小改进。

  自动色阶、自动对比度以及直方图均衡这三个算法虽然很普通,也很简单,但是在实际应用中有着非常高的使用率,特别是在修图中,很多设计师打开一幅图,首先的的操作就是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

  他的核心代码修改如下:

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);
}
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: http://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 13行代码实现最快速最高效的积分图像算法。

      研究图像到一定程度的人,应该都对积分图像有所了解,大家在百度或者google中都可以搜索到大量的相关博客,我这里不做多介绍。用积分图也确实能解决很多实际的问...

    用户1138785
  • 超像素经典算法SLIC的代码的深度优化和分析。

         现在这个社会发展的太快,到处都充斥着各种各样的资源,各种开源的平台,如github,codeproject,pudn等等,加上一些大型的官方的开源软件...

    用户1138785
  • SSE图像算法优化系列十二:多尺度的图像细节提升。

    无意中浏览一篇文章,中间提到了基于多尺度的图像的细节提升算法,尝试了一下,还是有一定的效果的,结合最近一直研究的SSE优化,把算法的步骤和优化过程分享给大家。...

    用户1138785
  • 自动色阶、对比度、直方图均衡等算法的一些小改进

    自动色阶、自动对比度以及直方图均衡这三个算法虽然很普通,也很简单,但是在实际应用中有着非常高的使用率,特别是在修图中,很多设计师打开一幅图,首先的的操作就是Sh...

    OpenCV学堂
  • poj-----Ultra-QuickSort(离散化+树状数组)

    Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submission...

    Gxjun
  • 堆排序

    Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

    用户2909867
  • 08:Challenge 1

    总时间限制: 10000ms单个测试点时间限制: 1000ms内存限制: 262144kB描述 给一个长为N的数列,有M次操作,每次操作是以下两种之一: (1)...

    attack
  • P1613 跑路

    题目描述 小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零。可是小A偏偏又有赖床的坏毛病。于是为了保住自己的工资,...

    attack
  • 一点思考|工作十几年了,竟从未用过do-while!

    最近在看 Java 的基础知识,其中有部分是关于循环的,在 Java 中,循环的语法总共分为 3 种: for、 while、 do-while,如下图所示:

    Java中文社群_老王
  • 【2020HBU天梯赛训练】7-48 重排链表

    给定一个单链表 L​1​​→L​2​​→⋯→L​n−1​​→L​n​​,请编写程序将链表重新排列为 L​n​​→L​1​​→L​n−1​​→L​2​​→⋯。例如...

    韩旭051

扫码关注云+社区

领取腾讯云代金券