ニートがプログラミングするブログ(はてな出張所)

ニートがプログラミングするブログです。今は主にコンピュータビジョンに関することをやっています。

ボイスチェンジャー1

統計的声質変換 (1) ロードマップ を参考にしつつボイスチェンジャーを作っていました。
先に結果を載せておきます。
データはsoftalkの女性01と男性(m4b)を使いました。
トレーニングデータは外郎売でテストデータは平家物語の冒頭です。
ただ音声の分解コマンドのオプションが良く分からなかったので、合成した結果が元の音声と違って聞こえます。
ソース(変換前の声)

ターゲット(正解の声)

変換結果(男の声を女の声に変換)


変換結果を正解データと比べるとまだまだ精度が低いですが、いろいろ試行錯誤した結果でこれなので、これ以上ボイスチェンジャーはやりたくない気分です。

トレーニングに使った外郎売は6分程度だったので、もう少しデータ数を増やせば精度が上がるかもしれません。
というか音声ファイルってaudioってタグで貼り付けられるんですね。


まだサウンドプログラミングを勉強し始めて1週間くらいなのでよく分かりませんが一応解説を書いておきます。
wavファイルはパワー・メルケプストラムとピッチに分けられるようです。
パワーは振幅なので(?)たぶん声の大きさを表します。
メルケプストラムは話している内容と声質を表します。低周波数部分が話してる内容で、高周波数部分が声質らしいです。
ピッチは声の高さです。
なので、メルケプストラムとピッチを変換すればボイスチェンジャーが出来ます。
(パワーは声の大きさなので変換しませんでした。)
上のサイトではピッチを変換していませんが、リアルタイムトーキングアバターの実現に向けたキャラクタ依存声質変換の研究ではピッチも変換しているので、僕も変換してみました。


方法:
1.上のサイトを参考にして、pythonとSPTKを使えるようにします。
2.上のサイトを参考にして、wavファイルからmcepファイルとpitchファイルを作ります。
3.上のサイトを参考にして、ソースとターゲットの音の位置あわせをします。
4.ピッチを変換する方法は、単純な行列による変換です。
[pitch_1 pitch pitch1 1]という縦4次元ベクトルを横方向につなぎ合わせます。
ここでpitch_1は1フレーム(?)前の値、pitchは現在の値、pitch1は次の値を指します。
そしてターゲットの行列にソースの行列の擬似逆行列を掛けると、変換行列が出来るのでこれを保存しておき、テストデータに掛けます。
5.メルケプストラムを変換する方法は、入力層→隠れ層(ニューロン数は100)→出力層の2層構造ニューラルネットワークを使います。
SPTKのmcepコマンドは0次元目にパワー(たぶん振幅の大きさ?)が入ってきますが、これは変換せずそのまま使うので学習時には除外します。
そしてソースのメルケプストラムを入れると、ターゲットのメルケプストラムが出てくるようにトレーニングします。
テスト時にはメルケプストラムをこのニューラルネットワークにいれ、除外しておいたパワーを先頭に付け加えて出力します。
6.上のサイトを参考にして、パワー・メルケプストラムとピッチを合成してwavファイルを作り完成です。

ディープラーニングを使わない顔認識

最近は様々なところでディープラーニングが使われています。
ここで書く顔認識の分野でも主流となっています。
しかし、この記事ではあえてそれを使わない方法を説明します。
というか単にディープラーニングがうまく扱えなくて、自己流で顔認識技術を改良して言っただけですが……。
ちなみにここでは、画像中から人の顔を見つけるのが顔”検出”、その顔が誰であるかを特定するのが顔”認識”ということにしておきます。

一昔前の顔認識ではeigen face、fisher faceやLBPなどが使われていました。
これらはOpenCVに実装されているので、簡単に利用することが出来ます。
しかし実際に試してみたところ、これらは精度があまり高くない気がしました。
他に良い方法がないか探していたら、ぱろすけさんがAV女優の顔認識に関する論文を書いていたのでそれを参考にしました。
ちなみに、この論文は既に削除されてるようです。
論文中ではHistogram of Oriented Gradients(HOG)特徴量を使っていました。
HOGはその性質上、人の”検出”にはよく利用されますが、顔の”認識”にはあまり利用されないという印象があります。
とはいえ試してみたらそこそこの精度が出たのでHOGを使っています。
そんなわけでHOGを使った顔認識について具体的に書いていこうと思います。

1.データの水増し data augmentation
識別器の精度を上げるためにデータ数を増やします。
僕の実装では左右反転と色調補正を行いました。
色調補正ではガンマ補正を使いました。

2.顔検出 face detection
次に画像中から顔の部分を切り取ります。
この切り取った小さな画像のことをパッチといいます。
顔検出ではOpenCVが良く利用されていますが、ここではより精度の高いdlibの顔検出を利用しています。
検出される領域は少し小さいので、僕の実装では各辺を1.3倍くらいにしています。

3.顔の特徴点検出 landmark detection
次に顔の特徴点を検出します。
特徴点とは目尻や目頭、口の端などの部分です。
OpenCVには特徴点検出機能がないので、dlibのものを使うか、detectFace();を使うのが楽だと思います。
僕は自分で実装しましたが、面倒なので上のものを使うのが良いかと。

4.顔の位置合わせ face alignment
どれでもいいのですが1枚基準となる顔画像を選んでおきます。
そして他の画像をこの画像に合うようにアフィン変換を適用します。
アフィン変換とは拡大縮小、回転、平行移動を行う変換のことをいいます。
変換で使うパラメータは、3番で求めた特徴点を用いて、procrustes analysisや参考文献[1]のAppendix Dの方法で求めます。
僕の実装では位置合わせが済んだら全画像のサイズを一辺が約200pxの正方形にしています。

5.特徴量の計算 HOG feature
それぞれの人がどんな顔をしているのかを数値的に表したものを特徴量といいます。
一般的にはLBPが用いられますが、経験的にHOGのほうが良かったのでそっちを使います。
HOGは比較的簡単に実装できますが、dlibのFHOG(HOGの改善版)を使うのが簡単だと思います。
僕の実装では、特徴点を中心とする一辺が60pxの正方形のパッチのHOGを求めています。
ただし、すべての特徴点で取ると制度が悪くなるので、5個置きに取っています。
僕の場合特徴点は合計で81個あるので、81/6=13箇所でHOGを取っています。
さらに画像を2倍に拡大して同様のことを行うので、合計26箇所でHOGを取っています。
ちなみにHOGのセルサイズは20px、ブロックサイズは2セルx2セル、ヒストグラムのサイズは12です。

6.次元圧縮 dimensionality reduction
5番で求めたHOGを全て連結(concatenate)して特徴量として使うのもありですが、次元圧縮をしたほうが精度が上がります。
僕の実装ではPCAを使い次元圧縮をしています。

7.識別器の作成 neural network
6番で求めた特徴量を全て連結してベクトルとして、ニューラルネットワークをトレーニングします。
ただし、特徴量をそのまま入れると学習がうまく進まないので、各次元ごとに値が平均0分散1となるように標準化します。
僕の実装では1つのニューラルネットワークで多クラス問題として扱わずに、人数分の二値問題用のニューラルネットワークを作りました。
ちなみに入力層と出力層だけの1層ニューラルネットワークを使っています。

8.テスト test
テスト時には1番から6番までの処理を行い、7番で作ったニューラルネットワークに入れます。
僕の実装では、データの水増しは左右反転と3段階のガンマ補正を行った計6枚の画像をテストして、その平均値を出力確率としています。

実際はもう少しこまごまとしたテクニックを使っていますが、せいぜい3%程度しか識別率が上がらないので省略します。
この手法の精度を測るために、sugyanさんのアイドルデータセットを使いました。
面倒なのでcase#5しか測っていませんが、正解率は96%でディープラーニングとほぼ同等の精度が出ています。

この方法を使いAV女優の検索サービスを作ったのでぜひお試し下さい。

それからこんな面倒な方法を使わずともAPIやライブラリを使えばもっと楽に顔認識ができます。
一例として以下の4つを挙げておきます。
Microsoft Face API
face++
OpenFace
OpenBR

参考文献
[1]Cootes, Tim, E. Baldock, and J. Graham. "An introduction to active shape models." Image processing and analysis (2000): 223-248.

はじめまして

はじめまして、suzuichiというものです。ニートです。

今はFC2ブログでブログをやっていますが、ブログやwebサービスへのアクセス数を増やそうと思いはてなブログにもブログを開設しました。

(前にますだで宣伝記事を書いたら少し叩かれたので、普通のブログで宣伝しようと考えました。)

興味のある分野は機械学習で、今はAV女優の顔画像検索サービスを作っています。

これが終わったら、競馬の予想をする人工知能を作ってみたいです。

 

基本的にFC2ブログと同じことを書くので、はてなブログでもFC2ブログでも好きなほうを読んでいただければ良いです。

 

あまり専門的なことは知識が無いので書けませんが、どうぞよろしくお願いします。