2020/10/13 公開
・2値化 その2
フルカラーの画像を2色だけで表現した2値画像に変換し、2値のBMP形式で保存する方法を説明します。
フルカラー画像が持つ画素の色RGBの値が、白と黒のどちらの色に近いかを自動判定し、その近い色で埋めて画像を作成します。
ここで紹介する方法は、BufferedImageクラスで2値の画像を作成し、setRGBメソッドでフルカラー画像のRGB値を格納していくものです。
BufferedImageクラスで作成した2値画像のカラーマップは黒(R=G=B=0)と白(R=G=B=255)の2色となります。この2つの色は、後で変えることもできます。
この2値画像に任意のRGB値を格納すると、自動的に2色のうちの近いほうの色を選んでくれます。これにより簡単に2値の画像を作成することができます。
2値化した画像は、2値のBMP形式で保存するようにしています。
Binarization2.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 Binarization2 { 007: public static void main( String[] args ) { 008: // ファイル名 009: String inname, outname; 010: // 画像格納クラス 011: BufferedImage img = null; 012: 013: // 入力した引数が2つ以上かを調べる 014: if ( 2 > args.length ) { 015: // 入力した引数が2つ未満の場合、使用方法を表示する 016: System.out.println( 017: "Binarization2 [入力JPEG名] [出力BMP名]" ); 018: return; 019: } 020: 021: // 入力JPEG名をinnameに代入(拡張子".jpg"省略なし) 022: inname = args[ 0 ]; 023: // 出力BMP名をoutnameに代入(拡張子".bmp"省略なし) 024: outname = args[ 1 ]; 025: 026: // JPEG画像の読み込み 027: try { 028: // inname(入力JPEG)を読み込んでimgにセット 029: img = ImageIO.read( new File( inname ) ); 030: } catch (Exception e) { 031: // inname(入力JPEG)の読み込みに失敗したときの処理 032: e.printStackTrace(); 033: return; 034: } 035: 036: // 画像の色の持ち方をチェック 037: if ( BufferedImage.TYPE_3BYTE_BGR != img.getType() ) 038: { 039: System.out.println( "対応していないカラーモデルです!(" 040: + inname +")" ); 041: return; 042: } 043: 044: // 2値化 045: int x, y; 046: int width, height; 047: int color, r, g, b; 048: int newcolor; 049: BufferedImage img2 = null; 050: 051: // 画像サイズの取得 052: width = img.getWidth(); 053: height= img.getHeight(); 054: 055: // 1ビットカラーの画像を作成 056: try { 057: img2 = new BufferedImage( width, height, 058: BufferedImage.TYPE_BYTE_BINARY ); 059: } catch ( Exception e ) { 060: // 画像作成に失敗したときの処理 061: e.printStackTrace(); 062: return; 063: } 064: 065: // 2値化処理 066: for ( y = 0; y < height; ++ y ) { 067: for ( x = 0; x < width; ++ x ) { 068: // (x,y)の色を取得 069: color = img.getRGB( x, y ); 070: 071: // 色をr,g,bに分解 072: r = ( color >> 16 ) & 0xff; 073: g = ( color >> 8 ) & 0xff; 074: b = color & 0xff; 075: 076: // r,g,bの色を合成 077: newcolor = ( r << 16 ) + ( g << 8 ) + b; 078: 079: // 合成した色を(x,y)に設定 080: img2.setRGB( x, y, newcolor ); 081: } 082: } 083: 084: // 2値のBMPで保存 085: try { 086: boolean result; 087: // imgをoutname(出力BMP)に保存 088: result = ImageIO.write( img2, "bmp", new File( outname ) ); 089: } catch ( Exception e ) { 090: // outname(出力BMP)の保存に失敗したときの処理 091: e.printStackTrace(); 092: return; 093: } 094: 095: // 正常に終了 096: System.out.println( "正常に終了しました" ); 097: } 098: }
Binarization2を実行
java Binarization2 indexcolor-full.jpg binarization2.bmp
1つ目の引数で渡したJPEGファイルをグレースケールの画像に変換し、2つ目の引数で指定したBMPファイル名で保存します。
実行結果
・元の画像(indexcolor-full.jpg.jpg)
・変換後の2値のBMP画像(binarization2.bmp)
画像が、白と黒の2色で表現されました。作成したBMP形式の画像は非圧縮ですが、ビットの深さが1(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 Binarization2 {
クラス名を、Binarization2としています。
007: public static void main( String[] args ) {
このmainメソッドからプログラムを実行します。
008: // ファイル名 009: String inname, outname; 010: // 画像格納クラス 011: BufferedImage img = null;
このプログラムで使う変数を宣言しています。
013: // 入力した引数が2つ以上かを調べる 014: if ( 2 > args.length ) { 015: // 入力した引数が2つ未満の場合、使用方法を表示する 016: System.out.println( 017: "Binarization2 [入力JPEG名] [出力BMP名]" ); 018: return; 019: }
2つ以上の引数が与えられたかをチェックし、2つ未満の場合に、使い方のメッセージを表示し、returnによってmainメソッドを抜けています。
021: // 入力JPEG名をinnameに代入(拡張子".jpg"省略なし) 022: inname = args[ 0 ]; 023: // 出力BMP名をoutnameに代入(拡張子".bmp"省略なし) 024: outname = args[ 1 ];
与えられた引数をそれぞれ、入力JPEG名の変数(inname)、出力BMP名の変数(outname)代入しています。
026: // JPEG画像の読み込み 027: try { 028: // inname(入力JPEG)を読み込んでimgにセット 029: img = ImageIO.read( new File( inname ) ); 030: } catch (Exception e) { 031: // inname(入力JPEG)の読み込みに失敗したときの処理 032: e.printStackTrace(); 033: return; 034: }
入力JPEG名の変数(inname)を読み込んで、BufferedImageクラスのimgに格納しています。この処理には、ImageIOクラスのreadメソッドを使います。
ImageIO.readメソッド
■Fileオブジェクトを復元した結果をBufferedImageに格納します。 パラメータ input : Fileオブジェクト 戻り値 inputを復元したBufferedImageaを返します。
try { ~ } catchは、失敗する可能性がある処理を波括弧で囲み、その処理に失敗したときにcatch { ~ }の波括弧で囲まれた処理を実行するということです。この場合は、JPEGファイル名が不正であったり、存在していなかったり、フォーマットが違っているなどが原因で処理が失敗する可能性があります。処理が失敗するとreturnによってmainメソッドを抜けるようにしています。
036: // 画像の色の持ち方をチェック 037: if ( BufferedImage.TYPE_3BYTE_BGR != img.getType() ) 038: { 039: System.out.println( "対応していないカラーモデルです!(" 040: + inname +")" ); 041: return; 042: }
BufferedImageクラスのgetTypeメソッドで画像のイメージ型を取得しています。
BufferedImage.getTypeメソッド
■イメージ型を返します。 パラメータ なし 戻り値 BufferedImage のイメージ型を返します。
044: // 2値化 045: int x, y; 046: int width, height; 047: int color, r, g, b; 048: int newcolor; 049: BufferedImage img2 = null;
051: // 画像サイズの取得 052: width = img.getWidth(); 053: height= img.getHeight();
widthに画像の幅(ピクセル)、heightに画像の高さ(ピクセル)を代入しています。
055: // 1ビットカラーの画像を作成 056: try { 057: img2 = new BufferedImage( width, height, 058: BufferedImage.TYPE_BYTE_BINARY ); 059: } catch ( Exception e ) { 060: // 画像作成に失敗したときの処理 061: e.printStackTrace(); 062: return; 063: }
フルカラーと同じ大きさの新しい2値画像を作成しています。色の種類BufferedImage.TYPE_BYTE_BINARYでBufferedImageクラスを作成すると2値画像になります。
065: // 2値化処理 066: for ( y = 0; y < height; ++ y ) { 067: for ( x = 0; x < width; ++ x ) { 068: // (x,y)の色を取得 069: 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)の色情報
071: // 色をr,g,bに分解 072: r = ( color >> 16 ) & 0xff; 073: g = ( color >> 8 ) & 0xff; 074: b = color & 0xff;
変数colorに入っている色情報を赤(R)、緑(G)画、青(B)の成分に分解し、それぞれ変数a、b、cに代入しています。
色の分解方法の詳細はこちらを参照してください。「色をARGB値に分解」
076: // r,g,bの色を合成 077: newcolor = ( r << 16 ) + ( g << 8 ) + b;
色の成分を合成して、新しい色(変数newcolor)を作成しています。
079: // 合成した色を(x,y)に設定 080: img2.setRGB( x, y, newcolor );
新しい色(変数newcolor)を(x,y)に代入すると自動的に近い方の色が選択されます。
084: // 2値のBMPで保存 085: try { 086: boolean result; 087: // imgをoutname(出力BMP)に保存 088: result = ImageIO.write( img2, "bmp", new File( outname ) ); 089: } catch ( Exception e ) { 090: // outname(出力BMP)の保存に失敗したときの処理 091: e.printStackTrace(); 092: return; 093: }
BufferedImageクラスのimgのメモリ内のデータを、出力BMP名の変数(outname)に格納されているファイル名で保存します。この場合は、BMPファイル名が不正であったり、保存先のHDDなどが存在していなかったり、空き容量が少ないなどが原因で処理が失敗する可能性があります。
ImageIO.writeメソッド
■BufferedImageを画像ファイルに保存します。 パラメータ RenderedImage : 保存するRenderedImage formatName : 画像ファイルのフォーマット(png/jpeg/bmp/gifなど) output : Fileオブジェクト 戻り値 保存に成功するとtrue、失敗するとfalseを返します。
095: // 正常に終了 096: System.out.println( "正常に終了しました" );
全ての処理が正常終了すると、ここまで処理が実行されます。
以上です。
■関連コンテンツ
カラーマップ | 色番号に色を割り当て |
画像の色 | 画像の色について解説 |
画像ファイル形式 | 画像ファイル形式について解説 |
N値化 | カラー画像をN値化する方法について解説 |
グレースケール変換カラー画像のRGB値の平均でグレースケールに変換する方法について解説しています。 |
|
より自然なグレースケール変換NTSC 加重平均法によるグレースケールに変換について解説しています。 |
|
2値化RGBの平均値と閾値を使ってカラー画像を2値化する方法を解説しています。 |
|
光と色の3原色光の3色(RGB)の混合と、インクの3色(CMY)の混合の考え方を説明しています。 |
|
画素画素とは、デジタル画像データを構成している色情報を持った点のことです。 |
|
for文繰り返し処理に使用するfor文をJavaのソースコードを使って説明しています。 |
|
多重ループfor文などのループの中にループをいれたプログラムの構造、多重ループについて説明しています。 |
■新着情報
2022.07.07 | 外部プログラムの実行 | exeファイル実行 |
2022.07.06 | 完全数 | 6=1+2+3 |
■広告