Retty Tech Blog

実名口コミグルメサービスRettyのエンジニアによるTech Blogです。プロダクト開発にまつわるナレッジをアウトプットして、世の中がHappyになっていくようなコンテンツを発信します。

[iOS] Visionフレームワークを用いた料理写真の画像分類精度検証

Rettyアプリチームの若田(@wakanao_banana )です!この記事はRetty Advent Calendar 2024の4日目の記事です🗓️

12月に入り寒くなってまいりましたが、地元の北海道では冬に部屋をぬくぬく温めてお風呂上がりにアイスを食べる、なんてことを思い出す季節ですね🍨

今回はオンデバイスでの画像分類の精度についてお話しします🫡

Webで十分な時代になぜモバイルアプリを作るのか?

モバイルアプリには、Webでは実現が難しい独自の価値をプロダクトに組み込む力があります。 例えば、滑らかで手に馴染む使い心地の追求、プッシュ通知やリアルタイムの位置情報などを活用した機能、さらにはOS固有の機能を組み込んだ体験の提供など、アプリならではの強みを活かすことが可能です。

今回は、その中で「オンデバイスでの画像分類」をテーマに選び、オフライン環境で動作する画像分類モデルをプロダクションレベルの精度で実現することが可能かを検証しました。

Visionフレームワークについて

developer.apple.com

VisonフレームワークAppleが提供する画像分析のためのフレームワークです。機械学習を活用し、以下のような画像処理機能をアプリケーションに簡単に統合することができます。

  • 人間や動物の体の姿勢や物体の軌道を追跡する
  • 18の異なる言語のテキストを認識
  • 顔や目、鼻、口などの顔の特徴を検出する
  • 物体の検出と分類

そして通信を必要とせずオンデバイスで使用が可能・アプリサイズが変わらないなどの使用上のメリットも大きいです。

今回はVisionフレームワークで提供されている画像分類のAPIである VNClassifyImageRequest を利用して料理写真の分類を行いました。

VNClassifyImageRequest

VNClassifyImageRequestを利用することで以下の数行で画像分類を行うことができます

let handler = VNImageRequestHandler(cgImage: cgIamge, options: [:])
let request = VNClassifyImageRequest()
try? handler.perform([request])
let result = request.results as? [VNClassificationObservation]

VNClassificationObservationは

  • その写真が何かを表すidentifier(food, people, table ...)
  • その確率であるconfidence(0~1)

を持っています。 今回は identifierがfoodのものを料理写真、confidenceを料理写真か否かの閾値として用いて検証を行なっていきます。実際に画像分類を行うと以下の写真のようにラベルとその確度を取得できていることがわかります。

VNClassifyImageRequestの画像分類結果。美味しそうなしらす丼

推論の速度

オンデバイスで完結する画像の推論のメリットとしては通信を介さない速さがあると思い、iPhone14で撮影した画像10枚に対してiPhone14上で画像の推論を行い、処理速度を計測してみました。

let startTime = Date()
                
// 画像の推論
let handler = VNImageRequestHandler(cgImage: cgIamge, options: [:])
let request = VNClassifyImageRequest()
try? handler.perform([request])
let result = request.results as? [VNClassificationObservation] ?? []

// 推論の開始・終了時刻の差分を出す
let endTime = Date()
let processingTime = endTime.timeIntervalSince(startTime)
print("処理時間: \(processingTime) seconds")

結果は1枚あたりおよそ10msで、高速に推論を行うことができました。通信を必要とせずデバイス上で安定して高速な推論が可能なため、アプリケーションに組み込みやすいことがわかります。

料理写真の画像分類の精度検証

精度検証の目的

今回、画像分類を適用するシーンを「ユーザーさんが持つ写真を料理写真と判定すること」と想定します。そして精度検証の目的を、施策に適用可能なレベルで料理写真の分類を行うためのパラメータを見つけること、と位置付けました。

画像分類のイメージ図

ユーザー観点で大切なことは、料理写真を正確に料理写真として判定すること以上に、料理写真ではない写真を間違って料理写真として判定しないことです。 例えば、人が写った写真や料理と全く関係ない写真を料理写真と判定してしまうと、ユーザーに不快感を与え、アプリの印象を悪くする恐れがあります。 そのため、料理写真以外を料理写真として判定しないことを最優先に考え、一方で料理写真を見落としてしまうケースは一定程度許容する方針とします。

検証

自前で分類した料理写真209枚・料理写真以外205枚・合計414枚について、Visionフレームワークを用いて料理か料理以外の写真かの画像分類を行い、その精度を検証しました

自前で分類した料理写真と料理以外の写真

検証方法

Visionフレームワークを用いて、任意のパラメータで料理写真か否かの判別を行い、次の4象限に分類をします。

分類の4象限

4象限に分類したのちAccurecy(精度)、Precision(適合率)、Recall(再現率)の値を算出する。その値を比較し最終的にパラメータを確定させます。

  • Accuracy(精度) = (TP+TN)/(TP+FP+TN+FN)※単純な画像分類の精度
  • Precision(適合率)=TP / (TP+FP)※ 料理写真と予測したうち、実際に料理写真のもの
  • Recall(再現率)=TP / (TP+FN)※ 実際に料理写真のうち、料理写真と予測できたもの

今回の要件では、関係のない写真を料理写真と判定することは避けたいです。なのでRecallが低いことは一定程度許容しPrecisionが高いものを目指しました。

結果

1. foodラベルの確度が80%以上のものを料理写真と分類した場合

foodラベルの確度が80%以上の分類結果

foodラベルの確度が80%以上のAccuracy・Precision・Recall

Accuracy(単純な予測精度)が62%、Precision(料理写真と予測したものの中で正解だった割合)が100%と非常に高い一方で、Recall(実際の料理写真のうち正しく予測できた割合)は24%に留まっています。

この結果から、料理写真以外を誤って料理写真と判定するケースはないものの、料理写真を見落とす取りこぼしが非常に多いため、実用レベルには達していないという結果になりました。

2. foodラベルの確度が30%以上のものを料理写真と分類した場合

foodラベルの確度が30%以上の分類結果
foodラベルの確度が30%以上のAccuracy・Precision・Recall

Recallが75%であり、一部取りこぼしはあるものの、Precisionは98%と非常に高いため、料理写真と予測した中で誤判定(料理写真ではないもの)がほとんどないことが確認できました。これはかなり実用的な精度であると思います○

3. foodが30%以上かつtablewareが30%以上のものを料理写真と分類した場合

食器を表す"tableware"ラベルを掛け合わせることで精度向上を目指しました

foodが30%以上かつtablewareが30%以上の分類結果

foodが30%以上かつtablewareが30%以上のAccuracy・Precision・Recall

Precisionが98%で誤判定は少なく、Recallも73%と比較的高い。ただ(2)とほぼ同等の結果であり、tablewareを含めるメリットはあまりない。

料理写真の判別結果の例

最も結果が良かった、foodラベルの確度が30%以上のものを料理写真と分類した場合、について判別結果の例を以下に示します。

料理写真と分類できた料理写真

料理写真と分類できなかった料理写真

結論

いくつかのパラメータで料理写真の分類精度を比較した結果、foodラベルの確度が30%以上のものを料理であると判定すれば、実用的な精度で料理写真を分類可能なことがわかりました。 簡単に組み込むことができるVisionフレームワークで、実用可能なレベルで画像分類を行うことができると確認できたのはとても大きな収穫となりました!

今回の記事が参考になれば幸いです!寒いので身体には気をつけて暖かいカツカレーをお腹いっぱい頬張りましょう🍛