2016/01/21 公開
・2値化
2値化とは、カラーの画像を2つの色だけで表現した画像に変換することです。一般的には白と黒だけで表現しますが、2色であればどんな組み合わせでも良いです。
光の三原色の赤(R)、緑(G)、青(B)の輝度の平均値がある値(閾値)以上で白、未満で黒になるようにすることで2値化画像を作成することができます。
次に、フルカラー(24bit)画像を2値画像に変換するソースコードを解説します。以下が、そのソースコード例です。
Binarization.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 Binarization { 007: public static void main( String[] args ) { 008: // 閾値 009: int tv; 010: // ファイル名 011: String inname, outname; 012: // 画像格納クラス 013: BufferedImage img = null; 014: 015: // 入力した引数が3つ以上かを調べる 016: if ( 3 > args.length ) { 017: // 入力した引数が3つ未満の場合、使用方法を表示する 018: System.out.println( 019: "Binarization [入力JPEG名] [出力PNG名] [閾(しきい)値]" ); 020: return; 021: } 022: 023: // 入力JPEG名をinnameに代入(拡張子".jpg"省略なし) 024: inname = args[ 0 ]; 025: // 出力PNG名をoutnameに代入(拡張子".png"省略なし) 026: outname = args[ 1 ]; 027: 028: // 閾値をtvに代入 029: try { 030: // 閾値を代入 031: tv = Integer.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: // 2値化 058: int x, y; 059: int width, height; 060: int color, r, g, b; 061: int p; 062: int newcolor; 063: 064: // 画像サイズの取得 065: width = img.getWidth(); 066: height= img.getHeight(); 067: 068: for ( y = 0; y < height; ++ y ) { 069: for ( x = 0; x < width; ++ x ) { 070: // (x,y)の色を取得 071: color = img.getRGB( x, y ); 072: 073: // 色をr,g,bに分解 074: r = ( color >> 16 ) & 0xff; 075: g = ( color >> 8 ) & 0xff; 076: b = color & 0xff; 077: 078: // rgbの平均値を計算 079: p = ( r + g + b ) / 3; 080: 081: // 2値化 082: if ( tv <= p ) { 083: // 閾値tv以上なら白 084: r = 255; 085: g = 255; 086: b = 255; 087: } 088: else { 089: // 閾値tv未満なら黒 090: r = 0; 091: g = 0; 092: b = 0; 093: } 094: 095: // r,g,bの色を合成 096: newcolor = ( r << 16 ) + ( g << 8 ) + b; 097: 098: // 合成した色を(x,y)に設定 099: img.setRGB( x, y, newcolor ); 100: } 101: } 102: 103: try { 104: boolean result; 105: // imgをoutname(出力PNG)に保存 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: }
Binarizationを実行
C:\talavax\javasample>java Binarization sampleimage001_400x320.jpg binarization.png 127
1つ目の引数で渡したJPEGファイルを2値の画像に変換し、2つ目の引数で指定したPNGファイル名で保存します。
実行結果
・元の画像(sampleimage001_400x320.jpg)
・変換後の2値画像(binarization_127.png) 閾値:127
・変換後の2値画像(binarization_100.png) 閾値:100
・変換後の2値画像(binarization_80.png) 閾値:80
画像が、白と黒の2色で表現されました。
ここからは、このソースコードを上から順番に解説していきます。
001: import java.awt.image.BufferedImage; 002: import java.io.File; 003: import javax.imageio.ImageIO; 004: import java.io.IOException;
Javaのクラスライブラリの中から「java.awt.image.BufferedImage」と「java.io.File」と「javax.imageio.ImageIO」と「java.io.IOException」というパッケージにあるクラスを、このプログラム内で使うために記述します。 この記述により、ImageIOクラスとBufferedImageクラスが利用できるようになります。
006: public class Binarization {
クラス名を、Binarizationとしています。
007: public static void main( String[] args ) {
このmainメソッドからプログラムを実行します。
008: // 閾値 009: int tv; 010: // ファイル名 011: String inname, outname; 012: // 画像格納クラス 013: BufferedImage img = null;
このプログラムで使う変数を宣言しています。どのように使われているかは、後ろのソースコードで。
015: // 入力した引数が3つ以上かを調べる 016: if ( 3 > args.length ) { 017: // 入力した引数が3つ未満の場合、使用方法を表示する 018: System.out.println( 019: "Binarization [入力JPEG名] [出力PNG名] [閾(しきい)値]" ); 020: return; 021: }
3つ以上の引数が与えられたかをチェックし、3つ未満の場合に、使い方のメッセージを表示し、returnによってmainメソッドを抜けています。
023: // 入力JPEG名をinnameに代入(拡張子".jpg"省略なし) 024: inname = args[ 0 ]; 025: // 出力PNG名をoutnameに代入(拡張子".png"省略なし) 026: outname = args[ 1 ];
与えられた引数をそれぞれ、入力JPEG名の変数(inname)、出力PNG名の変数(outname)代入しています。
028: // 閾値をtvに代入 029: try { 030: // 閾値を代入 031: tv = Integer.valueOf( args[ 2 ] ); 032: } 033: catch( NumberFormatException ne ) 034: { 035: System.out.println( "引数が不正です" ); 036: return; 037: }
3番目に与えられた引数を閾値の変数(tv)に代入しています。
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: }
入力JPEG名の変数(inname)を読み込んで、BufferedImageクラスのimgに格納しています。この処理には、ImageIOクラスのreadメソッドを使います。
ImageIO.readメソッド
■Fileオブジェクトを復元した結果をBufferedImageに格納します。 パラメータ input : Fileオブジェクト 戻り値 inputを復元したBufferedImageaを返します。
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メソッド
■イメージ型を返します。 パラメータ なし 戻り値 BufferedImage のイメージ型を返します。
057: // 2値化 058: int x, y; 059: int width, height; 060: int color, r, g, b; 061: int p; 062: int newcolor;
2値化で使う変数を宣言しています。
064: // 画像サイズの取得 065: width = img.getWidth(); 066: height= img.getHeight();
widthに画像の幅(ピクセル)、heightに画像の高さ(ピクセル)を代入しています。
068: for ( y = 0; y < height; ++ y ) { 069: for ( x = 0; x < width; ++ x ) { 070: // (x,y)の色を取得 071: color = img.getRGB( x, y );
画像の中の全てのピクセルの座標を参照する変数xと変数yの多重ループをつくり、その座標の色情報を取得しています。具体的には、変数yを0~height-1、変数xを0~width-1に変化させながら、BufferedImageクラスのgetRGBメソッドで、(x,y)の色を変数colorに代入しています。
BufferedImage.getRGBメソッド
■(x,y)で指定した画像座標の色情報を取得します。 パラメータ x : 画像のx座標(単位ピクセル) y : 画像のy座標(単位ピクセル) 戻り値 (x,y)の色情報
073: // 色をr,g,bに分解 074: r = ( color >> 16 ) & 0xff; 075: g = ( color >> 8 ) & 0xff; 076: b = color & 0xff;
変数colorに入っている色情報を赤(R)、緑(G)画、青(B)の成分に分解し、それぞれ変数a、b、cに代入しています。
色の分解方法の詳細はこちらを参照してください。「色をARGB値に分解」
078: // rgbの平均値を計算 079: p = ( r + g + b ) / 3;
赤(R)、緑(G)、青(B)の成分の合計値を3で割り平均値を求め、その値を変数pに代入しています。
081: // 2値化 082: if ( tv <= p ) { 083: // 閾値tv以上なら白 084: r = 255; 085: g = 255; 086: b = 255; 087: } 088: else { 089: // 閾値tv未満なら黒 090: r = 0; 091: g = 0; 092: b = 0; 093: }
赤(R)、緑(G)、青(B)の成分の平均値(変数p)が閾値以上であれば白(r=255,g=255,b=255)とし、未満であれば黒(r=0,g=0,b=0)にしています。
095: // r,g,bの色を合成 096: newcolor = ( r << 16 ) + ( g << 8 ) + b;
色の成分を合成して、新しい色(変数newcolor)を作成しています。
098: // 合成した色を(x,y)に設定 099: img.setRGB( x, y, newcolor );
新しい色(変数newcolor)を(x,y)に代入して、カラーの色情報を2値に変換しています。
103: try { 104: boolean result; 105: // imgをoutname(出力PNG)に保存 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( "正常に終了しました" );
全ての処理が正常終了すると、ここまで処理が実行されます。
以上です。
■関連コンテンツ
画像の色 | 画像の色について解説 |
画像ファイル形式 | 画像ファイル形式について解説 |
N値化 | カラー画像をN値化する方法について解説 |
色をARGB値に分解 | 色情報→ARGB |
グレースケール変換カラー画像のRGB値の平均でグレースケールに変換する方法について解説しています。 |
|
より自然なグレースケール変換NTSC 加重平均法によるグレースケールに変換について解説しています。 |
|
2値化 その2インデックスカラーを使ってカラー画像を2値化する方法を解説しています。2値化した画像は1ビットのBMPで保存します。 |
|
光と色の3原色光の3色(RGB)の混合と、インクの3色(CMY)の混合の考え方を説明しています。 |
|
画素画素とは、デジタル画像データを構成している色情報を持った点のことです。 |
|
for文繰り返し処理に使用するfor文をJavaのソースコードを使って説明しています。 |
|
多重ループfor文などのループの中にループをいれたプログラムの構造、多重ループについて説明しています。 |
■新着情報
2022.07.07 | 外部プログラムの実行 | exeファイル実行 |
2022.07.06 | 完全数 | 6=1+2+3 |
■広告