モザイクカメラを作ろう(2)
顔情報を抽出する
Android Asynchronous Http Clientを使うと、レスポンスデータは、Android SDK標準のJSONObjectに変換されます。今回は、FaceCoordinatesというクラスで、そのJSONObjectから顔の位置データ(左上のXY座標、幅、高さ)をArrayListデータとして抽出しています。
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)。
// 画像データに、顔情報を利用してモザイク処理を行い、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ピクセル四方の矩形としています。
// 指定した範囲をモザイク処理する 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アプリを作ってみます。