图像处理之玻璃水印特效(祝大家圣诞节快乐)

from:http://blog.youkuaiyun.com/jia20003/article/details/13159535


Water Ripple Effect - 水波纹效果

一:原理

模拟水波纹效果,最常见的是sine或者cosn的函数,周期性变化,贴近自然

当水波纹中中间开始向四周扩散的时候,一般都是慢慢的失去能量,振幅也是

越来越小,所以程序要模拟这个过程时候,要加上一个能量递减因子。然后用

公式 y = a*sine(bx + c)来表示波纹公式。

二:程序实现

最重要的一步是计算水波纹的振幅。在任意一点确定水波的中心位置,可以是

鼠标随机选取,对半径范围内的像素位置实现水波生成,然后转换为位置,对

位置实现浮点数取整,然后使用适当的插值算法,本例使用双线性插值。

三:程序效果


四:滤镜完全源代码,这次我写了些中文注解,不给源代码的博文不是好博文

  1. package com.gloomyfish.filter.study;  
  2.   
  3. import java.awt.image.BufferedImage;  
  4.   
  5. public class WaterFilter extends AbstractBufferedImageOp {  
  6.     private float wavelength = 16;  
  7.     private float amplitude = 10;  
  8.     private float phase = 0;  
  9.     private float centreX = 0.5f;  
  10.     private float centreY = 0.5f;  
  11.     private float radius = 50;  
  12.   
  13.     private float radius2 = 0;  
  14.     private float icentreX;  
  15.     private float icentreY;  
  16.       
  17.     public WaterFilter() {  
  18.   
  19.     }  
  20.   
  21.     @Override  
  22.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  23.         int width = src.getWidth();  
  24.         int height = src.getHeight();  
  25.   
  26.         if ( dest == null )  
  27.             dest = createCompatibleDestImage( src, null );  
  28.   
  29.         int[] inPixels = new int[width*height];  
  30.         int[] outPixels = new int[width*height];  
  31.         getRGB( src, 00, width, height, inPixels );  
  32.         icentreX = width * centreX;  
  33.         icentreY = height * centreY;  
  34.         if ( radius == 0 )  
  35.             radius = Math.min(icentreX, icentreY);  
  36.         radius2 = radius*radius;  
  37.         int index = 0;  
  38.         float[] out = new float[2];  
  39.         for(int row=0; row<height; row++) {  
  40.             for(int col=0; col<width; col++) {  
  41.                 index = row * width + col;  
  42.                   
  43.                 // 获取水波的扩散位置,最重要的一步  
  44.                 generateWaterRipples(col, row, out);  
  45.                 int srcX = (int)Math.floor( out[0] );  
  46.                 int srcY = (int)Math.floor( out[1] );  
  47.                 float xWeight = out[0]-srcX;  
  48.                 float yWeight = out[1]-srcY;  
  49.                 int nw, ne, sw, se;  
  50.                   
  51.                 // 获取周围四个像素,插值用,  
  52.                 if ( srcX >= 0 && srcX < width-1 && srcY >= 0 && srcY < height-1) {  
  53.                     // Easy case, all corners are in the image  
  54.                     int i = width*srcY + srcX;  
  55.                     nw = inPixels[i];  
  56.                     ne = inPixels[i+1];  
  57.                     sw = inPixels[i+width];  
  58.                     se = inPixels[i+width+1];  
  59.                 } else {  
  60.                     // Some of the corners are off the image  
  61.                     nw = getPixel( inPixels, srcX, srcY, width, height );  
  62.                     ne = getPixel( inPixels, srcX+1, srcY, width, height );  
  63.                     sw = getPixel( inPixels, srcX, srcY+1, width, height );  
  64.                     se = getPixel( inPixels, srcX+1, srcY+1, width, height );  
  65.                 }  
  66.                   
  67.                 // 取得对应的振幅位置P(x, y)的像素,使用双线性插值  
  68.                 /*if(xWeight >=0 || yWeight >= 0) 
  69.                 { 
  70.                     outPixels[index] = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se);                  
  71.                 } 
  72.                 else  
  73.                 { 
  74.                     outPixels[index] = inPixels[index]; 
  75.                 }*/  
  76.                 outPixels[index] = ImageMath.bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se);  
  77.             }  
  78.         }  
  79.   
  80.         setRGB( dest, 00, width, height, outPixels );  
  81.         return dest;  
  82.     }  
  83.   
  84.     private int getPixel(int[] pixels, int x, int y, int width, int height) {  
  85.         if (x < 0 || x >= width || y < 0 || y >= height) {  
  86.             return 0// 有点暴力啦,懒得管啦  
  87.         }  
  88.         return pixels[ y*width+x ];  
  89.     }  
  90.   
  91.     protected void generateWaterRipples(int x, int y, float[] out) {  
  92.         float dx = x-icentreX;  
  93.         float dy = y-icentreY;  
  94.         float distance2 = dx*dx + dy*dy;  
  95.         // 确定 water ripple的半径,如果在半径之外,就直接获取原来位置,不用计算迁移量  
  96.         if (distance2 > radius2) {   
  97.             out[0] = x;  
  98.             out[1] = y;  
  99.         } else {  
  100.             // 如果在radius半径之内,计算出来  
  101.             float distance = (float)Math.sqrt(distance2);  
  102.             // 计算改点振幅  
  103.             float amount = amplitude * (float)Math.sin(distance / wavelength * ImageMath.TWO_PI - phase);  
  104.             // 计算能量损失,   
  105.             amount *= (radius-distance)/radius; // 计算能量损失,  
  106.             if ( distance != 0 )  
  107.                 amount *= wavelength/distance;  
  108.             // 得到water ripple 最终迁移位置  
  109.             out[0] = x + dx*amount;  
  110.             out[1] = y + dy*amount;  
  111.         }  
  112.     }  
  113.       
  114. }  

觉得不错请顶一下,谢谢!

转载请务必注明出处!谢谢!

【最优潮流】直流最优潮流(OPF)课设(Matlab代码实现)内容概要:本文档主要围绕“直流最优潮流(OPF)课设”的Matlab代码实现展开,属于电力系统优化领域的教学与科研实践内容。文档介绍了通过Matlab进行电力系统最优潮流计算的基本原理与编程实现方法,重点聚焦于直流最优潮流模型的构建与求解过程,适用于课程设计或科研入门实践。文中提及使用YALMIP等优化工具包进行建模,并提供了相关资源下载链接,便于读者复现与学习。此外,文档还列举了大量与电力系统、智能优化算法、机器学习、路径规划等相关的Matlab仿真案例,体现出其服务于科研仿真辅导的综合性平台性质。; 适合人群:电气工程、自动化、电力系统及相关专业的本科生、研究生,以及从事电力系统优化、智能算法应用研究的科研人员。; 使用场景及目标:①掌握直流最优潮流的基本原理与Matlab实现方法;②完成课程设计或科研项目中的电力系统优化任务;③借助提供的丰富案例资源,拓展在智能优化、状态估计、微电网调度等方向的研究思路与技术手段。; 阅读建议:建议读者结合文档中提供的网盘资源,下载完整代码与工具包,边学习理论边动手实践。重点关注YALMIP工具的使用方法,并通过复现文中提到的多个案例,加深对电力系统优化问题建模与求解的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值