パーリンノイズ(Perlin noise)

ランダムな画像を生成する方法の一つに、パーリンノイズの活用がある。
Wikipedia による パーリンノイズ の説明は次のような感じ。

パーリンノイズとは、コンピュータグラフィックスのリアリティを増すために使われるテクスチャ作成技法。擬似乱数的な見た目であるが、同時に細部のスケール感が一定である。このため制御が容易であり、各種スケールのパーリンノイズを数式に入力することで多彩なテクスチャを表現できる。パーリンノイズによるテクスチャは、CGIで自然な外観を物に与えるためによく使われる。

http://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%83%AA%E3%83%B3%E3%83%8E%E3%82%A4%E3%82%BA

単純な乱数で各画素の濃度値を決定した場合には、次のような不自然な(自然界には存在しないような)乱雑なノイズ画像が得られる。

上記の画像は、Javaアプレットのpaintメソッドを次のようにして生成した。

	public void paint(Graphics g){
		for(int y = 0; y < 1000; y++) {
			for(int x = 0; x < 1000; x++) {
				double b = Math.random();
				g.setColor(new Color( (int)(256*b), (int)(256*b), (int)(256*b)));
				g.fillRect(x, y, 1, 1);				
			}
		}		
	}

パーリンノイズの生成については、次の場所でJavaのプログラムコードが公開されている。
http://mrl.nyu.edu/~perlin/noise/

上記のループ内部を次のようにすることで、パーリンノイズ生成のためのImprovedNoiseクラスを使用した画像が得られる。

	double b = ImprovedNoise.noise(x/50.0f,  y/50.0f, 0);
	g.setColor(new Color( (int)(128 + 128*b), (int)(128 + 128*b), (int)(128 + 128*b)));
	g.fillRect(x, y, 1, 1);	

パーリンノイズを使用すると、次のような自然な(全体的に滑らかに濃淡が変化する)ノイズ画像になることが確認できる。

ImprovedNoiseクラスのnoiseメソッドは3つの引数を取るので、3次元的に連続したノイズ画像を生成できる。
この3つめの引数を時間軸にすれば、次のように滑らかに変化するアニメーションを生成できる。

http://youtube.com/watch?v=0KFk5uKYUY8

このアニメーションを生成するJavaアプレットのプログラムコードは次のような感じ。

import java.applet.*;
import java.awt.*;

public class PerlinNoiseAnimation extends Applet implements Runnable {
	private boolean running;
	private Dimension size;
	private Image bufferImage;
	private Graphics bufferg;
	private double z = 0;

	public void init() {
		running = true;
		new Thread(this).start();
		size = getSize();
		bufferImage = createImage(size.width, size.height);
		bufferg = bufferImage.getGraphics();
	}

	public void destroy() {
		running = false;
	}

	public void run() {
		while (running) {
			z += 0.005;
			repaint();
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void paint(Graphics g) {
		bufferg.setColor(getBackground());
		bufferg.fillRect(0, 0, size.width, size.height);

		for (int y = 0; y < 1000; y++) {
			for (int x = 0; x < 1000; x++) {
				double b = ImprovedNoise.noise(x / 50.0f, y / 50.0f, z);
				bufferg.setColor(new Color((int) (128 + 128 * b),
						(int) (128 + 128 * b), (int) (128 + 128 * b)));
				bufferg.fillRect(x, y, 1, 1);
			}
		}
		g.drawImage(bufferImage, 0, 0, this);

	}

	public void update(Graphics g) {
		paint(g);
	}
}

ちなみに、このパーリンノイズを発明したKen Perlin氏のWebページはこちら。
http://mrl.nyu.edu/~perlin/

ブログでは、楽しく遊べるJavaアプレットが多数公開されている。

画像処理工学―基礎編

画像処理工学―基礎編