2020/11/11 公開
・正確な割合のノイズ画像
乱数を使って指定サイズのノイズ画像を作る方法を解説します。ノイズが発生する割合をパーセントで指定することで、ノイズの密度を調整することができるようにします。
(幅ピクセル数×高さピクセル数)× 発生する割合(%)÷100
になる方法を説明します。(小数点以下は切捨て)
次に、上記の式でノイズピクセル数を計算し、画像の上部をノイズ数の黒色ピクセルで埋めます。(下図の左)
最後に、画像の全てのピクセルの色を乱数を使って入れ替えます。(下図の右)
この処理によって、ノイズピクセルの割合を正確にすることができます。
Noise3.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 Noise3 { 007: public static void main( String[] args ) { 008: // 変数宣言 009: int w, h; // 画像の幅・高さ 010: double noiserate; // ノイズの割合 011: String outname; // 出力ファイル名 012: BufferedImage img = null; // 画像格納クラス 013: 014: // 入力した引数が4以上かを調べる 015: if ( 4 > args.length ) { 016: // 入力した引数が4未満の場合、使用方法を表示する 017: System.out.println( 018: "Noise3 [出力PNG名][幅][高][ノイズの割合%]" ); 019: return; 020: } 021: 022: try { 023: // 引数を変換し、画像サイズに代入 024: w = Integer.valueOf( args[ 1 ] ); 025: h = Integer.valueOf( args[ 2 ] ); 026: // 引数を変換し、ノイズの割合に代入 027: noiserate = Double.valueOf( args[ 3 ] ); 028: } 029: catch( NumberFormatException ne ) 030: { 031: System.out.println( "引数が不正です" ); 032: return; 033: } 034: 035: // 出力PNG名をoutnameに代入(拡張子".png"省略なし) 036: outname = args[ 0 ]; 037: 038: // 新しい画像を作成 039: // 24ビットカラーの画像を作成 040: try { 041: img = new BufferedImage( w, h, 042: BufferedImage.TYPE_INT_RGB ); 043: } catch ( Exception e ) { 044: // 画像作成に失敗したときの処理 045: e.printStackTrace(); 046: return; 047: } 048: 049: // ノイズ画像の作成 050: int x, y, noisecount; 051: int sx, sy; 052: int r, g, b, color; 053: int color1, color2; 054: 055: // ノイズ数を正確に計算 056: noisecount = (int)( (double)( h * w ) * noiserate / 100.0 ); 057: 058: // ノイズ画像の元になる画像を作成 059: for ( y = 0; y < h; ++ y ) { 060: for ( x = 0; x < w; ++ x ) { 061: // ノイズ色を決定 062: if ( 1 <= noisecount ) { 063: // ノイズとして黒色を設定 064: r = 0; 065: g = 0; 066: b = 0; 067: -- noisecount; 068: } 069: else { 070: // ノイズでない白色を設定 071: r = 255; 072: g = 255; 073: b = 255; 074: } 075: 076: // r,g,bの色を合成 077: color = ( r << 16 ) + ( g << 8 ) + b; 078: 079: // 合成した色を(x,y)に設定 080: img.setRGB( x, y, color ); 081: } 082: } 083: 084: // 全ピクセルをランダムに並び替え 085: for ( y = 0; y < h; ++ y ) { 086: for ( x = 0; x < w; ++ x ) { 087: // sxに0~w-1の乱数を格納 088: sx = (int)( Math.random() * (double)w ); 089: 090: // syに0~h-1の乱数を格納 091: sy = (int)( Math.random() * (double)h ); 092: 093: // (x,y)と(sx,sy)の色を入れ替える 094: color1 = img.getRGB( x, y ); 095: color2 = img.getRGB( sx, sy ); 096: img.setRGB( x, y, color2 ); 097: img.setRGB( sx, sy, color1 ); 098: } 099: } 100: 101: 102: // 画像をPNG出力 103: try { 104: // imgをoutname(出力PNG)に保存 105: boolean result; 106: result = ImageIO.write( img, "PNG", new File( outname ) ); 107: } catch ( Exception e ) { 108: // outname(出力PNG)の保存に失敗したときの処理 109: e.printStackTrace(); 110: return; 111: } 112: 113: // 正常に終了 114: System.out.println( "正常に終了しました" ); 115: } 116: }
Noise3を実行
C:\talavax\javasample>java Noise3 noise3_50.png 256 256 50
2つ目と3つ目の引数でピクセル座標、4つ目の引数でノイズピクセルの発生率をパーセントで指定します。これらの引数からノイズ画像を作成し、1つ目の引数で指定したPNGファイル名で保存します。
この例では、ノイズピクセル発生率50%で、サイズ256x256のPNGファイル(noise3_50.png)を作成しています。
実行結果
ノイズ発生率50%、幅256ピクセル、高さ256ピクセルのノイズ画像が作成されました。黒色がノイズピクセルです。
ここからは、この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 Noise3 {
クラス名を、Noise3としています。
007: public static void main( String[] args ) {
このmainメソッドからプログラムを実行します。
008: // 変数宣言 009: int w, h; // 画像の幅・高さ 010: double noiserate; // ノイズの割合 011: String outname; // 出力ファイル名 012: BufferedImage img = null; // 画像格納クラス
このプログラムで使う変数を宣言しています。
014: // 入力した引数が4以上かを調べる 015: if ( 4 > args.length ) { 016: // 入力した引数が4未満の場合、使用方法を表示する 017: System.out.println( 018: "Noise3 [出力PNG名][幅][高][ノイズの割合%]" ); 019: return; 020: }
4つ以上の引数が与えられたかをチェックし、4つ未満の場合に、使い方のメッセージを表示し、returnによってmainメソッドを抜けています。
022: try { 023: // 引数を変換し、画像サイズに代入 024: w = Integer.valueOf( args[ 1 ] ); 025: h = Integer.valueOf( args[ 2 ] ); 026: // 引数を変換し、ノイズの割合に代入 027: noiserate = Double.valueOf( args[ 3 ] ); 028: } 029: catch( NumberFormatException ne ) 030: { 031: System.out.println( "引数が不正です" ); 032: return; 033: }
与えられた引数をそれぞれ、ピクセル幅、、ピクセルの高さ、ノイズの割合を格納する変数に代入しています。
035: // 出力PNG名をoutnameに代入(拡張子".png"省略なし) 036: outname = args[ 0 ];
与えられた引数を、出力PNG名の変数(outname)代入しています。
038: // 新しい画像を作成 039: // 24ビットカラーの画像を作成 040: try { 041: img = new BufferedImage( w, h, 042: BufferedImage.TYPE_INT_RGB ); 043: } catch ( Exception e ) { 044: // 画像作成に失敗したときの処理 045: e.printStackTrace(); 046: return; 047: }
BufferedImageクラスのコンストラクタで、新しいBufferedImageを構築しています。
BufferedImageコンストラクタ
■新しい BufferedImage を構築します。 パラメータ width : 構築する画像の横ピクセル height : 構築する画像の縦ピクセル imageType : 構築する画像のイメージ形式
imgTypeで指定しているTYPE_INT_RGBは、整数型ピクセルにパックされた 8 ビット RGB 色成分によるイメージを表します。これを指定することで24ビットの画像を作成できます。
try { ~ } catchは、失敗する可能性がある処理を波括弧で囲み、その処理に失敗したときにcatch { ~ }の波括弧で囲まれた処理を実行するということです。この場合は、PNGファイル名が不正であったり、存在していなかったり、フォーマットが違っているなどが原因で処理が失敗する可能性があります。処理が失敗するとreturnによってmainメソッドを抜けるようにしています。
049: // ノイズ画像の作成 050: int x, y, noisecount; 051: int sx, sy; 052: int r, g, b, color; 053: int color1, color2;
055: // ノイズ数を正確に計算 056: noisecount = (int)( (double)( h * w ) * noiserate / 100.0 );
画像の幅と高さのピクセル数とノイズの割合からノイズピクセルの個数を計算し、結果をint型の変数noisecountに代入しています。
058: // ノイズ画像の元になる画像を作成 059: for ( y = 0; y < h; ++ y ) { 060: for ( x = 0; x < w; ++ x ) { 061: // ノイズ色を決定 062: if ( 1 <= noisecount ) { 063: // ノイズとして黒色を設定 064: r = 0; 065: g = 0; 066: b = 0; 067: -- noisecount; 068: } 069: else { 070: // ノイズでない白色を設定 071: r = 255; 072: g = 255; 073: b = 255; 074: } 075: 076: // r,g,bの色を合成 077: color = ( r << 16 ) + ( g << 8 ) + b; 078: 079: // 合成した色を(x,y)に設定 080: img.setRGB( x, y, color ); 081: } 082: }
画像の中の全てのピクセルの座標を参照するループをつくっています。具体的には、変数yを0~h-1、変数xを0~w-1に変化させています。
このループの中で、noisecountが1以上であればノイズ色のピクセルを代入しています。ノイズ色を代入する毎に、noisecountから1ずつひいています。
084: // 全ピクセルをランダムに並び替え 085: for ( y = 0; y < h; ++ y ) { 086: for ( x = 0; x < w; ++ x ) { 087: // sxに0~w-1の乱数を格納 088: sx = (int)( Math.random() * (double)w ); 089: 090: // syに0~h-1の乱数を格納 091: sy = (int)( Math.random() * (double)h ); 092: 093: // (x,y)と(sx,sy)の色を入れ替える 094: color1 = img.getRGB( x, y ); 095: color2 = img.getRGB( sx, sy ); 096: img.setRGB( x, y, color2 ); 097: img.setRGB( sx, sy, color1 ); 098: } 099: }
画像の中の全てのピクセルの座標を参照するループをつくっています。具体的には、変数yを0~h-1、変数xを0~w-1に変化させています。
このループの中で、画像座標(x,y)の色と、ランダムに発生した画像座標(sx,sy)の色を入れ替えています。
Math.randomメソッド
■乱数を返します。 パラメータ なし 戻り値 0.0以上、1.0未満の乱数
102: // 画像をPNG出力 103: try { 104: // imgをoutname(出力PNG)に保存 105: boolean result; 106: result = ImageIO.write( img, "PNG", new File( outname ) ); 107: } catch ( Exception e ) { 108: // outname(出力PNG)の保存に失敗したときの処理 109: e.printStackTrace(); 110: return; 111: }
BufferedImageクラスのimgのメモリ内のデータを、出力PNG名の変数(outname)に格納されているファイル名で保存します。この場合は、PNGファイル名が不正であったり、保存先のHDDなどが存在していなかったり、空き容量が少ないなどが原因で処理が失敗する可能性があります。
ImageIO.writeメソッド
■BufferedImageを画像ファイルに保存します。 パラメータ RenderedImage : 保存するRenderedImage formatName : 画像ファイルのフォーマット(png/jpeg/bmp/gifなど) output : Fileオブジェクト 戻り値 保存に成功するとtrue、失敗するとfalseを返します。
113: // 正常に終了 114: System.out.println( "正常に終了しました" );
全ての処理が正常終了すると、ここまで処理が実行されます。
以上です。
■関連コンテンツ
画像の色 | 画像の色について解説 |
画像ファイル形式 | 画像ファイル形式について解説 |
配列の並び替え | 配列をランダムに並び替える方法を解説 |
コマンドライン引数 | 外部からの値を受け取る方法について解説 |
ノイズ画像乱数を使ったノイズ画像の作成方法について解説しています。 |
|
画像にノイズを加える乱数を使って画像にノイズを加える方法を解説しています。 |
|
光と色の3原色光の3色(RGB)の混合と、インクの3色(CMY)の混合の考え方を説明しています。 |
|
画素画素とは、デジタル画像データを構成している色情報を持った点のことです。 |
|
for文繰り返し処理に使用するfor文をJavaのソースコードを使って説明しています。 |
|
乱数 randomMath.randomメソッドを使って乱数を発生する方法を解説します。指定範囲の乱数の発生方法も解説しています。 |
■新着情報
2022.07.07 | 外部プログラムの実行 | exeファイル実行 |
2022.07.06 | 完全数 | 6=1+2+3 |
■広告