• 图像处理------噪声之美


    数学原理:

    首先看两张图片,大小均为256 * 256个像素, 第一张是纯蓝色

    图一:

    第二张是加有随机噪声的蓝色

     图二:

    产生随机噪声的算法简单的不能再简单了

    假设RGB的R与G颜色分量均为零, 则 Blue = 255 * Math.Random() 随机数的取值范围在

    [0, 1]之间, 程序的核心代码如下:

    for(int row=0; row<256; row++) {

                                for(int col=0; col<256; col++) {

    b = (int)(255.0d * Math.random());

                                         rgbData[index]= ((clamp(a) & 0xff) << 24) |

                                                                               ((clamp(r)& 0xff) << 16)  |

                                                                               ((clamp(g)& 0xff) << 8)   |

                                                                               ((clamp(b)& 0xff));

                                         index++;

                                }

    }

     

    上面显然不是我想要的结果,我想要的是下面两种:

     图三:


    图四:


    对的,只要我们对上面的算法稍加改进,就可以实现这样漂亮的噪声效果

    实现第二张图效果的算法缺点在于,它每次都产生一个新的随机数,假设[0,1] = 255,接着第

    二点随机可以能为[0, 2] = 0 第三个点可能随机值为[0, 3] = 125, 毫无规律可言,而我希望是

    假设第一点随机[0, 1] = 255则间隔N个点以后再产生下个随机颜色值[0,N+1] =125, 在下一

    个点则为[0, 2N +1] = 209…..于是问题产生了, 我们怎么计算[1, N]的之间的每个像素点的值

    哇,这个问题不正是关于图像放缩的插值问题嘛,一个最简单的选择是双线性插值算法,

    算法解释参考这里:http://blog.csdn.net/jia20003/article/details/6915185

    有了算法选择,下面的问题就是我们怎么计算点值的问题,面临两个选择,一个值照搬双线

    性插值中的计算方法,但是有点不自然,我们想要的是噪声,显然线性的计算结果不是最好

    的最好的选择,cos(x)如何,在[0, PI]内是递减,在[PI,2PI]内是递增,而且值的范围在[-1, 1]

    之间,而我们的随机数值要在[0, 1]之间于是综合上述考虑我们有cos(PI + (x-x0/x1-x0)* PI) + 1, 现

    在计算出来的值是[0, 1]区间之内 根据插值公式最终有:

    y= (y1-y0) * cos(PI + (x-x0/x1-x0) * PI) + 1 + y0

     

    其中[x, y]代表要计算的点,周围四个采样点为:[x-N, y-N], [x+N,y-N], [x-N, y+N], [x+N, y+N ]

    运用双线性插值原理即可计算出[1, N]个每个像素点的值。


    关键代码实现及解释:

    获取四个采样点,及其值,然后使用类似双线性算法计算出[x,y]的随机数值进而计算出像素值

    的程序代码如下:

    1. // bi-line interpolation algorithm here!!!  
    2.     Double GetColor(int x, int y, int M, int colorType)  
    3.     {  
    4.        int x0 = x - (x % M);  
    5.        int x1 = x0 + M;  
    6.        int y0 = y - (y % M);  
    7.        int y1 = y0 + M;  
    8.    
    9.         Double x0y0 = Noise(x0,y0, colorType);  
    10.         Double x1y0 = Noise(x1,y0, colorType);  
    11.         Double x0y1 = Noise(x0,y1, colorType);  
    12.         Double x1y1 = Noise(x1,y1, colorType);  
    13.    
    14.         Double xx0 =Interpolate(x0, x0y0, x1, x1y0, x);  
    15.         Double xx1 = Interpolate(x0,x0y1, x1, x1y1, x);  
    16.    
    17.         Double N =Interpolate(y0, xx0, y1, xx1, y);  
    18.         return N;  
    19.     }  

    根据两个点计算插入值的公式代码如下:

    1. return (1.0 + Math.cos(Math.PI +  (Math.PI / (x1-x0)) * (x-x0))) / 2.0   
    2. * (xx1-xx0) + xx0;  

    对一张图像实现随机噪声值得出像素值计算的代码如下:

    1.               for(int row=0; row<256; row++) {  
    2.     for(int col=0; col<256; col++) {  
    3.         // set random color value for each pixel  
    4.         r = (int)(255.0d * GetColor(row, col, intervalPixels, 1));  
    5.         g = (int)(255.0d * GetColor(row, col, intervalPixels, 2));  
    6.         b = (int)(255.0d * GetColor(row, col, intervalPixels, 4));  
    7.           
    8.         rgbData[index] = ((clamp(a) & 0xff) << 24) |  
    9.                         ((clamp(r) & 0xff) << 16)  |  
    10.                         ((clamp(g) & 0xff) << 8)   |  
    11.                         ((clamp(b) & 0xff));  
    12.         index++;  
    13.     }  
    14. }  
    完全源代码如下:

    1. import java.awt.BorderLayout;  
    2. import java.awt.Dimension;  
    3. import java.awt.Graphics;  
    4. import java.awt.Graphics2D;  
    5. import java.awt.RenderingHints;  
    6. import java.awt.image.BufferedImage;  
    7. import java.util.Random;  
    8.   
    9. import javax.swing.JComponent;  
    10. import javax.swing.JFrame;  
    11.   
    12. public class RandomNoiseImage extends JComponent {  
    13.   
    14.     /** 
    15.      *  
    16.      */  
    17.     private static final long serialVersionUID = -2236160343614397287L;  
    18.     private BufferedImage image = null;  
    19.     private double[] blue_random;  
    20.     private double[] red_random;  
    21.     private double[] green_random;  
    22.     private int intervalPixels = 40// default  
    23.       
    24.     public RandomNoiseImage() {  
    25.         super();  
    26.         this.setOpaque(false);  
    27.     }  
    28.       
    29.     protected void paintComponent(Graphics g) {  
    30.         Graphics2D g2 = (Graphics2D)g;  
    31.         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
    32.         g2.drawImage(getImage(), 55, image.getWidth(), image.getHeight(), null);  
    33.     }  
    34.       
    35.     private BufferedImage getImage() {  
    36.         if(image == null) {  
    37.             image = new BufferedImage(256256, BufferedImage.TYPE_INT_ARGB);  
    38.             int[] rgbData = new int[256*256];  
    39.             generateNoiseImage(rgbData);  
    40.             setRGB(image, 00256256, rgbData);  
    41.         }  
    42.         return image;  
    43.     }  
    44.       
    45.     private void generateNoiseImage(int[] rgbData) {  
    46.         int index = 0;  
    47.         int a = 255;  
    48.         int r = 0;  
    49.         int g = 0;  
    50.         int b = 0;  
    51.         int sum = 256 * 256;  
    52.         blue_random = new double[sum];  
    53.         red_random = new double[sum];  
    54.         green_random = new double[sum];  
    55.         Random random = new Random();  
    56.         for(int i=0; i< sum; i++) {  
    57.             blue_random[i] = random.nextDouble();  
    58.             red_random[i] = random.nextDouble();  
    59.             green_random[i] = random.nextDouble();  
    60.         }  
    61.           
    62.           
    63.         for(int row=0; row<256; row++) {  
    64.             for(int col=0; col<256; col++) {  
    65.                 // set random color value for each pixel  
    66.                 r = (int)(255.0d * GetColor(row, col, intervalPixels, 1));  
    67.                 g = (int)(255.0d * GetColor(row, col, intervalPixels, 2));  
    68.                 b = (int)(255.0d * GetColor(row, col, intervalPixels, 4));  
    69.                   
    70.                 rgbData[index] = ((clamp(a) & 0xff) << 24) |  
    71.                                 ((clamp(r) & 0xff) << 16)  |  
    72.                                 ((clamp(g) & 0xff) << 8)   |  
    73.                                 ((clamp(b) & 0xff));  
    74.                 index++;  
    75.             }  
    76.         }  
    77.           
    78.     }  
    79.       
    80.     private int clamp(int rgb) {  
    81.         if(rgb > 255)  
    82.             return 255;  
    83.         if(rgb < 0)  
    84.             return 0;  
    85.         return rgb;  
    86.     }  
    87.       
    88.     // bi-line interpolation algorithm here!!!  
    89.     Double GetColor(int x, int y, int M, int colorType)  
    90.     {  
    91.         int x0 = x - (x % M);  
    92.         int x1 = x0 + M;  
    93.         int y0 = y - (y % M);  
    94.         int y1 = y0 + M;  
    95.   
    96.         Double x0y0 = Noise(x0, y0, colorType);  
    97.         Double x1y0 = Noise(x1, y0, colorType);  
    98.         Double x0y1 = Noise(x0, y1, colorType);  
    99.         Double x1y1 = Noise(x1, y1, colorType);  
    100.   
    101.         Double xx0 = Interpolate(x0, x0y0, x1, x1y0, x);  
    102.         Double xx1 = Interpolate(x0, x0y1, x1, x1y1, x);  
    103.   
    104.         Double N = Interpolate(y0, xx0, y1, xx1, y);  
    105.         return N;  
    106.     }  
    107.   
    108.     // algorithm selection here !!!  
    109.     private Double Interpolate(double x0, double xx0, double x1, double xx1, double x) {  
    110.           
    111.         return (1.0 + Math.cos(Math.PI +   
    112.                   (Math.PI / (x1-x0)) * (x-x0))) / 2.0 * (xx1-xx0) + xx0;  
    113.     }  
    114.   
    115.     Double Noise(int x, int y, int colorType)  
    116.     {  
    117.         if(colorType == 1) {  
    118.             if (x < 256 && y < 256)  
    119.                 return red_random[y * 256 + x];  
    120.             else  
    121.                 return 0.0;  
    122.         } else if(colorType == 2) {  
    123.             if (x < 256 && y < 256)  
    124.                 return green_random[y * 256 + x];  
    125.             else  
    126.                 return 0.0;  
    127.         } else {  
    128.             if (x < 256 && y < 256)  
    129.                 return blue_random[y * 256 + x];  
    130.             else  
    131.                 return 0.0;  
    132.         }  
    133.     }  
    134.   
    135.     public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {  
    136.         int type = image.getType();  
    137.         if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )  
    138.             image.getRaster().setDataElements( x, y, width, height, pixels );  
    139.         else  
    140.             image.setRGB( x, y, width, height, pixels, 0, width );  
    141.     }  
    142.       
    143.     public static void main(String[] args) {  
    144.         JFrame frame = new JFrame("Noise Art Panel");  
    145.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
    146.         frame.getContentPane().setLayout(new BorderLayout());  
    147.           
    148.         // Display the window.  
    149.         frame.getContentPane().add(new RandomNoiseImage(), BorderLayout.CENTER);  
    150.         frame.setPreferredSize(new Dimension(280,305));  
    151.         frame.pack();  
    152.         frame.setVisible(true);  
    153.     }  
    154. }  

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    vue2.0 动画
    I. 对缓存进行处理
    G. 【案例】Ajax实现无刷新分页效果
    H. Ajax对XML信息的接收与处理
    F. 异步同步请求
    D. 接收服务器端返回的信息
    E. 请求GET和POST的不同
    C. 发起对服务器的请求
    B. 创建Ajax对象
    A. AJAX介绍
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706380.html
Copyright © 2020-2023  润新知