« 今日の畑
ジャガイモ掘りとネギの植え替え
| トップページ | 顔認識プログラム 2 »

2010.07.11

顔認識プログラム

ちょっと腰が重いのだけれど、顔認識プログラムが作りたくて、一から少しずつ作っています。
やってくうちにC++に便利なAPIがあるという噂を知り、それをJavaから使おうかと思いましたが、ちょっと我慢しています。ロジックを自分で考える努力は後々に繋がりそうだもの。
ということで、現段階での考え方をコードと共にメモしておこうと思います。


はじめに作ったプログラムがこれです。

processingとゴミが混ざっていますが気にしない。うん。
内容は肌色検出です。正直肌色検出で顔認識するのは無理だと思っています。なぜかというと環境光の違いでとたんに検出できなくなるから。コードの最後で実験結果を貼付けたいと思います。
苦労した点はprocessingのcolor指定ですね、colorがただのintだというのがよく分からず、ずいぶん時間を費やしました。(今でもよく分かっていない)
本当に最初の頃はcolorModeをRGBでやってたので、検出がうまくいかず、HSBにして、赤系を指定してやれば!と思うが前述のcolor値で、数字がどの色を示しているのか分からなかった。この問題は10進数を16進数に変換して、先頭の"ff"(アルファ)を取り去ることで解決することができました。


package test;


//import processing
//import processing.core.*;
import processing.core.PApplet;
import processing.core.PImage;
import java.awt.Color;



public class FaceCatch extends PApplet{

        private static final long serialVersionUID = 1L;

        //コンストラクタ
        public FaceCatch(){

        }

        //イメージの読み込み
        PImage mapImage;

        //イメージのピクセルの個数
        int pixcelOll;
        //イメージの縦横ピクセル
        int pixcelHieght, pixcelWidth;
        //イメージのピクセル値 RGB
        int celColorR, celColorG, celColorB;
        //イメージのピクセル値 HSB
        int celColorH, celColorS, celColorHB;

        //肌色定数上位下位
        final String SKINOVER = "FFE1D5";
        final String SKINUNDER = "DE9D7F";

        //肌色特定閾値
        final int THRASHOLD = Integer.decode("0x220000").intValue();


        public void setup(){

                //画面サイズ
                size(200, 200, JAVA2D);

                //colorモード
                colorMode(HSB, 255);

                //イメージの読み込み
                mapImage = loadImage("画像のある場所");

                //ピクセルの縦数
                pixcelHieght = mapImage.height;
                //ピクセルの横数
                pixcelWidth = mapImage.width;

                //肌色定数を10進数のRGBごとに分解
                int skinColor[] = {

                        rgb(SKINOVER, 1),
                        rgb(SKINOVER, 2),
                        rgb(SKINOVER, 3),
                        rgb(SKINUNDER, 1),
                        rgb(SKINUNDER, 2),
                        rgb(SKINUNDER, 3),

                };

                //イメージの中に肌色が無いか調べる
                for(int i = 0; i < pixcelHieght; i++){
                        for(int j = 0; j < pixcelWidth; j++){


                                //ここで画像から取得されるピクセルの値はgetメソッドにより必ずRGBとなってしまう。これをHSBに変換してやる必要がある。



                                //取得されるRGBの調査

                                //イメージからピクセルのRGBを取得
                                int pixcelRGB = mapImage.get(j, i);


                                //System.out.println("取得したRGBの値を10進数の整数で表示_" + pixcelRGB);

                                //頭の2桁を取る
                                StringBuffer s = new StringBuffer(Integer.toString(pixcelRGB));
                                //-のみを取り去る
                                s.delete(0, 1);
                                //System.out.println("10進数_" + s);
                                //System.out.println("16進数に変換_" + Integer.toHexString(Integer.parseInt(s.toString())));

                                StringBuffer ss = new StringBuffer(Integer.toHexString(pixcelRGB));
                                ss.delete(0, 2);
                                //System.out.println("16進数_" + ss);


                                //RGBをHSBに変換
                                float pixcelHSB[] = Color.RGBtoHSB(rgb(ss.toString(), 1), rgb(ss.toString(), 2), rgb(ss.toString(), 3), null);

                                //テスト表示
                                //System.out.println("色相Hは、" + pixcelHSB[0]);
                                //System.out.println("彩度Sは、" + pixcelHSB[1]);
                                //System.out.println("明るさBは、" + pixcelHSB[2]);

                                //RGB、HSB変換の戻り値floatをレンジ255の整数にマッピング

                                //色相を255にマップ
                                int hsbH = (int) (255 * pixcelHSB[0]);
                                //彩度を255にマップ
                                int hsbS = (int) (255 * pixcelHSB[1]);
                                //明るさを255にマップ
                                int hsbB = (int) (255 * pixcelHSB[2]);

                                //System.out.println("H_" + hsbH + " S_" + hsbS + " B_" + hsbB);



                                if(hsbH > 5 && hsbH < 30 && hsbS > 50 && hsbB > 170 && hsbB < 250){
                                        //System.out.println("該当のデータが見つかりました");
                                        mapImage.set(j, i, 255);
                                }




                                /*
                                //取得した値を16進数に変換し、先頭の2文字FFを削除する
                                StringBuffer s = new StringBuffer(Integer.toHexString(mapImage.get(j, i)));
                                //頭のアルファを取る
                                s.delete(0, 2);

                                //H、色相に分離
                                celColorH = rgb(s.toString(), 1);
                                System.out.println("色相値は、" + celColorH);
                                //肌色判定HSB版色相だけを判断材料に使う
                                if(celColorH > 25 && celColorH < 76){
                                System.out.println("該&#24403;のデ&#12540;タが見つかりました");
                                mapImage.set(j, i, 255);

                        }*/




                                /*
                                //入手したピクセルをRGBに3分割する

                                //R、赤に分離
                                celColorR = rgb(s.toString(), 1);
                                //G、緑に分解
                                celColorG = rgb(s.toString(), 2);
                                //B、青に分解
                                celColorB = rgb(s.toString(), 3);
                                //肌色判定RGB版
                                if(celColorR < skinColor[0] && celColorR > skinColor[3] && celColorG < skinColor[1] && celColorG > skinColor[4] && celColorB < skinColor[2] && celColorB > skinColor[4]){
                                mapImage.set(j, i, 255);
                                //rect(j, i, 5, 5);
                        }*/
                        }
                }
        }

        public void draw(){

                //背景画像指定
                image(mapImage, 0, 0);


                //HSB表示のテスト
                //fill(25, 96, 237);
                //rect(width / 2 - 10, height / 2 - 10, 20, 20);

        }

        //RGBを分解するメソッド
        public int rgb(String rgb, int num){
                int rgbNum = 0;
                StringBuffer s = new StringBuffer(rgb);

                switch(num){
                        case 1:
                        //赤の処理
                        s.delete(2, 6);
                        break;
                        case 2:
                        //緑の処理
                        s.delete(0, 2);
                        s.delete(2, 4);
                        break;
                        case 3:
                        //青の処理
                        s.delete(0, 4);
                        break;
                }

                //16進数を10進数に変換する
                rgbNum = Integer.decode("0x" + s.toString()).intValue();
                return rgbNum;
        }






        //HSBを分解するメソッド
        public int hsb(String hsb, int num){
                int hsbNum = 0;
                StringBuffer s = new StringBuffer(hsb);

                switch(num){
                        case 1:
                        //色相の処理
                        break;
                        case 2:
                        //彩度の処理
                        break;
                        case 3:
                        //明るさの処理
                        break;
                }

                return hsbNum;
        }

}



《実験結果》

Fc001_2

Fc002_2

Fc003_2


ご覧の通り、全体的に暗くなったりすると前もって指定した肌色の定数に引っかからない。
これじゃだめだね。


統計的パターン認識入門統計的パターン認識入門
価格 : ¥2,940 (税込み)

本書は、統計的パターン認識の識別系と特徴抽出系の理論とその基本的考え方を丁寧に解説した入門書である。また、より実用的な観点から具体的な図表や計算機演習を用意して理解が深まるように工夫したテキストでもある。

|

« 今日の畑
ジャガイモ掘りとネギの植え替え
| トップページ | 顔認識プログラム 2 »

processing」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/198455/48851117

この記事へのトラックバック一覧です: 顔認識プログラム:

« 今日の畑
ジャガイモ掘りとネギの植え替え
| トップページ | 顔認識プログラム 2 »