モザイクカメラを作ろう(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アプリを作ってみます。

