解决问题的艺术:半小时编程实现照片的反转负冲特效

简介:

如何直接有效的解决问题是一门艺术。我们是做产品、做系统、做服务的,不是玩技术的,需要做的是在最短的时间内以最有效的方式来解决工作中面对的难题。就在刚才,用了半小时不到时间,俺用一种极其简单、直接、有效、霸道的方法解决了照片的反转负冲特效问题。这种解决问题的思路值得总结推广。

反转负冲(反转片)是一种摄影拍摄技术,它通过拍摄后反转冲洗,得到色彩鲜艳的照片,非常养眼。现在都是数码相机了,可以通过图像处理算法来模拟反转片的效果,比如说,“光影魔术手”就提供了5种反转片特效:(1)素淡人像;(2)淡雅色彩;(3)真实色彩;(4)艳丽色彩;(5)浓郁色彩。且看(5)浓郁色彩的效果:

image_2

左边是处理前的图像,右边是处理后的图像,可以看到,处理后的图像颜色格外饱满。我目前开发的一款图像处理软件,一个难题就是处理后的照片色彩会变暗,这个反转负冲特效的效果正是我所需要的。

且看“光影魔术手”怎样描绘“反转片”功能——

“模拟反转片的效果,是《光影魔术手》最重要的功能之一。经处理后照片反差更鲜明,色彩更亮丽。算法经多次改良后,暗部细节得到最大程度的保留,高光部分无溢出,红色还原十分准确,色彩过渡自然艳丽,绝无色斑!提供多种模式供用户选择,其中人像模式对亚洲人的肤色进行了优化,不会出现肤色偏黄现象。独有的暗部增补算法不仅增强了暗部, 同时令高光部分的表现更出色,绝对没有雾感引入。精心设计,专业效果!强烈推荐所有用户使用! ”

下面且看俺怎么在半小时内将这个光影魔术手引以为豪的功能给集成到俺自己的软件中来。

第一步,先查资料。以关键字“反转片”+“算法”在google搜索,搜到的都是说“光影魔术手”这效果多NB多NB的文章,没参考意义。

第二步,在金山词霸网上输入“反转片”,查出来英文单词是 “reversal film”,然后在google scholar中搜索 “reversal film algorithm”,没介绍的。在 google 中搜索“reversal film algorithm”,没有一篇文章讲了实质性内容的。进 google code search 搜索 “reversal film”,没一个有实质性内容的。进 cnki 搜索 “reversal film”和“反转片”,没一个有实质性内容的。这下完蛋了,没参考的,眼看要个屁了。

第三步,反转片这个效果很重要,一定有很多人用 photoshop 处理过。搜“反转片”,专门找介绍怎么用 photoshop 进行反转负冲处理的文章。找到几篇讲如何手动进行反转负冲特效处理的文章,比如这一篇:http://www.windsn.com/article.asp?id=478。这篇文章中的效果是很NB的。通过阅读这篇文章发现,“反转片”仅仅是点操作即可,它与像素的邻域无关,与图像的统计信息无关。

第四步,天空一声巨响,头脑一片闪亮。通过第三步,可以推测,反转负冲实际上只是一个 RGB 空间到 RGB 空间的映射而已。只需要对于RGB空间的任意一个颜色,计算出它所对应的颜色,做一个替换即可。

第五步,如何寻找这个映射呢?利用归约解决问题。

Udi Manber 的《算法引论-一种创造性的方法》第10章《归约》的引言部分讲了这样一个故事——

有人问一个数学家和她的丈夫如下问题:假设你在地下室,想烧开水怎么办?数学家说,她会上到厨房并在那里烧水。她的丈夫回答类似。那人继续问:假设你在厨房,想烧开水怎么办?她丈夫回答说:“这很容易的,将水壶灌满然后点燃煤气。”而数学家回答:“我的答案更简单。到地下室去,在那里我已经知道如何解决这个问题了。”

就让我们回到“地下室”去解决这个问题。前面说过,光影魔术手可以实现反转片的效果。因此,建立一张图片,让这张图片上包含所有的RGB颜色值,然后用光影魔术手去处理这张图片,得到的效果图另存下来,这就得到了一个RGB空间到RGB空间的映射。通常,RGB的每一个Channel是1个Byte,那么将全部的RGB颜色值放到一张图片上去,这张图片就太大了,需要256×256×256个像素。为了减少处理量,对RGB空间进行采样,只选择Channel值为偶数的色彩,这样,就把RGB空间压缩到 128×128×128大小了,也就是一张1024×2048的图片即可。下面是生成算法:

ImageRgb24 img = new ImageRgb24(1024, 2048); 
for (int x = 0; x < 128; x++) 

    for (int y = 0; y < 128; y++) 
    { 
        for (int z = 0; z < 128; z++) 
        { 
            int index = x * 128 * 128 + y * 128 + z; 
            img[index] = new Rgb24(x * 2, y * 2, z * 2); 
        } 
    } 
}

将上面的图片存为 bmp 格式:

image_6

用 光影魔术手 的5种反转片特效分别进行处理,另存为5个 bmp 文件。每一个bmp文件,代表1种反转片特效,假设某个特效的 bmp 的图储加载在一个名为 img 的 ImageRgb24 中,则 img[color.Red / 2 * 128 * 128 + color.Green / 2 * 128 + color.Blue/2] 就是色彩 color 反转片处理后的色彩了。下面是使用“浓郁色彩”bmp图片映射后的效果图,是不是和光影魔术手处理结果很像呢?

image_4

通过对光影魔术手的进一步分析,发现它的反转片特效并不完全是点操作,比如说,截取一张图片的一部分,处理后相同位置的像素和全张图片处理后相同位置的像素并不一样,而是有比较小的差异。可能它根据色彩的概率分布进行了进一步的处理。不过无所谓了,前面这些已经够用了。

想起了读研究生时的一个故事。老师布置了阅读题目,让写一份读书报告。我将那个主题的文章查了几十篇,然后进行资料分类,写出了一篇很漂亮的读书报告。很幸运的被老师选为3份最优秀的读书报告,上讲台去讲。我这份报告写得很好,但是报告里写的内容我是完全不明白,结果讲的一塌糊涂。不一定非要懂才能写得好一份报告,你只需要善于归纳总结即可。

到目前为止,反转片的原理俺依然是毫无头绪,但问题已经解决了——我成功将这一特效用寥寥几行代码实现,集成在我的程序中!解决问题是一门艺术。

==== 完 ====

本文转自xiaotie博客园博客,原文链接http://www.cnblogs.com/xiaotie/archive/2010/11/30/1891644.html如需转载请自行联系原作者


xiaotie 集异璧实验室(GEBLAB)

相关文章
|
2月前
扑克牌翻牌记忆小游戏源码
扑克牌翻牌记忆小游戏源码
52 0
扑克牌翻牌记忆小游戏源码
|
6月前
|
Java C# 图形学
【3D捏脸功能实现】
【3D捏脸功能实现】
331 0
|
8月前
四、巧用Camtasia来剪视频 | 微课系列教程
因为平时我们要用到的视频操作很多,视频拼接、细节修正、从长视频中取一部分等等。那么本课以微课录制后的视频裁剪为例,教大家一些简单的视频剪切和音频杂音处理,最后导出视频。
69 0
|
存储 Java
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(下)
文章目录 1 开发环境及游戏展示 1.1 游戏主界面 1.2 移动界面 1.3 奖励界面 1.4 F加速功能界面 1.5 死亡界面 2 需求分析 3 系统设计 3.1 系统总体功能设计 3.2 系统总体流程设计 4 功能设计 4.1 贪吃蛇移动及加速功能设计 4.2 贪吃蛇吃食物加速及死亡判定功能的设计 4.2.1 贪吃蛇吃食物加速功能的设计 4.2.2 贪吃蛇死亡判定功能的设计 4.3 贪吃蛇主动加速功能的设计 4.4 贪吃蛇奖励机制功能的设计 5 项目结构与项目实现 5.1 项目结构及类间关系 5.2 项目完整源码 5.2.1 Images类
|
11月前
|
小程序 开发者 索引
如何做一个俄罗斯方块7:下落处理
下落处理”也是俄罗斯方块游戏循环中的最后一个环节,因为“下落处理”结束后,就又进入到了下一个新的循环中。 与之前一样,我们先来看一下什么时候需要进行“下落处理”“下落处理”是在消除完成之后进行的,消除完成之后,上方的未被消除的方块会下落,直到碰到下方的其它方块或者是第一行为止。
143 0
|
11月前
|
Python
Python实现超级玛丽游戏系列教程03玛丽跳跃
Python实现超级玛丽游戏系列教程03玛丽跳跃
123 0
Python实现超级玛丽游戏系列教程03玛丽跳跃
|
前端开发 JavaScript
2023跨年烟花(浪漫烟花+美妙音乐+雪花飘飘)含前端源码直接下载---系列最终篇
2023跨年烟花(浪漫烟花+美妙音乐+雪花飘飘)含前端源码直接下载---系列最终篇
416 0
2023跨年烟花(浪漫烟花+美妙音乐+雪花飘飘)含前端源码直接下载---系列最终篇
|
算法 程序员
拿捏汉诺塔问题(附有动图)
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
213 0
拿捏汉诺塔问题(附有动图)
|
Java 开发工具
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(上)
文章目录 1 开发环境及游戏展示 1.1 游戏主界面 1.2 移动界面 1.3 奖励界面 1.4 F加速功能界面 1.5 死亡界面 2 需求分析 3 系统设计 3.1 系统总体功能设计 3.2 系统总体流程设计 4 功能设计 4.1 贪吃蛇移动及加速功能设计 4.2 贪吃蛇吃食物加速及死亡判定功能的设计 4.2.1 贪吃蛇吃食物加速功能的设计 4.2.2 贪吃蛇死亡判定功能的设计 4.3 贪吃蛇主动加速功能的设计 4.4 贪吃蛇奖励机制功能的设计 5 项目结构与项目实现 5.1 项目结构及类间关系 5.2 项目完整源码 5.2.1 Images类
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(上)
|
Java 图形学
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(中)
文章目录 1 开发环境及游戏展示 1.1 游戏主界面 1.2 移动界面 1.3 奖励界面 1.4 F加速功能界面 1.5 死亡界面 2 需求分析 3 系统设计 3.1 系统总体功能设计 3.2 系统总体流程设计 4 功能设计 4.1 贪吃蛇移动及加速功能设计 4.2 贪吃蛇吃食物加速及死亡判定功能的设计 4.2.1 贪吃蛇吃食物加速功能的设计 4.2.2 贪吃蛇死亡判定功能的设计 4.3 贪吃蛇主动加速功能的设计 4.4 贪吃蛇奖励机制功能的设计 5 项目结构与项目实现 5.1 项目结构及类间关系 5.2 项目完整源码 5.2.1 Images类
Java实现贪吃蛇大作战小游戏(完整教程+源码)额外实现积分和变速功能(中)