文档章节

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

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:38
字数 1836
阅读 1
收藏 0
点赞 0
评论 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
粉丝 60
博文 6195
码字总数 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
Camera 图像处理原理分析

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

Jerikc
2013/09/25
0
1
c#开发大全、系列文章、精品教程

全栈工程师开发手册 (作者:栾鹏) c#系列教程: c#实现ajax通信:向后台发送JSON字符串,接收响应字符串,并转换为对象 c#文件夹常用操作,属性设置,遍历、压缩 c#获取网页源代码的5种方式...

luanpeng825485697
2017/10/03
0
0
教你用PS调出阿宝色

阿宝色是近来十分流行的PS处理的人物肤色,它的特点是整个照片看上去粉粉的,两边的腮红特别明显,用PS调制阿宝色特别简单,下面奉上一张完成图片: 下面介绍制作方法: 首先,打开ps,再打开...

材大难为用
2017/08/04
0
0
关于对每种图片格式的理解(学习记录)

有损vs无损 图片文件格式有可能会对图片的文件大小进行不同程度的压缩,图片的压缩分为有损压缩和无损压缩两种。 有损压缩。指在压缩文件大小的过程中,损失了一部分图片的信息,也即降低了图...

小海bug
05/28
0
1
RGB色彩空间和RGB波形

红、绿、蓝(RGB)三种颜色不同比例的混合可以得到不同的颜色,我们经常用的曲线就是运用的这个原理 在曲线中,从左到右(黑->白)一共有(0-255)256个色阶值 RGB示波器波形有RGB波形和RGB...

NiceBlueChai
02/15
0
0
从零开始:编码神经网络参数的初始化!

  【IT168 资讯】机器学习/深度学习环境中的优化是改变模型参数以提高其性能的过程。换句话说,它是在预定假设空间中找到最佳参数以获得最佳性能的过程。有三种优化算法:   ・优化算法不...

it168网站
04/28
0
0
Android图像处理(二)--Paint,Canvas,ColorMatrix详细

android开发中可能经常会用到这些东西; 一.介绍 Paint:画笔 Canvas:画布 Matrix:变换矩阵 Paint 根据我们要画的类型,我们可以选择不同的笔,比如大气磅礴的山水画,我们可以选择大头的毛笔;...

andy521zhu
2015/04/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

NNS域名系统之域名竞拍

0x00 前言 其实在官方文档中已经对域名竞拍的过程有详细的描述,感兴趣的可以移步http://doc.neons.name/zh_CN/latest/nns_protocol.html#id30 此处查阅。 我这里主要对轻钱包开发中会用到的...

暖冰
今天
0
0
32.filter表案例 nat表应用 (iptables)

10.15 iptables filter表案例 10.16/10.17/10.18 iptables nat表应用 10.15 iptables filter表案例: ~1. 写一个具体的iptables小案例,需求是把80端口、22端口、21 端口放行。但是,22端口我...

王鑫linux
今天
0
0
shell中的函数&shell中的数组&告警系统需求分析

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析

影夜Linux
今天
0
0
Linux网络基础、Linux防火墙

Linux网络基础 ip addr 命令 :查看网口信息 ifconfig命令:查看网口信息,要比ip addr更明了一些 centos 7默认没安装ifconfig命令,可以使用yum install -y net-tools命令来安装。 ifconfig...

李超小牛子
今天
1
0
[机器学习]回归--Decision Tree Regression

CART决策树又称分类回归树,当数据集的因变量为连续性数值时,该树算法就是一个回归树,可以用叶节点观察的均值作为预测值;当数据集的因变量为离散型数值时,该树算法就是一个分类树,可以很...

wangxuwei
昨天
1
0
Redis做分布式无锁CAS的问题

因为Redis本身是单线程的,具备原子性,所以可以用来做分布式无锁的操作,但会有一点小问题。 public interface OrderService { public String getOrderNo();} public class OrderRe...

算法之名
昨天
10
0
143. Reorder List - LeetCode

Question 143. Reorder List Solution 题目大意:给一个链表,将这个列表分成前后两部分,后半部分反转,再将这两分链表的节点交替连接成一个新的链表 思路 :先将链表分成前后两部分,将后部...

yysue
昨天
1
0
数据结构与算法1

第一个代码,描述一个被称为BankAccount的类,该类模拟了银行中的账户操作。程序建立了一个开户金额,显示金额,存款,取款并显示余额。 主要的知识点联系为类的含义,构造函数,公有和私有。...

沉迷于编程的小菜菜
昨天
1
0
从为什么别的队伍总比你的快说起

在机场候检排队的时候,大多数情况下,别的队伍都要比自己所在的队伍快,并常常懊悔当初怎么没去那个队。 其实,最快的队伍只能有一个,而排队之前并不知道那个队快。所以,如果有六个队伍你...

我是菜鸟我骄傲
昨天
1
0
分布式事务常见的解决方案

随着互联网的发展,越来越多的多服务相互之间的调用,这时候就产生了一个问题,在单项目情况下很容易实现的事务控制(通过数据库的acid控制),变得不那么容易。 这时候就产生了多种方案: ...

小海bug
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部