OpenCV の物体認識を動画に適用する
4/8追記:拡張モジュールのダウンロードリンクは一番下にあります。
今回は自動的に顔にボカシを入れるスクリプトを書いてみました。しかし、対象となるのは静止画ではなく、動画です。ソフト・オン・デマンドの開発したという全自動デジタルモザイク処理システムデジエモンにインスパイアされました。
動画の場合、もっと効率良く精度も高く処理する方法はあるのですが…今回まだ OpenCV のAPIを拡張モジュール側でラップしきれていないので、フレームごとに (一から) 認識を走らせるというベタな方法に終始してしまっています。真似しないでください。
<?php $FILE = 'Beyonceatthe2007Osca.avi'; // First detect the maximum frame size $cap = cv_capture_from_file($FILE); $width = 0; $height = 0; $fps = 0; $fourcc = false; while (cv_capture_query_frame($cap)) { $fps = max($fps, cv_capture_get_property($cap, CV_CAP_PROP_FPS)); $width = max($width, cv_capture_get_property($cap, CV_CAP_PROP_FRAME_WIDTH)); $height = max($height, cv_capture_get_property($cap, CV_CAP_PROP_FRAME_HEIGHT)); } $cap = cv_capture_from_file($FILE); $vw = cv_video_writer_create("out.avi", 0, $fps, $width, $height, true); $haar = cv_object_load('haarcascade_frontalface_alt2.xml'); $rects = array(); while ($im = cv_capture_query_frame($cap)) { $seq = cv_haar_classifier_cascade_detect_objects($haar, $im); if (cv_rect_seq_count($seq)) { $rects = array(); for ($i = 0, $l = cv_rect_seq_count($seq); $i < $l; $i++) { $rect = cv_rect_seq_get($seq, $i); $rect['w'] -= $rect['w'] % 2; $rect['h'] -= $rect['h'] % 2; $rects[] = $rect; } } foreach ($rects as $rect) { $im2 = cv_image_create( $rect['w'] / 2, $rect['h'] / 2, cv_image_get_depth($im), cv_image_get_num_channels($im)); $im3 = cv_array_get_sub_rect($im, $rect['x'], $rect['y'], $rect['w'], $rect['h']); for ($i = 0; $i < 20; $i++) { cv_array_pyr_down($im3, $im2); cv_array_pyr_up($im2, $im3); } } cv_video_writer_write_frame($vw, $im); } ?>
以下、ビヨンセのオスカーでのインタビュー映像に処理を行った例。出力された動画を Totem 経由でキャプチャしています。
まず、これ
顔じゃないものも勝手に顔と認識してしまってますね。
新しい拡張モジュールのダウンロードは以下から。
前のリリースにあったおかしなバグは大分潰したつもりです。