Javaプログラミング学習サイト ゆるゆるプログラミング

2016/06/14 公開

・画像にノイズを加える

乱数を使って指定の画像ノイズ画像を加える方法を解説します。ノイズが発生する割合をパーセントで指定することで、ノイズの密度を調整することができるようにします。

Noise2.java ← クリックしてダウンロードページに移動
001:    import java.awt.image.BufferedImage;
002:    import java.io.File;
003:    import javax.imageio.ImageIO;
004:    import java.io.IOException;
005:    
006:    public class Noise2 {
007:    	public static void main( String[] args ) {
008:    		boolean result;	// 結果格納フラグ
009:    		double noiserate;	// ノイズの割合	
010:    
011:    		// ファイル名
012:    		String inname, outname;
013:    		// 画像格納クラス
014:    		BufferedImage img = null;
015:    
016:    		// 入力した引数が3つ以上かを調べる
017:    		if ( 3 > args.length ) {
018:    			// 入力した引数が3つ未満の場合、使用方法を表示する
019:    			System.out.println(
020:    				 "Noise2 [入力JPEG名]  [出力JPEG名] [ノイズの割合%]" );
021:    			return;
022:    		}
023:    
024:    		// 入力JPEG名をinnameに代入(拡張子".jpg"省略なし)
025:    		inname  = args[ 0 ];
026:    		// 出力JPEG名をoutnameに代入(拡張子".jpg"省略なし)
027:    		outname = args[ 1 ];
028:    
029:    		// 引数を変換し、ノイズの割合に代入
030:    		try {
031:    			noiserate = Double.valueOf( args[ 2 ] );
032:    		}
033:    		catch( NumberFormatException ne )
034:    		{
035:    			System.out.println( "引数が不正です" );
036:    			return;
037:    		}
038:    
039:    		// JPEGの読み込み
040:    		try {
041:    			// inname(入力JPEG)を読み込んでimgにセット
042:    			img = ImageIO.read( new File( inname ) );
043:    		} catch (Exception e) {
044:    			// inname(入力JPEG)の読み込みに失敗したときの処理
045:    			 e.printStackTrace();
046:    			return;
047:    		}
048:    
049:    		// 画像の色の持ち方をチェック
050:    		if ( BufferedImage.TYPE_3BYTE_BGR != img.getType() )
051:    		{
052:    			System.out.println( "対応していないカラーモデルです!("
053:    									 + inname +")" );
054:    			return;
055:    		}
056:    
057:    		// ノイズ画像の作成
058:    		int        x, y;
059:    		int        width, height;
060:    		int        r, g, b, color;
061:    		double rate;
062:    
063:    		// 画像サイズの取得
064:    		width = img.getWidth();
065:    		height= img.getHeight();
066:    	
067:    		// ノイズを加える
068:    		for ( y = 0; y < height; ++ y ) {
069:    			for ( x = 0; x < width; ++ x ) {
070:    				// 乱数を発生
071:    				rate = Math.random() * 100.0;
072:    
073:    				// ノイズ色にするかを判定
074:    				if ( noiserate > rate ) {
075:    					// ノイズとして白色を設定
076:    					r = 255;
077:    					g =255;
078:    					b =255;
079:    
080:    					// r,g,bの色を合成
081:    					color = ( r << 16 ) + ( g << 8 ) + b;
082:    
083:    					// 合成した色を(x,y)に設定
084:    					img.setRGB( x, y, color );
085:    				}
086:    			}
087:    		}
088:    
089:    		try {
090:    			// imgをoutname(出力JPEG)に保存
091:    			result = ImageIO.write( img, "jpeg", new File( outname ) );
092:    		} catch ( Exception e ) {
093:    			// outname(出力JPEG)の保存に失敗したときの処理
094:    			e.printStackTrace();
095:    			return;
096:    		}
097:    
098:    		// 正常に終了
099:    		System.out.println( "正常に終了しました" );
100:    	}
101:    }

Noise2を実行

C:\talavax\javasample>java Noise2 sampleimage001_400x320.jpg noise2.jpg 20.0

1つ目の引数で元のJPEGファイル名、2つ目の引数ノイズを加えたJPEG画像ファイル名、3つ目の引数ノイズピクセルの発生率をパーセントで指定します。

実行結果

・元の画像(sampleimage001_400x320.jpg)

元画像

・ノイズを加えた画像(noise2.jpg)

ノイズを加えた画像(20%)ノイズを加えた画像(20%)

画像に中にある白い点がノイズです。

ここからは、このJavaソースコードを上から順番に解説していきます。

001:    import java.awt.image.BufferedImage;
002:    import java.io.File;
003:    import javax.imageio.ImageIO;
004:    import java.io.IOException;
005:    

Javaクラスライブラリの中から「java.awt.image.BufferedImage」と「java.io.File」と「javax.imageio.ImageIO」と「java.io.IOException」と「java.awt.image.RasterFormatException」というパッケージにあるクラスを、このプログラム内で使うために記述します。 この記述により、ImageIOクラスBufferedImageクラスRasterFormatExceptionが利用できるようになります。

006:    public class Noise2 {

クラス名を、Noise2としています。

007:    	public static void main( String[] args ) {

このmainメソッドからプログラムを実行します。

008:    		boolean result;	// 結果格納フラグ
009:    		double noiserate;	// ノイズの割合	
010:    
011:    		// ファイル名
012:    		String inname, outname;
013:    		// 画像格納クラス
014:    		BufferedImage img = null;

このプログラムで使う変数を宣言しています。

016:    		// 入力した引数が3つ以上かを調べる
017:    		if ( 3 > args.length ) {
018:    			// 入力した引数が3つ未満の場合、使用方法を表示する
019:    			System.out.println(
020:    				 "Noise2 [入力JPEG名]  [出力JPEG名] [ノイズの割合%]" );
021:    			return;
022:    		}

3つ以上の引数が与えられたかをチェックし、4つ未満の場合に、使い方のメッセージを表示し、returnによってmainメソッドを抜けています。

024:    		// 入力JPEG名をinnameに代入(拡張子".jpg"省略なし)
025:    		inname  = args[ 0 ];
026:    		// 出力JPEG名をoutnameに代入(拡張子".jpg"省略なし)
027:    		outname = args[ 1 ];
028:    
029:    		// 引数を変換し、ノイズの割合に代入
030:    		try {
031:    			noiserate = Double.valueOf( args[ 2 ] );
032:    		}
033:    		catch( NumberFormatException ne )
034:    		{
035:    			System.out.println( "引数が不正です" );
036:    			return;
037:    		}

与えられた引数をそれぞれ、入力JPEGファイル名、出力JPEGファイル名、ノイズの割合を格納する変数に代入しています。

039:    		// JPEGの読み込み
040:    		try {
041:    			// inname(入力JPEG)を読み込んでimgにセット
042:    			img = ImageIO.read( new File( inname ) );
043:    		} catch (Exception e) {
044:    			// inname(入力JPEG)の読み込みに失敗したときの処理
045:    			 e.printStackTrace();
046:    			return;
047:    		}

BufferedImageクラスコンストラクタで、新しいBufferedImageを構築しています。

BufferedImageコンストラクタ

BufferedImage( int width, int height, int imageType )
■新しい BufferedImage を構築します。
  パラメータ width     : 構築する画像の横ピクセル
        height    : 構築する画像の縦ピクセル
        imageType : 構築する画像のイメージ形式

imgTypeで指定しているTYPE_INT_RGBは、整数ピクセルにパックされた 8 ビット RGB 色成分によるイメージを表します。これを指定することで24ビット画像を作成できます。

try { ~ } catchは、失敗する可能性がある処理を波括弧で囲み、その処理に失敗したときにcatch { ~ }の波括弧で囲まれた処理を実行するということです。この場合は、JPEGファイル名が不正であったり、存在していなかったり、フォーマットが違っているなどが原因で処理が失敗する可能性があります。処理が失敗するとreturnによってmainメソッドを抜けるようにしています。

049:    		// 画像の色の持ち方をチェック
050:    		if ( BufferedImage.TYPE_3BYTE_BGR != img.getType() )
051:    		{
052:    			System.out.println( "対応していないカラーモデルです!("
053:    									 + inname +")" );
054:    			return;
055:    		}

BufferedImageクラスgetTypeメソッド画像のイメージ型を取得しています。

BufferedImage.getTypeメソッド

public static int getType()
■イメージ型を返します。
  パラメータ なし

  戻り値     BufferedImage のイメージ型を返します。

057:    		// ノイズ画像の作成
058:    		int        x, y;
059:    		int        width, height;
060:    		int        r, g, b, color;
061:    		double rate;

ノイズ画像作成で使う変数を宣言しています。

063:    		// 画像サイズの取得
064:    		width = img.getWidth();
065:    		height= img.getHeight();

画像の幅を変数width、高さを変数heightに代入しています。

067:    		// ノイズを加える
068:    		for ( y = 0; y < height; ++ y ) {
069:    			for ( x = 0; x < width; ++ x ) {

画像の中の全てのピクセルの座標を参照するループをつくっています。具体的には、変数yを0~height-1、変数xを0~width-1に変化させています。

070:    				// 乱数を発生
071:    				rate = Math.random() * 100.0;

乱数からパーセントを計算した値(0.0~99.999..)を変数rateに代入しています。Math.randomメソッドは、0.0~0.99999..の乱数を発生するので、その値に100.0を掛けることでパーセントを計算しています。

Math.randomメソッド

public static double Math.random()
■乱数を返します。

  パラメータ なし

  戻り値     0.0以上、1.0未満の乱数

073:    				// ノイズ色にするかを判定
074:    				if ( noiserate > rate ) {

引数で指定したノイズの割合(noiserate)より、乱数から作成した値(rate)が小さければノイズと判定しています。この処理で、指定したノイズ割合を大きくすれば、ノイズの発生率が高くなるようにしています。

075:    					// ノイズとして白色を設定
076:    					r = 255;
077:    					g =255;
078:    					b =255;
079:    
080:    					// r,g,bの色を合成
081:    					color = ( r << 16 ) + ( g << 8 ) + b;

RGB合成して、色(変数color)を作成しています。

083:    					// 合成した色を(x,y)に設定
084:    					img.setRGB( x, y, color );

色(変数color)を(x,y)に代入しています。

089:    		try {
090:    			// imgをoutname(出力JPEG)に保存
091:    			result = ImageIO.write( img, "jpeg", new File( outname ) );
092:    		} catch ( Exception e ) {
093:    			// outname(出力JPEG)の保存に失敗したときの処理
094:    			e.printStackTrace();
095:    			return;
096:    		}

BufferedImageクラスのimgのメモリ内のデータを、出力JPEG名の変数(outname)に格納されているファイル名で保存します。この場合は、JPEGファイル名が不正であったり、保存先のHDDなどが存在していなかったり、空き容量が少ないなどが原因で処理が失敗する可能性があります。

ImageIO.writeメソッド

public static boolean write( RenderedImage im, String formatName, File output ) throws IOException
■BufferedImageを画像ファイルに保存します。

  パラメータ RenderedImage : 保存するRenderedImage
                  formatName     : 画像ファイルのフォーマット(png/jpeg/bmp/gifなど)
                  output             : Fileオブジェクト

  戻り値     保存に成功するとtrue、失敗するとfalseを返します。

098:    		// 正常に終了
099:    		System.out.println( "正常に終了しました" );

全ての処理が正常終了すると、ここまで処理が実行されます。

■関連コンテンツ

光と色の3原色 光と色の3原色の考え方を解説
画像の色 画像の色について解説
画像ファイル形式 画像ファイル形式について解説
コマンドライン引数 外部からの値を受け取る方法について解説
乱数を使ってノイズ画像を作成する方法について解説-画像

ノイズ画像

乱数を使ったノイズ画像の作成方法について解説しています。

正確な割合のノイズ画像を作成する方法を解説-画像

正確な割合のノイズ画像

乱数を使って正確な割合のノイズ画像を作成する方法を解説しています。

光と色の3原色の考え方を解説-画像

光と色の3原色

光の3色(RGB)の混合と、インクの3色(CMY)の混合の考え方を説明しています。

画素について説明-画像

画素

画素とは、デジタル画像データを構成している色情報を持った点のことです。

繰り返し処理に使用するfor文について解説-画像

for文

繰り返し処理に使用するfor文をJavaのソースコードを使って説明しています。

Math.randomの使い方について解説-画像

乱数 random

Math.randomメソッドを使って乱数を発生する方法を解説します。指定範囲の乱数の発生方法も解説しています。

■新着情報

2022.07.07 外部プログラムの実行 exeファイル実行
2022.07.06 完全数 6=1+2+3

■広告

 

 

 

 

 

スッキリわかるJava入門第3版 [ 中山清喬 ]

価格:2,860円
(2021/6/18 14:32時点)
感想(6件)

 

 

 

 

Topへ