Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

誰でも手軽にNTTドコモのサービスのような機能を持つアプリが作れる ~顔検出APIでモザイクカメラを作ろう

スマホアプリを豊かにする「docomo Developer support」で遊ぼう(3)

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2015/02/04 14:00
目次

モザイクカメラを作ろう(2)

顔情報を抽出する

 Android Asynchronous Http Clientを使うと、レスポンスデータは、Android SDK標準のJSONObjectに変換されます。今回は、FaceCoordinatesというクラスで、そのJSONObjectから顔の位置データ(左上のXY座標、幅、高さ)をArrayListデータとして抽出しています。

リスト6 FaceCoordinates.javaの一部
public class FaceCoordinates {

    // 顔の位置データ
    public class faceCoordinate {
        int left; int top;          // 左上の座標
        int width; int height;      // 幅と高さ
    }

    // 顔検出結果のJSON文字列から、顔の位置データを抽出する
    public List<faceCoordinate> extract(JSONObject response) {

        List<faceCoordinate> faces = new ArrayList<faceCoordinate>();

        try {
            JSONArray detectionFaceInfo =
                response.getJSONObject("results")
                    .getJSONObject("faceRecognition")
                        .getJSONArray("detectionFaceInfo");

            for (int i = 0; i < detectionFaceInfo.length(); i++) {
                JSONObject faceCoordinates =
                    detectionFaceInfo.getJSONObject(i)
                        .getJSONObject("faceCoordinates");

                faceCoordinate face = new faceCoordinate();
                face.left = faceCoordinates.getInt("faceFrameLeftX");
                face.top = faceCoordinates.getInt("faceFrameTopY");
                face.width = faceCoordinates.getInt("faceFrameRightX")
                                 - faceCoordinates.getInt("faceFrameLeftX");
                face.height = faceCoordinates.getInt("faceFrameBottomY")
                                 - faceCoordinates.getInt("faceFrameTopY");
                faces.add(face);
            }
        }
        catch (JSONException e) {
        }
        return faces;
    }
}

モザイク処理行う

 モザイク処理は、MainActivityクラスのsaveMosaicメソッドとして実装しています。

 モザイク処理を行うために、コールバックメソッドに渡されたJPEG形式の画像データを、1ピクセル32ビット(αチャネル、RGB、各8ビット)のビットマップデータに変換します(1)

 そしてモザイク処理(2)を追加してから、再度JPEG形式で保存し(3)、画像ギャラリーに反映させるために、AndroidのDBに登録します(4)

リスト7 MainActivity.javaの一部
// 画像データに、顔情報を利用してモザイク処理を行い、JPEG形式で保存する
private void saveMosaic(byte[] data, JSONObject response) {

    // バイト配列をビットマップデータに変換する
    Bitmap original = BitmapFactory.decodeByteArray(data, 0, data.length);

    // ビットマップデータを、
    // 32ビットのARGB(alpha, red, green, blue)データに変換する(1)
    Bitmap b = original.copy(Bitmap.Config.ARGB_8888, true);

    // 顔情報を利用してモザイク処理を行う(2)
    FaceCoordinates fs = new FaceCoordinates();
    for (FaceCoordinates.faceCoordinate f : fs.extract(response)) {
        b = mosaic(b, f.left, f.top, f.width, f.height);
    }

    // 保存する画像ファイル名を設定する
    long now = System.currentTimeMillis();
    File mediaFile = new File(
        Environment.getExternalStoragePublicDirectory(
                                    Environment.DIRECTORY_DCIM), now + ".jpg");
    try {
        FileOutputStream fos = new FileOutputStream(mediaFile, true);
        // JPEG形式で保存する(3)
        b.compress(CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    }
    catch (IOException e) {
    }

    // 画像ファイルを登録(4)
    ContentValues values = new ContentValues();
    ContentResolver contentResolver = getContentResolver();
    values.put(Images.Media.MIME_TYPE, "image/jpeg");
    values.put("_data", mediaFile.getAbsolutePath());   // フルパス
    values.put(Images.Media.DATE_TAKEN, now);           // 撮影日時
    contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);
}

モザイクアルゴリズム

 モザイク処理のアルゴリズムは、比較的単純で、画像を一定のサイズの矩形領域で区切り、その矩形全体を、領域内の色の平均値で塗りつぶします。ここでは、8ピクセル四方の矩形としています。

リスト8 MainActivity.javaの一部
// 指定した範囲をモザイク処理する
private Bitmap mosaic(Bitmap bitmap, int left, int top, int width, int height) {
    int dot = 8;
    int square = dot * dot;

    for (int x = 0; x < width / dot; x++) {
        for (int y = 0; y < height / dot; y++) {
            int r = 0, g = 0, b = 0;
            for (int w = 0; w < dot; w++) {
                for (int h = 0; h < dot; h++) {
                    int dotColor =
                        bitmap.getPixel(left + x * dot + w, top + y * dot + h);
                    r += Color.red(dotColor);
                    g += Color.green(dotColor);
                    b += Color.blue(dotColor);
                }
            }
            r /= square; g /= square; b /= square;  // 色を平均する
            for (int dw = 0; dw < dot; dw++) {
                for (int dh = 0; dh < dot; dh++) {
                    bitmap.setPixel(left + x * dot + dw, top + y * dot + dh,
                        Color.rgb(r, g, b));
                }
            }
        }
    }
    return bitmap;
}

 モザイク処理については本稿の範疇を越えますので、ここでは割愛します。詳しくは『Androidでモザイク画像を作ってみる』などを参考にしてください。

最後に

 今回は、PUX社の技術を用いた顔・オブジェクト認識APIの紹介と、顔検出APIを用いたモザイクカメラを作ってみました。顔検出APIでは、顔の位置だけでなく、年齢や、どや顔判定などもありますので、ゲームやジョークアプリにおもしろく応用できそうです。

 次回も、APIを利用して、楽しいAndroidアプリを作ってみます。



  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト 高江 賢(タカエ ケン)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

バックナンバー

連載:スマホアプリを豊かにする「docomo Developer support」で遊ぼう
All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5