[图像处理] 利用PerlinNoise实现图像雾化效果
来源:互联网 发布:.net cms 源码 编辑:程序博客网 时间:2024/06/05 15:06
时间:2017年7月2日(大三下学期)
写在前面:
最近觉得Steam的软件界面非常的美观,尤其是图片的渐隐、雾化效果看起来非常漂亮。无奈我PS技术不行,手笨做不出那样的效果…… 于是,我就自己写了一款方便高效的图像处理程序,只需设置相应的参数即可完成处理(懒人模式)。如果点入的读者只是为了使用程序,那么可以无视我下面啰啰嗦嗦的科普,通过下面的链接,就获取到我的打包程序:
http://download.csdn.net/detail/mahabharata_/9886497
在正文开始之前,首先贴一下效果图:
(1) 程序界面效果图
(2) 图片的处理效果图:
【原理一】 图像雾化 —— Perlin Noise (柏林噪声)
关于柏林噪声,我曾经写过一篇“基于Perlin Noise实现的Minecraft游戏”,这里也贴一下传送门:
柏林噪声实现的Minecraft游戏
柏林噪声是由Ken Perlin于1983年提出的一种梯度噪声(Gradient Noise,通常由计算机模拟得到的一组噪声,相较于传统的离散数值噪声value noise要更加连续平滑)他在1985年的SIGGRAPH会议上,做了一场以“An Image Synthesizer”为题的学术报告,正式提出他的这一发现。
柏林噪声的应用非常广泛: 合成地形高度图、生成物体表面的复杂纹理、火焰烟雾特效、波动效果的模拟等等。下面的几副图片就是以Perlin Noise为原理做出的效果:
关于Perlin Noise的基本原理,在wikipedia和perlin的个人主页上都能找到,这里不多做赘述,大家可以通过下面的链接找到关于Ken Perlin关于柏林噪声的介绍以及它的其他研究成果(看了一下感觉蛮有意思的):
Ken Perlin的个人主页:http://mrl.nyu.edu/~perlin/(纽约大学-媒体研究实验室 nyu Media Research Lab)
这里只贴一下我的相关实现代码:
class ImageFogger{public: ImageFogger(); QImage processImage(const QImage& img); // 处理img,并返回图像 float m_persistence; int m_octaveNum; float m_frequency; int m_amplitude; // 噪声相关 double Noise(int x,int y); double SmoothedNoise(int x, int y); double Cosine_Interpolate(double a,double b, double x); double InterpolatedNoise(float x,float y); double PerlinNoise(float x,float y); QColor reverseRGB(int r,int g,int b); // 修正像素};#include "imagefogger.h"ImageFogger::ImageFogger(){ m_persistence = 0.50; m_octaveNum = 4; m_frequency = 0.025; m_amplitude = 200;}// 处理图像QImage ImageFogger::processImage(const QImage &img){ QImage pimg = img; for(int i=0; i<pimg.height() ; i++) // 遍历图像 { for(int k=0; k<pimg.width(); k++) { QRgb pixel = pimg.pixel(k,i); QColor rgb(pixel); double noise = m_amplitude*PerlinNoise(k*m_frequency,i*m_frequency); // 获取噪声数值 int r = (noise+rgb.red()); int g = (noise+rgb.green()); int b = (noise+rgb.blue()); pimg.setPixel(k,i,reverseRGB(r,g,b).rgb()); } } return pimg;}double ImageFogger::Noise(int x,int y) // 根据(x,y)获取一个初步噪声值{ int n = x + y * 57; n = (n<<13) ^ n; return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);}double ImageFogger::SmoothedNoise(int x, int y) //光滑噪声{ double corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16; double sides = ( Noise(x-1, y) +Noise(x+1, y) +Noise(x, y-1) +Noise(x, y+1) ) / 8; double center = Noise(x, y) / 4; return corners + sides + center;}double ImageFogger::Cosine_Interpolate(double a,double b, double x) // 余弦插值{ double ft = x * 3.1415927; double f = (1 - cos(ft)) * 0.5; return a*(1-f) + b*f;}double ImageFogger::InterpolatedNoise(float x,float y) // 获取插值噪声{ int integer_X = int(x); float fractional_X = x - integer_X; int integer_Y = int(y); float fractional_Y = y - integer_Y; double v1 = SmoothedNoise(integer_X, integer_Y); double v2 = SmoothedNoise(integer_X + 1, integer_Y); double v3 = SmoothedNoise(integer_X, integer_Y + 1); double v4 = SmoothedNoise(integer_X + 1, integer_Y + 1); double i1 = Cosine_Interpolate(v1, v2, fractional_X); double i2 = Cosine_Interpolate(v3, v4, fractional_X); return Cosine_Interpolate(i1, i2, fractional_Y);}double ImageFogger::PerlinNoise(float x,float y) // 最终调用:根据(x,y)获得其对应的PerlinNoise值{ double total = 0; double p = m_persistence; int n = m_octaveNum; for(int i=0; i<n; i++) { double frequency = pow(2,i); double amplitude = pow(p,i); total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude; } return total;}// 修正像素QColor ImageFogger::reverseRGB(int r, int g, int b){ r = r<(0)?0:r; g = g<(0)?0:g; b = b<(0)?0:b; r = r>(255)?255:r; g = g>(255)?255:g; b = b>(255)?255:b; return QColor(r,g,b);}
【原理二】 图像刻蚀效果
这个相对来讲就不那么复杂了。 我们可以预先设定一个限制条件t,对于图像中的每个像素,如果它不满足条件t,那么我们就可以剔除该点的像素并以黑色替代。条件t可以随便设置,以实现不同的刻蚀效果,比如:
颜色(r,g,b)的红色分量小于50、红绿分量的壁纸(r/g)小于0.7等。
相关实现的代码如下:
QImage ImageCarver::processImage(const QImage &img){ QImage pimg = img; for(int i=0; i<pimg.height() ; i++) // 遍历y { for(int k=0; k<pimg.width(); k++) // 遍历x { QRgb pixel = pimg.pixel(k,i); QColor rgb(pixel); // 获取像素的rgb值 if(rgb.red()/(float)rgb.blue()<0.7) pimg.setPixel(k,i, QColor(0,0,0) ); // 黑色 else pimg.setPixel(k,i, rgb); // 保持颜色不变 } } return pimg;}
【原理三】 图像光晕效果
图像的光晕可以通过一种与距离有关的插值实现。实现的步骤如下:
(1) 选定一个点(cx,cy)为光晕的中心。
(2) 遍历图像的每个像素(x,y),计算(x,y)与(cx,cy)的距离dist;
(3) 根据dist修改该像素的颜色值,这里可以随便设置插值函数,比如这里采用平方过渡:
(r',g',b') = (r,g,b) + dist*dist*0.0001;
(4) 修正(r',g',b')的数值在0-255之间,并作为该点的新颜色数值。
三种特效的大概原理就是这样。这个程序是我偶然间想到可以写一个工具来帮助我这种不会用PS的人处理图片,三种特效除了柏林噪声,另两种是我随便琢磨的、觉得可行的方法,没想到效果看起来还挺不错的。欢迎讨论~~
- [图像处理] 利用PerlinNoise实现图像雾化效果
- Win8 Metro(C#)数字图像处理--2.45图像雾化效果算法
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- No 68 · 以雾化效果显示图像
- 黄聪:C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果) (转)
- 暑假第一周 E
- 【网络】基础复习
- JZ2440 arm 调用C的点灯程序
- spring boot之Properties和YAML
- 网络知识总结
- [图像处理] 利用PerlinNoise实现图像雾化效果
- PAT乙级 1054. 求平均值 (20)
- 如何配置python环境和跑通第一个程序
- Java面试题-统计字符串的字符出现次数
- 暑假第一周 T
- 使用Mybatis模糊查询方法
- JS 函数的定义(一)
- VS使用SVN协同编程中遇到的小问题
- javascript实现二叉树的遍历