拙作マンホールマップの隠し(?)機能でも使っている手法の1つを紹介します。
マンホールマップで特定のマンホール画像を表示すると、このような画面になります(PC版の場合):
http://manholemap.juge.me/page.jsp?id=1125001 の例

http://manholemap.juge.me/page.jsp?id=157009 の例

注目していただきたいのは地図部分ではなくマンホール画像部分です。画像が色の付いた枠(上は青枠、下は赤枠)で囲われていることにお気づきでしょうか?
これ、実は画像全体の色味を表しています。つまり上の画像は「全体的に青っぽい」、下の画像は「全体的に赤っぽい」ことを自動判断して表示しているのです。なんとなく合ってます(よね)。実際のアプリケーションでは赤、青、緑、黄、紫、そしてマジェンタの6種類のいずれかと判断しています。
これをどうやって実現しているか、というのが今回のネタです。
マンホールマップは Java で開発していて、特にこの部分は Java の拡張クラスである ImageIO (javax.imageio.ImageIO)を使っています。具体的にはこのようなコードです:
この例では画像バイナリのバイト配列( byte[] img )を引数として受け取る GetImageColor() 関数を定義しています。その中でまず ImageIO.read を使って、画像の BufferedImage を取り出します。
正しく取り出すことができたら、画像の幅と高さをピクセル単位で取得し、2重の for ループ内で1ピクセルずつ BufferedImage.getRGB 関数を実行し、RGB 値を取り出す、という処理を実行しています。これで1ピクセル毎の RGB 値を取り出すことができます。
あとはこの結果から、赤、青、緑、黄、紫、そしてマジェンタのどの色が多く使われているか、、、を調べるわけですが、そのあたりの細かなアルゴリズムは秘密(というか面倒なので省略)、ということで(苦笑)。
ちなみに白と黒が含まれていない理由は「マンホールの色が黒(または白)」というのは「普通過ぎてつまらないから、黒と白を除いて近い色を探す」という工夫をしているからでした。
この方法を応用することで、色んな画像の色情報(RGB値)を1ピクセル毎に取り出して判断することができるようになります。
マンホールマップで特定のマンホール画像を表示すると、このような画面になります(PC版の場合):
http://manholemap.juge.me/page.jsp?id=1125001 の例

http://manholemap.juge.me/page.jsp?id=157009 の例

注目していただきたいのは地図部分ではなくマンホール画像部分です。画像が色の付いた枠(上は青枠、下は赤枠)で囲われていることにお気づきでしょうか?
これ、実は画像全体の色味を表しています。つまり上の画像は「全体的に青っぽい」、下の画像は「全体的に赤っぽい」ことを自動判断して表示しているのです。なんとなく合ってます(よね)。実際のアプリケーションでは赤、青、緑、黄、紫、そしてマジェンタの6種類のいずれかと判断しています。
これをどうやって実現しているか、というのが今回のネタです。
マンホールマップは Java で開発していて、特にこの部分は Java の拡張クラスである ImageIO (javax.imageio.ImageIO)を使っています。具体的にはこのようなコードです:
:
public String GetImageColor( byte[] img ){
String r = null;
:
if( img != null ){
BufferedImage image = null;
try{
InputStream is = new ByteArrayInputStream( img );
image = ImageIO.read( is );
}catch( IOException e ){
}
if( image != null ){
//. 画像の大きさをチェック
int w = image.getWidth();
int h = image.getHeight();
//. 1ピクセルずつ色を取り出す
for( int x = 0; x < w; x ++ ){
for( int y = 0; y < h; y ++ ){
//. 特定ピクセルの RGB 情報を取り出す
int rgb = image.getRGB( x, y );
:
}
}
}else{
}
}
return r;
}
:
この例では画像バイナリのバイト配列( byte[] img )を引数として受け取る GetImageColor() 関数を定義しています。その中でまず ImageIO.read を使って、画像の BufferedImage を取り出します。
正しく取り出すことができたら、画像の幅と高さをピクセル単位で取得し、2重の for ループ内で1ピクセルずつ BufferedImage.getRGB 関数を実行し、RGB 値を取り出す、という処理を実行しています。これで1ピクセル毎の RGB 値を取り出すことができます。
あとはこの結果から、赤、青、緑、黄、紫、そしてマジェンタのどの色が多く使われているか、、、を調べるわけですが、そのあたりの細かなアルゴリズムは秘密(というか面倒なので省略)、ということで(苦笑)。
ちなみに白と黒が含まれていない理由は「マンホールの色が黒(または白)」というのは「普通過ぎてつまらないから、黒と白を除いて近い色を探す」という工夫をしているからでした。
この方法を応用することで、色んな画像の色情報(RGB値)を1ピクセル毎に取り出して判断することができるようになります。
