文档章节

自己编码使用去色、曲线、色阶算法实现照片怀旧特效。

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:38
字数 1836
阅读 2
收藏 0

  天下文章一大抄,看你会抄不会抄,这个算法的初步雏形其实很简单,很多傻瓜级的软件业提供了相应的一键功能,比如美图秀秀。其实这就是个简单的调色功能,实现的方式五花八门,没有一个固定的标准,我们下面仅以几个开源的软件中的算法为例来说明实现过程。

      第一的参考算法是来自Paint.net的,在专业的软件中,这个功能的英文一般称之为Sepia,在Paint.net中,这个算法实现的主要代码如下:

this.desaturate = new UnaryPixelOps.Desaturate();
this.levels = new UnaryPixelOps.Level(
                ColorBgra.Black, 
                ColorBgra.White,
                new float[] { 1.2f, 1.0f, 0.8f },
                ColorBgra.Black,
                ColorBgra.White);

      即先去色,然后再执行色阶命令,似乎很简单,而我们先看看效果。

   

   

                       原图                        Paint.net的效果                    美图怀旧特效的结果

  从效果上比较接近的,这里和美图比较,并不是说美图就是行业标准,只是做个参照而已,我这里主要说说Paint.net这个代码的简易实现(并不是照抄其代码,实际上我根本没看Paint.net具体的实现代码,而只看其实现的思路)。

     第一步是个去色,去色的算法有N多种,我们这里以业界老大Adobe Photoshop提供的算法为标准实现,主要C++代码如下:

void __stdcall Desaturate(unsigned char * Src , int Width, int Height ,int Stride )
{
    int X,Y, Max, Min, Value;
    unsigned char * Pointer;
    for (Y = 0; Y < Height; Y++)
    {
        Pointer = Src + Y * Stride;
        for (X = 0; X < Width; X++)
        {
            if (*Pointer >= *(Pointer + 1))     //取R/G/B各分量的最大和最小值的平均值
            {
                Max = *Pointer;
                Min = *(Pointer + 1);
            }
            else
            {
                Max = *(Pointer + 1);
                Min = *Pointer;
            }
            if (*(Pointer + 2) > Max)
                Max = *(Pointer + 2);
            else if (*(Pointer + 2) < Min)
                Min = *(Pointer + 2);
            Value =( Max + Min )>>1;
            *Pointer++ =Value;
            *Pointer++ =Value;
            *Pointer++ =Value;
        }
    }
}

   可见PS的去色算法的原理性实现还是很简单的,就是取RGB通道最大值和最小值的平均值,这相当于在色相饱和度效果中的饱和度取0的效果。

     所谓色阶指令,别看PS的Level界面做的很复杂,有N多输入参数,其实内部也没啥复杂的技术,简单的讲就是通过哪些参数计算出一个隐射表,最终都是通过Curve指令来实现的,所以在GIMP下这两个指令的参数可以在不同界面之间相互转换。下面先给出通过那些参数计算隐射表的过程:

void  GetLevelTable(unsigned char * Table, unsigned char InputLeftLimit, unsigned char InputMiddle, unsigned char InputRightLimit, unsigned char OutputLeftLimit , unsigned char OutputRightLimit)
{
    if (InputLeftLimit > 253) InputLeftLimit = 253;
    if (InputLeftLimit < 0)    InputLeftLimit = 0;
    if (InputRightLimit > 255)InputRightLimit = 255;
    if (InputRightLimit < 2) InputRightLimit = 2;
    if (InputMiddle > 254)InputMiddle = 254;
    if (InputMiddle < 1)InputMiddle = 1;
    if (InputMiddle > InputRightLimit)InputMiddle = InputRightLimit - 1;
    if (InputMiddle < InputLeftLimit)InputMiddle = InputLeftLimit + 1;
    if (OutputLeftLimit < 0)OutputLeftLimit = 0;
    if (OutputLeftLimit > 255)OutputLeftLimit = 255;
    if (OutputRightLimit < 0)OutputRightLimit = 0;
    if (OutputRightLimit > 255)OutputRightLimit = 255;

    for (int Index = 0; Index <= 255; Index++)
    {
        double Temp = Index - InputLeftLimit;
        if (Temp < 0) 
        {
            Temp = OutputLeftLimit;
        }
        else if (Temp + InputLeftLimit > InputRightLimit)
        {
            Temp = OutputRightLimit;
        }
        else 
        {
            double Gamma = log(0.5) / log((double)(InputMiddle - InputLeftLimit) / (InputRightLimit - InputLeftLimit));
            Temp = OutputLeftLimit + (OutputRightLimit - OutputLeftLimit) * pow((Temp / (InputRightLimit - InputLeftLimit)), Gamma);
        }
        if (Temp > 255)
            Temp = 255;
        else if (Temp < 0)
            Temp = 0;
        Table[Index] = Temp;
    }
}

  我们先贴下PS的Level界面:

     

  我想稍微懂点英语的人对理解上面代码中的参数和这个界面中的那些位置的标签对应应该都没有问题,如果有,请回到初中课堂。 

     这里重点关注下上图中有提示文字“调整中间调输入色阶"一项,PS的这一栏的输入范围是9.9-0.01,而我上述代码中对应的范围是1-254,唯一的区别我觉得就是量化等级变得少了,这里的主要算法我记得是模仿的Gimp的。

     有了上述过程,只要在进行一个隐射就OK了,这部分其实就是PS的曲线功能的结果,虽然你看曲线的界面那么复杂,其实都是一些控制而已。

void __stdcall Curve(unsigned char * Src , int Width, int Height , int Stride ,unsigned char * TableB,unsigned char * TableG,unsigned char * TableR)
{
    int X,Y;
    int ByteCount = Stride / Width;
    unsigned char * Pointer;
    for (Y = 0; Y < Height; Y++)
    {
        Pointer = Src + Y * Stride;
        for (X = 0; X < Width; X++)
        {
            *Pointer++ = TableB[*Pointer];
            *Pointer++ = TableG[*Pointer];
            *Pointer++ = TableR[*Pointer];
        }
    }
}

  最后给出Level命令的代码:

void __stdcall Level(unsigned char * Src , int Width, int Height ,int Stride , Channel DestChannel, unsigned char InputLeftLimit, unsigned char InputMiddle, unsigned char InputRightLimit, unsigned char OutputLeftLimit , unsigned char OutputRightLimit)
{
    unsigned char * Table = (unsigned char *) malloc ( 256 * sizeof (unsigned char));
    unsigned char * LinearTable = (unsigned char *) malloc ( 256 * sizeof (unsigned char));
    for (int X=0;X<256;X++)    LinearTable[X] = X; 
    GetLevelTable(Table, InputLeftLimit,InputMiddle,InputRightLimit,OutputLeftLimit,OutputRightLimit);
    if (DestChannel == RGB)
        Curve(Src,Width,Height,Stride,Table,Table,Table);
    else if (DestChannel == Blue)
        Curve(Src,Width,Height,Stride,Table,LinearTable,LinearTable);
    else if (DestChannel == Green)
        Curve(Src,Width,Height,Stride,LinearTable,Table,LinearTable);
    else if (DestChannel == Red)
        Curve(Src,Width,Height,Stride,LinearTable,LinearTable,Table);
    free(Table);
    free(LinearTable);
}

  对应上述Paint.net的level指令,我们把我们的调用形式更给为:

Level(Dest, Width, Height, Stride, Channel.Blue, 0, 152, 255, 0, 255);
Level(Dest, Width, Height, Stride, Channel.Red, 0, 101, 255, 0, 255);

  就OK了,具体的调用即效果可见后面的附件。

     第二中参考算法来自于ImageJ软件,JAVA版本的图像处理包。其所谓的Sepia的命令只能针对8位灰度图,其实这个就印证了上述的Desaturate过程,并且Sepia出现在其LookUp Tables命令组内,这也就和上述描述想对应:level指令也是一种简单的映射而已,我们这里贴出ImageJ的相关隐射表的数据:

byte[] Table = {
                0,0,0, 
                43,28,4, 
                57,35,5, 
                65,35,6, 
                66,36,7, 
                67,37,8, 
                68,38,9, 
                69,39,10, 
                70,40,11, 
                71,41,12, 
                72,42,13, 
                73,43,14, 
                74,44,15, 
                75,45,16, 
                76,46,17, 
                77,47,18, 
                78,48,19, 
                79,49,20, 
                80,50,21, 
                81,51,22, 
                82,52,23, 
                83,53,24, 
                83,53,24, 
                84,54,25, 
                85,55,26, 
                86,56,27, 
                87,57,28, 
                88,58,29, 
                89,59,30, 
                90,60,31, 
                91,61,32, 
                92,62,33, 
                93,63,34, 
                94,64,35, 
                95,65,36, 
                96,66,37, 
                97,67,38, 
                98,68,39, 
                99,69,40, 
                100,70,41, 
                101,71,42, 
                102,72,43, 
                103,73,44, 
                104,74,45, 
                105,75,46, 
                106,76,47, 
                107,77,48, 
                107,77,48, 
                108,78,49, 
                109,79,50, 
                110,80,51, 
                111,81,52, 
                112,82,53, 
                113,83,54, 
                114,84,55, 
                115,85,56, 
                116,86,57, 
                117,87,58, 
                118,88,59, 
                119,89,60, 
                120,90,61, 
                121,91,62, 
                122,92,63, 
                123,93,64, 
                124,94,65, 
                125,95,66, 
                125,95,66, 
                126,96,67, 
                127,97,68, 
                128,98,69, 
                129,99,70, 
                130,100,71, 
                131,101,72, 
                132,102,73, 
                133,103,74, 
                134,104,75, 
                135,105,76, 
                136,106,77, 
                137,107,78, 
                138,108,79, 
                139,109,80, 
                140,110,81, 
                141,111,82, 
                142,112,83, 
                143,113,84, 
                144,114,85, 
                145,115,86, 
                146,116,87, 
                147,117,88, 
                148,118,89, 
                149,119,90, 
                150,120,91, 
                151,121,92, 
                152,122,93, 
                153,123,94, 
                154,124,95, 
                155,125,96, 
                156,126,97, 
                157,127,98, 
                158,128,99, 
                159,129,100, 
                160,130,101, 
                161,131,102, 
                162,132,103, 
                163,133,104, 
                164,134,105, 
                165,135,106, 
                166,136,107, 
                167,137,108, 
                168,138,109, 
                169,139,110, 
                170,140,111, 
                171,141,112, 
                172,142,113, 
                173,143,114, 
                174,144,115, 
                175,145,116, 
                176,146,117, 
                177,147,118, 
                178,148,119, 
                179,149,120, 
                180,150,121, 
                181,151,122, 
                182,152,123, 
                183,153,124, 
                184,154,125, 
                185,155,126, 
                186,156,127, 
                187,157,128, 
                187,157,128, 
                188,158,129, 
                189,159,130, 
                190,160,131, 
                191,161,132, 
                192,162,133, 
                193,163,134, 
                194,164,135, 
                195,165,136, 
                196,166,137, 
                197,167,138, 
                198,168,139, 
                199,169,140, 
                200,170,141, 
                201,171,142, 
                202,172,143, 
                203,173,144, 
                204,174,145, 
                205,175,146, 
                206,176,147, 
                207,177,148, 
                208,178,149, 
                209,179,150, 
                210,180,151, 
                211,181,152, 
                212,182,153, 
                213,183,154, 
                214,184,155, 
                215,185,156, 
                216,186,157, 
                217,187,158, 
                218,188,159, 
                219,189,160, 
                220,190,161, 
                221,191,162, 
                222,192,163, 
                223,193,164, 
                224,194,165, 
                225,195,166, 
                226,196,167, 
                227,197,168, 
                228,198,169, 
                229,199,170, 
                230,200,171, 
                231,201,172, 
                232,202,173, 
                233,203,174, 
                234,204,175, 
                235,205,176, 
                236,206,177, 
                237,207,178, 
                238,208,179, 
                239,209,180, 
                240,210,181, 
                241,211,182, 
                242,212,183, 
                243,213,184, 
                244,214,185, 
                245,215,186, 
                246,216,187, 
                247,217,188, 
                248,218,189, 
                249,219,190, 
                250,220,191, 
                251,221,192, 
                252,222,193, 
                253,223,194, 
                254,224,195, 
                255,225,196, 
                255,225,196, 
                255,225,196, 
                255,225,196, 
                255,225,196, 
                255,225,197, 
                255,225,197, 
                255,225,197, 
                255,225,197, 
                255,226,198, 
                255,226,198, 
                255,226,198, 
                255,226,198, 
                255,226,198, 
                255,226,199, 
                255,226,199, 
                255,226,199, 
                255,226,199, 
                255,226,199, 
                255,227,200, 
                255,227,200, 
                255,227,200, 
                255,227,200, 
                255,227,200, 
                255,227,201, 
                255,227,201, 
                255,227,201, 
                255,227,201, 
                255,227,201, 
                255,228,202, 
                255,228,202, 
                255,228,202, 
                255,228,202, 
                255,228,202, 
                255,228,202, 
                255,228,203, 
                255,228,203, 
                255,228,203, 
                255,228,203, 
                255,228,203, 
                255,229,204, 
                255,229,204, 
                255,229,204, 
                255,229,204, 
                255,229,204, 
                255,229,204, 
                255,229,205, 
                255,229,205, 
                255,229,205, 
                255,229,205, 
                255,229,205, 
                255,230,205, 
                255,230,205, 
                255,231,205, 
                255,231,209, 
                255,233,214, 
                255,233,217, 
                255,242,233, 
                255,255,255
            };
View Code

  你如果在网络上搜索PS+老照片效果,你会发现这其实只是处理过程中占有比例很小的一部分,但是这一部分却对最终的效果起到了铺垫的作用。也就是说,仅仅通过这一过程,只是获得老照片效果的基础,一个出色的自动老照片滤镜还需要更多的其他处理,比如老照片必然存在一些皱褶,边缘部位很有可能有磨损,图片周边一般比较偏暗等等。这些过程的实现需要较强的编码能力和创造力,在GIMP中存在一个old photo插件,可以实现较为出色的效果,并且这个是个开源的软件,有想开发此类算法的朋友应该去参考下。

    相关程序下载: http://files.cnblogs.com/Imageshop/OldPhoto.rar

 

*********************************作者: laviewpbt   时间: 2013.12.6   联系QQ:  33184777  转载请保留本行信息************************

 

 

本文转载自:http://www.cnblogs.com/Imageshop/p/3460951.html

共有 人打赏支持
abcijkxyz
粉丝 63
博文 6196
码字总数 1876
作品 0
深圳
项目经理
PS教程1000例

http://www.missyuan.com/thread-446934-1-1.html Photoshop绘制逼真头发发丝效果 http://www.missyuan.com/thread-446912-1-1.html Photoshop合成在空中漂移的陆地 http://www.missyuan.co......

机器的心脏
2017/12/12
0
0
Photoshop色阶、曲线命令图解和编程实现(附源码)

Photoshop功能强大,使用灵活。初级使用者通常有几个禁区: 1.图像->调整 菜单(色阶,曲线等命令都在此菜单中) 2.蒙版与矢量工具(如钢笔工具) 3.通道与色彩模式 4.图层混合模式 要用好这...

云栖希望。
2017/12/04
0
0
深度学习AI美颜系列---AI滤镜特效算法

滤镜是图像美化中必不可少的步骤, 所谓滤镜,最初是指安装在相机镜头前过滤自然光的附加镜头,用来实现调色和添加效果。我们做的滤镜算法又叫做软件滤镜,是对大部分镜头滤镜进行的模拟,当...

trent1985
05/25
0
0
【AI超级美发师】深度学习算法打造染发特效(附代码)

【新智元导读】如今,在类似天天P图、美图秀秀等手机APP中,给指定照片或视频中的人物更换头发颜色已经是再正常不过的事情了。那么本文便介绍了该功能背后如AI头发分割模块、头发换色、颜色增...

技术小能手
08/03
0
0
Camera 图像处理原理分析

色彩篇(一) 1 前言 做为拍照手机的核心模块之一,camera sensor效果的调整,涉及到众多的参数,如果对基本的光学原理及sensor软/硬件对图像处理的原理能有深入的理解和把握的话,对我们的工...

Jerikc
2013/09/25
0
1

没有更多内容

加载失败,请刷新页面

加载更多

OSX | SafariBookmarksSyncAgent意外退出解决方法

1. 启动系统, 按住⌘-R不松手2. 在实用工具(Utilities)下打开终端,输入csrutil disable, 然后回车; 你就看到提示系统完整性保护(SIP: System Integrity Protection)已禁用3. 输入reboot回车...

云迹
今天
4
0
面向对象类之间的关系

面向对象类之间的关系:is-a、has-a、use-a is-a关系也叫继承或泛化,比如大雁和鸟类之间的关系就是继承。 has-a关系称为关联关系,例如企鹅在气候寒冷的地方生活,“企鹅”和“气候”就是关...

gackey
今天
4
0
读书(附电子书)|小狗钱钱之白色的拉布拉多

关注公众号,在公众号中回复“小狗钱钱”可免费获得电子书。 一、背景 之前写了一篇文章 《小狗钱钱》 理财小白应该读的一本书,那时候我才看那本书,现在看了一大半了,发现这本书确实不错,...

tiankonguse
今天
4
0
Permissions 0777 for ‘***’ are too open

异常显示: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ......

李玉长
今天
5
0
区块链10年了,还未落地,它失败了吗?

导读 几乎每个人,甚至是对通证持怀疑态度的人,都对区块链的技术有积极的看法,因为它有可能改变世界。然而,区块链技术问世已经10年了,我们仍然没有真正的用上区块链技术。 几乎每个人,甚...

问题终结者
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部