頭と尻尾はくれてやる!

iOSアプリなどの開発日記です


PythonのOpenCVでデータセット内の重複画像をチェックする

CreateMLで人の顔を見分けたい
↑この続き。
機械学習(CreateML)で顔を見分けるために”良質な”データセットを作成しようと試みている。

画像検索で得た画像を使うとどうしても、これ持ってるよな?持ってたっけ?となってしまう。
なるべく避けようとするのだが、そうすると判断につかれるとかチェックに時間がかかってしまったりする。
そして実際どうしても重複してしまう。

なら重複覚悟でサクサク画像を得てから、後で重複をチェックすることにした。


(その1)顔の中にある目の相対位置で評価する

OpenCVで顔検出

↑PythonのOpenCVで顔や目の位置を得ることができる(※1)。
これを使って得た顔部分基準で目の相対位置なんかで評価すればいいんじゃね?というアイデアで実装を進めた。

ところがどうもよい結果がでない。調べてみたところ以下のようなことが原因だった。


サンプル画像1
サンプル画像2

↑例えばこの2枚の画像。単に1枚をクロップ(トリミング)したのがもう1枚の画像。この2枚の画像に対して顔の位置を検出した結果がこちら↓

OpenCVで顔検出結果1
OpenCVで顔検出結果2

同じ位置に顔を検出するものかと思っていたが微妙に違う。
そういうものなら仕方ない、とあきらめ別な方法を試してみた。



(その2)顔のランドマークを使う

OpenCVでランドマーク検出1

↑顔の輪郭や目の位置などを細かく取得できるのを利用してみた(※2)。
これだと顔のいろんな位置の座標を取得できる。

OpenCVでランドマーク検出2

↑ある点からある点へのベクトルを作成して、x軸との傾き(単位ベクトルにして内積から)などを評価、比較すればいいのでは?という考えで実装してみた。

類似画像検出結果1

↑これだと使えそうな程度にはなり、サクサクと重複している可能性のある画像を表示することができるようになった。

類似画像検出結果2

↑単に向きを数値化しているようなものなので似たような角度で撮影された画像は全く違っていても似ている、と判断するので完全自動化まではいかないが、自分の用途にはOKだ。



※1 参考サイト
Python, OpenCVで顔検出と瞳検出(顔認識、瞳認識) | note.nkmk.me

※2 参考サイト
顔のランドマークを検出 Python + OpenCV + dlib を使う | 404 Motivation Not Found
スポンサーサイト






コードの表示方法を変更

このブログ内のコード部分にはずっとsyntaxhihglighterを使ってたんだけど、正しく表示されなくなってるので最新バージョンにしようとした。

syntaxhighlighter/syntaxhighlighter: SyntaxHighlighter is a fully functional self-contained code syntax highlighter developed in JavaScript.
↑こちらが現時点で最新のversion4。

いろいろ調べたんだが、、、挫折した。
Failed to load external module @babel/register
ってエラーがどうしても発生する。

じゃあもういいや、と、単純にCSSで背景色だけ変えておくことにした。

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}

↑こんな感じ。

<pre class=“mycode”>
// code
</pre>
↑codeタグではさむだけ。


CSSのクラスが反映されない

久しぶりにスタイルシート(CSS)をいじろうとしたらはまった。
どういうわけかCSSファイルの内容が反映されないのがある。意図通りに表示されるのもある。
なのでCSSファイルへのリンク切れなどではない。

.example {
color: red;
}
↑クラスで適用させるこのような記述があるとする。


<p class=”example”>text</p>
↑これがどういうわけか適用されないんだ、、、???

無駄にいろいろと調査しつつ、ようやく判明。

<p class=”example”>text1</p>
<p class="example">text2</p>
↑二つ並べるとわかるだろうか?

そう、ダブルクォーテーションが全角になっていたのだ、、、orz

なのでクラスじゃなくタグで指定してたのは意図通り表示されていた。

Chromeによるソースのチェック画像

↑Chromeでソース表示させてチェックもしてたけど、この違いじゃ気付けないわ。全角なら全角らしくどーんと目立ってくれたり、文字(ここだと'example')をクリックしたら該当するCSSの記述部分の表示でもしてくれたらいいのに。

過去に自分が書いたCSSファイルから持ってきたのをコピペしただけだと思うのだが、OSかエディタの不具合なのだろうか?細かいことはわからないが、無駄に時間を使ってしまった。


CreateMLで人の顔を見分けたい

CreateMLで2種類の画像を見分けられなかった話
↑以前CreateMLで画像内にある文字列の有無を判断させようとしたけどうまくいかなかった、というのをやったが、、、
今回は人間の顔画像を与えて見分けることができるか試してみた。

顔写真を1人あたり学習用に40枚、テスト用に10枚用意した。
画像サイズは300 x 300px以上推奨だが横幅150px程度の小さいのも含む。
6人分のデータを用意し、maxIterations=30、オプションはCrop, Blur, Exposure, Noiseの4つ。学習時間は約31分で結果は、Evaluationが70%程度。
このデータ数、この処理時間でこの成績ならよしとすべきか?
と思いCoreMLでこのモデルを使っていろんな画像を評価してみたところ、、、

なんだか微妙だ、、、

評価用画像

↑例えばテスト用データにあった画像(訓練用ではない!)。
これを評価してみると
サンド富澤 71.5%
となり正解なのだが、、、

評価用画像ノイズ付き

↑先ほどの画像に画像処理アプリでノイズを入れてみたら
大島美幸 61.2%
サンド富澤 26.9%
という結果になった。

うーん、このまま行くのは躊躇するなあ。



↓やってて気付いたことなど

1)maxIterationsはデフォで10だが精度がよくなければ倍にしろ、とリファレンスにあるので20にしたら確かに良くなったが30だと20より下がった
2)同じ条件で実行してもやるたびに結果は変わる(データが多い方が安定してるように見えた)
3)オプションのFlipは上下左右反転させるとリファレンスにあった(水平だけが欲しかった)
4)繰り返し評価する場合GUIのMLImageClassifierBuilderを使うよりコード(※1)でMLImageClassifierなどを使った方がラク
5)精度が欲しいならやはりデータの質と量は大事だ


ということで、今はデータセットの質を高めてみようかと考えてる。







※1 コードの場合はこんな感じで。

import Cocoa
import CreateML

let trainDataPathStr = "/Users/…/train/"
let testDataPathStr = "/Users/…/test/"

let trainDataPath = URL(string: trainDataPathStr)!
let testDataPath = URL(string: testDataPathStr)!

// training
let parameters = MLImageClassifier.ModelParameters(
featureExtractor: .scenePrint(revision: 1),
validationData: nil,
maxIterations: 20,
augmentationOptions:[.crop])
let classifier = try! MLImageClassifier(trainingData: .labeledDirectories(at: trainDataPath) ,
parameters: parameters)

// evaluation
let evaluation = classifier.evaluation(on: .labeledDirectories(at: testDataPath))

let evalAccuracy = (1.0 - evaluation.classificationError) * 100.0
print("Evaluation Accuracy: ", evalAccuracy)
print("Confusion: ", evaluation.confusion)
print("Recall: ", evaluation.precisionRecall)


// save model
let metadata = MLModelMetadata(
author: "Tatsuya",
shortDescription: "ite20,40x6,crop only",
version: "1.0")

let saveFilePathStr = "/Users/…/model/hogeClassifier.mlmodel"
let saveDirectory = URL(fileURLWithPath: saveFilePathStr)
try classifier.write(to: saveDirectory, metadata: metadata)



↓参考サイト
Create ML Tutorial: Getting Started | raywenderlich.com

Create MLで簡単に機械学習を体験する - Qiita







【ポケモンGO】1週間で50kmを歩いて得たリワード

あまりやっていなかった時期もあったが、度重なるアップデート(特にいつでも冒険モードはいい!)もあり最近またはまっているポケモンGO。

先日1週間の歩いた距離が初めて50kmを超えた。この時にもらえるものってなんだろう?とずっと思っていたのでメモ。

リワード結果(53.6km)

↑53.6km歩いて
モンスターボール 20個
スーパーボール 10個
ハイパーボール 5個
ふしぎなアメ 8個
ほしのすな 6000(単位なんだろ?)
だった。
ほしのすながこんなにもらえるんだったら今度もらう時にほしのかけら使ってみようかな。毎回もらえるのか知らないが。


リワード結果(40.2km)

↑ちなみにこの翌週は40.2kmで
モンスターボール 20個
スーパーボール 10個
ふしぎなアメ 3個
ほしのすな 1000
だった。10kmの違いで随分違うな、、、なるほど。


リワード結果(43.4km)
↑ぎんのパイルのみがもらえることもあるのか。


リワード結果(57km)
↑週末にコミュニティ・デイ(キモリ大量発生)があったので結構歩いた。リワードは最初のと同じか。


リワード結果
↑初の60km超え!だけどリワードの個数は特に変わらないのか。


リワード結果
↑50km超えてるのにふしぎなアメがないケースもあるのか、、、最近はふしぎなアメがすごく欲しいのだが。




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.