PS色调均化滤镜的快捷实现(C#源代码)。

  photoshop色调均化功能通常是在进行修片处理前期比较常用的功能之一,其对扩展图像的对比度,增强视觉效果有一定的作用。在很多课本或者文章中,也称这种处理为灰度均衡化、直方图均衡化等等。算法原理都是对原始图像统计其直方图,然后通过累计分布函数,重新隐射直方图数据,使每个色阶的的分布概率都往一致的方向调整。我看到的网络上的代码,抑或是一些教材中的代码,对这个过程的描述都是相当的冗余,要么是代码累赘,效率低下,要么是萝莉啰唆,很是难受。

    在给出我的代码之前,还需要说明一些问题。对于灰度图像,由于只有一个通道,这个问题不明显,对于常见的24位图像,由于有RGB三个通道,那就存在是每个通道都单独均衡还是三通道联合计算直方图,然后利用相同的映射表在隐射RGB数据了,经过我的测试,在Photoshop中,是取的后者。

    for (Y = 0; Y < Height; Y++)
    {
        Pointer = Scan0 + Y * Stride;               // 定位到每个扫描行的第一个像素,以避免溶于数据的影响
        for (X = 0; X < Width; X++)
        {
            HistGram[*Pointer]++;                   // Blue
            HistGram[*(Pointer + 1)]++;             // Green
            HistGram[*(Pointer + 2)]++;             // Red    
            Pointer += 3;                           // 移向下一个像素
        }
    }
    Num = 0;
    for (Y = 0; Y < 256; Y++)
    {
        Num = Num + HistGram[Y];
        Lut[Y] = (byte)((float)Num / (Width * Height * 3) * 255);       // 计算映射表
    }
    for (Y = 0; Y < Height; Y++)
    {
        Pointer = Scan0 + Y * Stride;
        for (X = 0; X < Width * 3; X += 3)          //  也可以这样写
        {
            Pointer[X] = Lut[Pointer[X]];
            Pointer[X + 1] = Lut[Pointer[X + 1]];
            Pointer[X + 2] = Lut[Pointer[X + 2]];
        }
    }

  算法部分就是这么简单的二十几行代码,代码清晰,执行效率又特别高,数码相机中常见的4000*3000的照片100ms内就可以处理完。

    一副图像如果执行了一次色调均化,那么再次执行色调均化应该不会有任何像素发生变换了。

    从广义上讲,色调均化可以看成是直方图匹配的一个特例,即匹配的直方图分布为一条水平线。

    一些书中的色调均化是对各通道分别进行校正的,似乎这样处理的效果容易导致图像整体颜色不搭配,比如经典的Lena图:

                      原图                               PS的色调均化                               郎锐课本上的效果

   C#版色调均化代码:http://files.cnblogs.com/Imageshop/HistGramEqualize.rar

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开发与安全

算法:最短路径之弗洛伊德(Floyd)算法

为了能讲明白弗洛伊德(Floyd)算法的主要思想,我们先来看最简单的案例。图7-7-12的左图是一个简单的3个顶点的连通网图。 ? 我们先定义两个二维数组D[3...

3666
来自专栏开发与安全

算法:AOV网(Activity on Vextex Network)与拓扑排序

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Activity on Vextex ...

3977
来自专栏xingoo, 一个梦想做发明家的程序员

20120918-向量实现《数据结构与算法分析》

#include <iostream> #include <list> #include <string> #include <vector> #include...

1846
来自专栏后端之路

LinkedList源码解读

List中除了ArrayList我们最常用的就是LinkedList了。 LInkedList与ArrayList的最大区别在于元素的插入效率和随机访问效率 ...

21010
来自专栏java闲聊

JDK1.8 ArrayList 源码解析

当运行 ArrayList<Integer> list = new ArrayList<>() ; ,因为它没有指定初始容量,所以它调用的是它的无参构造

1232
来自专栏alexqdjay

HashMap 多线程下死循环分析及JDK8修复

1.1K4
来自专栏拭心的安卓进阶之路

Java 集合深入理解(12):古老的 Vector

今天刮台风,躲屋里看看 Vector ! 都说 Vector 是线程安全的 ArrayList,今天来根据源码看看是不是这么相...

2537
来自专栏MelonTeam专栏

ArrayList源码完全分析

导语: 这里分析的ArrayList是使用的JDK1.8里面的类,AndroidSDK里面的ArrayList基本和这个一样。 分析的方式是逐个API进行解析 ...

4699
来自专栏Hongten

ArrayList VS Vector(ArrayList和Vector的区别)_面试的时候经常出现

2202
来自专栏xingoo, 一个梦想做发明家的程序员

AOE关键路径

这个算法来求关键路径,其实就是利用拓扑排序,首先求出,每个节点最晚开始时间,再倒退求每个最早开始的时间。 从而算出活动最早开始的时间和最晚开始的时间,如果这两个...

2637

扫码关注云+社区