なるように、なる

徒然なつぶやき、備忘録です。

ofxFaceTrackerハマリ記録

FaceTrackerは画像から顔を検出し、顔のパーツ(特徴点)の座標を取得できるライブラリです。C++OpenCVで実装されていますが、Pythonのラッパーもあるようです。

今回私はopenFrameworksのアドオンとして提供されているofxFaceTrackerを利用しました。毎度のことですが、利用するまでにいくつか(いくつも?)ハマったので、記録として残しておきます。

 

開発環境
  • Windows10
  • VisualStudio2015
  • openFramewowks (nightly builds)
ハマり1 インストールするものたちのバージョン

openFrameworksの安定バージョンが0.9.8から0.10.0に移行しようとしている真只中の現在、ofxFaceTrackerとofxCvをgithubのmasterからそれぞれ落としてくると、ビルドエラーになります。これらのmasterは0.10.0向けとなっているためです。
もし、openFrameworksを0.9.8のstable版で使用している場合、ofxFaceTrackerとofxCvは、masterではなくstableブランチから落としてくる必要があります。


ハマり2.1 プロジェクト設定(ofxCvの追加のインクルードパス)

新規プロジェクトを作成してofxCvを利用しようとすると、追加のインクルードパスが以下のように設定されていました。このままだとインクルードファイルが見つからないので、それぞれフルパスに修正する必要があります。

  • libs/ofxCv/include
  • libs/CLD/include/CLD
  • src

 

ハマり2.2 プロジェクト設定(追加の依存ファイル)

つづいて追加の依存ファイルを見ると、依存ファイルの行頭に「%3b」という文字が付与されていました。このままだとリンクエラーになるので、「%3b」を削除します。

 

ハマり2.3 プロジェクト設定(出力ファイル/オブジェクトファイル)

ここまで実施しても、まだリンクエラーが出ます。ぐぬぅ。
最後はエラーメッセージをググってみたら、こちらの記事にあたりました。
出力ファイル名を「$(IntDir)」から「$(IntDir)/%(RelativeDir)」に変更しました。

 

ここまでで、無事にofxFaceTrackerをビルド出来るようになってるはずです。
もしまだ別のエラーに困っているようであれば、それは新規の案件かもしれないので、解決したらぜひ周知してください♪

 

おまけ

f:id:Shampagne:20180502001200p:plain

多摩美の田所先生が公開しているサンプルを使わせて頂いて、歌舞伎Faceをやりました。かなりしっかり顔にフィットしてますね。

mastodonインスタンスを立てた(@さくらVPS)

mastodonが流行り出してからほぼ1年が経ちました。僕自身は2017年のニコニコ超会議に相撲と歌舞伎を観にいった際にfriends.nicoに登録してからズブズブです。

mastodonとは


 

建てたインスタンス(mastodosukoi)

 

はじめてのことだらけで、稽古つけてもらった感じです。いい勉強になりました。
ごっつぁんです。

C++にPythonを組み込むメモ(Boost.python)

C++からPythonを呼びたいのです。
逆に比べると大分ニーズが少ない。
以下を参考にさせて頂きました。
Embedded Python in C++ / C++からPythonスクリプトを呼び出す - Qiita
Boost.PythonでC++からPythonの関数を呼び出す
C++からPythonを叩きつつ、boost.numpyを使ってC++とPython間でndarrayをやりとりする - verilog書く人

初期化
Py_Initialize();
auto main_mod = boost::python::::import("__main__");
auto main_ns = main_mod.attr("__dict__");
スクリプトの読み込み
std::string script((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
boost::python::::exec(script.c_str(), main_ns);
関数の実行
auto func = main_ns["func"];
auto result = func(1.0);
Pythonからの値のパース
boost::python::::extract<double>(result)
例外処理
try {
//
} catch (boost::python::error_already_set) {
    PyErr_Print();
}
リスト/タプルで引数渡し
boost::python::list list_val;
list_val.append(1.0);
list_val.append(2.0);
auto result = main_mod.attr("func")(list_val);
タプルを受け取る
using input_iterator = boost::python::stl_input_iterator<double>;
input_iterator begin(result), end;

std::vector<double> vals(begin, end);
for (auto val : vals) {
    std::cout << val << std::endl;
}

Boost.python/Boost.numpyを使いたい

openFrameworksを使い始めました。
そうしたらC++からPythonを呼び出したくなってきた。
以下の記事を参考に、Boost.pythonをインストールしたのでその記録。

PythonからC++を呼び出してnumpyを使う - TadaoYamaokaの日記
Boost.PythonおよびBoost.NumpyをWindowsで使うまで | tatsyblog

環境
  • Windows10
  • VisualStudio2015
  • Python 3.5.3 (c:\python35)
  • Boost 1.66 (c:\boost_1_66_0)
Boostのインストール

TadaoYamaokaさんの記事の手順のとおり。完全に同じ。ビリーブ。

  1. ダウンロードしたBoostを解凍して適当に配置。
  2. Boost.pythonのビルドを有効にする。
  3. Boostをビルド。
C++からBoost.pythonを使う

今度はtatsyさんのコードを参考にした。

#include "stdafx.h"
#define BOOST_PYTHON_STATIC_LIB
#define BOOST_NUMPY_STATIC_LIB
#include <Python.h>
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>

namespace py = boost::python;
namespace np = boost::python::numpy;

int main()
{
    Py_Initialize();
    np::initialize();

    // Matrix A
    py::tuple shapeA = py::make_tuple(2, 2);
    np::ndarray A = np::zeros(shapeA, np::dtype::get_builtin<double>());
    A[0][0] = 1.0;
    A[0][1] = 2.0;
    A[1][0] = 3.0;
    A[1][1] = 4.0;

    // Vector b
    py::tuple shapeB = py::make_tuple(2);
    np::ndarray b = np::zeros(shapeB, np::dtype::get_builtin<double>());
    b[0] = 3.0;
    b[1] = 7.0;

    // Prepare numpy.linalg.solve
    py::object solve = py::import("numpy").attr("linalg").attr("solve");

    // Solve
    np::ndarray x = py::extract<np::ndarray>(solve(A, b));
    int dims = x.shape(0);
    for (int i = 0; i < dims; i++) {
        std::cout << py::extract<double>(x[i]) << std::endl;
    }

    return 0;
}

無事に動きました。
先輩ありがとうございます。

タブラの音を学習させた

タブラの演奏を視覚化させるために、タブラの音を識別させることにチャレンジしています。タブラは2つの太鼓から20種類ほどの音色をだすことが出来ますので、それをひとつひとつ識別して、演奏をリアルタイムにVJみたいにしたいと思ってます。

今回識別させた音

キールフセイン先生の曲を波形を見てみましょう。このピークになっているのが太鼓の音です。

f:id:Shampagne:20171111170959p:plain

今回はこの曲の中から4種類の音を切り出してみました。

「na」

f:id:Shampagne:20171111171723p:plain

「tun」

f:id:Shampagne:20171111171539p:plain

「te」

f:id:Shampagne:20171111171602p:plain

「ge」

f:id:Shampagne:20171111171615p:plain

波形を見てみると、それぞれ個性がありますね。なんとなくいけそうな気がしません?ちなみに、私はこの作業のために曲を聴きながらそれぞれの波形を30個ずつ切り出したので、波形を見て音を識別できるようになりましたw
同じことをプログラムにもやってもらおうと思います。

どうやって識別させるか?

色々と調べてみて、いちばんやりたいことに近かったのがこちらです。

webdatareport.hatenablog.com

あとは、「実践機械学習システム」の9章(音楽ジャンル分類)を参考にしました。

要点は音のデータをMFCC (メル周波数ケプストラム係数)に変換し、それを特徴量とするということです。はっきり言ってMFCCが何かはさっぱりですが、音声認識などではメジャーな手法ということです。先人の力に頼りまくりたいと思います。

識別させてみた

実は今回、大変だったのはここまでです。どうやるかを調べるのが大変でしたが、あとは凄く簡単(株式会社ルーター様!ありがと!)。

やったことは以下。

1.元の楽曲から学習用に太鼓の音を切り出す(4種類 x 30パターン)。
2.太鼓の音が入ってない部分をノイズデータとして切り出し、1.と混ぜてデータ水増し(soxという神ライブラリを利用)。
3.wavデータをMFCCに変換。
  ※scikits.talkboxなど、MFCCを計算するライブラリは色々ある。
4.3.で得た特徴量をCNNにかける。

結果

89%まで識別できるようになりました。おぉ。

 

 Epoch loss: 0.2590 - acc: 0.8841 - val_loss: 0.2423 - val_acc: 0.8900
Test loss: 0.242288478737
Test accuracy: 0.89

 

f:id:Shampagne:20171111180943p:plain

トライアルとしては十分な成果が得られました。
次回は学習したモデルを使って実際にザキール先生の曲を再生しながら太鼓の音をリアルタイムに識別してみたいと思います。

タブラの音を認識したいのだ

みなさん、タブラという楽器を知っていますか?

知らないですよね、そうですよね。

タブラはインドの古典楽器で、手の指で叩く2つの太鼓です。

名前は聞いたことないかも知れないけど、きっとみんな音は聞いたことあるはず。

シタールとセットで、インドっぽい音楽には必ず入っています。

僕はこのタブラが大好きなんです。

まずはこれ

キールフセイン大先生

世界最高のタブラプレイヤーです。間違いないです。

www.youtube.com

あと、よく知らないんだけど、楽しくタブラを叩いてる人たちw

www.youtube.com

 

タブラとは?

matome.naver.jp

ここで説明されているように、世界一難しい楽器と言われています。

実際、何年か前にどうしても自分で演奏してみたくて、先生に習ってみたんですが、これはちょっと無理かな、、って感じになっちゃいました。

しかし、それでもタブラの魅力は僕を惹きつけ続けています。

なんでタブラの音を認識させたいか?

昨年、渋谷WWWX(というライブハウス)の杮落し公演にザキール先生が来まして、幸運なことにチケットとれたので観にいったのです。

それはそれはどえらい演奏だったのです。

もう何が起きてるか分からないけど、とにかくすごい。

逆に言うと、凄すぎてワケが分からなかったのです。

それで、時間がたつにつれて、こう思うようになったのです。

「タブラの魅力をもっと分かり易くすることはできないか?」

そして、最近vvvvや機械学習を勉強しているなかで、タブラの音を視覚化してみたいと思うようになりました。

 

次回から、タブラの視覚化チャレンジの道のりを書いていきます。