※Ubuntuは12.04系です
はい。今日もゲーム実況動画をBGMにしてコーディングしてます。ゲーム実況をしているマミルトン、もうみなさんご存知ですよね?この↓の右側の女性です。
まだ、ご存知ない方は下の動画をどうぞ。これは、ステマじゃないよ!
マミルトンのゲーム実況動画:【パズドラ】聖の龍騎姫【同キャラ禁止】 地獄級にマミルトンと挑む!
ゲーム実況動画をうまいこと分類したりできないか試行錯誤してきます。使用環境は Ubuntu (12.04) とRubyがメインで、shellスクリプトも使います。画像APIを提供するRekognitionですが、月に5,000くおーたしか使えないので、一部OpenCV使う予定です。
ffmpeg を使ってフレーム画像の抜出し
YouTube 動画のダウンロード
youtube-dl を使って、動画をダウンロードします。顔が大きめに映っているものを使いたいので、今回は↓の動画を使わせてもらいます。※ステマじゃないって!でもこの動画、おいしそーです。
youtube-dl コマンドライン
youtube-dl はそのままだとダウンロードしたファイル名に動画タイトルが含まれます。それはいやなので、videoId だけになるようにオプション渡します。
$ youtube-dl -f 22/17 -o "%(id)s.%(ext)s" https://www.youtube.com/watch?v=NNpOTng4b40
これで、NNpOTng4b40.mp4 というファイルがダウンロードされます。
フレーム画像の抜出 ffmpeg 使うよ
ダウンロードした動画からフレームの画像を抜き出します。全部は多いので、とりあえず1秒毎に1枚、最初の60秒ぐらい抜き出しましょう。シェル書きます。
#! /bin/bash
for i in `seq 1 1 60`
do
echo "$i"
#ls $1 -al
ffmpeg -y -i $1 -vframes 1 -ss $i -r 1 -f image2 $i.jpg
done
exit 0
シェルは苦手です。もっと良い書き方があったら教えてください。
これで、 1.jpg から 60.jpg までの画像ができていると思います。
4.jpg
10.jpg
ffmpeg のコマンドライン引数の順番でエラー?
以前より厳密になったのでしょうか?ほかサイトでは
ffmpeg -vframes 1 -i hoge.mp4 -ss 1 -r 1 -f image2 1.jpg
みたいに書いていたのも、-vframesの位置が悪いとおこられました。こんな感じ:
Option vframes (set the number of video frames to record) cannot be applied to an input option to an output file or vice versa. Move this option before the fi
Error parsing options for input file NNpOTng4b40.mp4.
せっかくなので RMagick 使って mosaic
# -*- coding: utf-8 -*-
require 'test/unit'
# RMagick
require 'rubygems'
require 'RMagick'
# http://www.imagemagick.org/ImageMagick-7.0.0/RMagick/doc/mosaic.rb.html
class TC_Foo < Test::Unit::TestCase
def setup
puts "setup"
end
def test_rmagick_mosaic
puts "open_images"
imageUrls = ["1.jpg",
"2.jpg",
"3.jpg",
"4.jpg",
"5.jpg",
"6.jpg",
"7.jpg",
"8.jpg",
"9.jpg"
]
images = Magick::ImageList.new(*imageUrls)
b = Magick::ImageList.new
page = Magick::Rectangle.new(0,0,0,0)
images.scene = 0
3.times do |i|
3.times do |j|
b << images.scale(0.57)
page.x = j * b.columns
page.y = i * b.rows
b.page = page
(images.scene += 1) rescue images.scene = 0
end
end
image = b.mosaic
image.write("mamiruton2.jpg")
end
end
test/unit を使っているのは、問題があったときのデバッグのためです。
Rekognition のAPIを使ってみる
とりあえずためしに 4.jpg を使ってみます
大きめの顔になっている 4.jpg を使います。
rekognize の gem を入れる
$ sudo gem install rekognize
APIを呼んでみる
class TC_Foo < Test::Unit::TestCase
def setup
@client = Rekognize::Client::Base.new(api_key: YOUR_API_KEY, api_secret: YOUR_API_SECRET)
end
def test_open_remote_image
response = @client.face_detect(urls: "http://gameranking.scleen.com/images/mamiruton/4.jpg", jobs: 'face_part_aggresive_emotion_age_beauty')
puts response
end
end
※test/unit 使っているのはデバッグしやすいからです・・・
※face_detect はパラメーター base64 をサポートして無いのかな・・・
APIの結果
レスポンス:
項目 | 数値 |
---|---|
happy | 0.98 |
sad | 0.03 |
disgust | 0.01 |
age | 17.07 |
smile | 0.97 |
beauty | 0.54331 |
とこんな感じのデータが得られます。happy と smile で数字が取れているのでこの数字を使ってみましょう。
顔の位置の確認
顔の位置も正しく認識できました。
このRectangleはRMagick使って描きました。
class TC_Foo < Test::Unit::TestCase
def setup
@client = Rekognize::Client::Base.new(api_key: YOUR_API_KEY, api_secret: YOUR_API_SECRET)
end
def test_open_remote_image
response = @client.face_detect(urls: "http://gameranking.scleen.com/images/mamiruton/4.jpg", jobs: 'face_part_aggresive_emotion_age_beauty')
puts response
# draw rectangles
image = Magick::Image.read("http://gameranking.scleen.com/images/mamiruton/4.jpg").first
response['face_detection'].each do |face|
x = face['boundingbox']['tl']['x']
y = face['boundingbox']['tl']['y']
w = face['boundingbox']['size']['width']
h = face['boundingbox']['size']['height']
puts "#{x},#{y} #{w},#{h}"
gc = Magick::Draw.new
gc.stroke = 'red'
gc.fill = 'transparent'
gc.rectangle x, y, (w+x), (y+h)
gc.draw(image)
end
image.write "result.jpg"
end
end
ミカルタンが一緒のフレームでもうまく顔が認識できます。Rekognition のAPIは beauty という超主観的な結果を戻してくれますが、とりあえず使わないでおきます。smile happy 程度がまぁいいんじゃないでしょうか。
えがおとHAPPY度合でスコアリング
Rekognition のAPIを使って開始1分間のえがおとHAPPY度合 をスコアリングして上位の画像を探してみた。
**これはなかなかやるのではないか?**マミルトンの笑顔をお楽しみいただけましたでしょーか?
いろいろ
Rekognition の制限事項
- 画像サイズは縦横800pxまで、それを超える場合は内部的に縮小してから処理してるらしい。
- 無料5,000回/月は少ないなー
検討すること
- Rekognitionが800pxまでなので、YouTubeからのダウンロードする動画サイズを小さくした方がいろいろ良さそう。処理が速くなるしディスクサイズの節約にもなる。
- ffmpeg のフレーム画像の切り出しに時間かかるので短縮する方法を考える。全部出してから削除したほうが速い感じだ。