はじめに
Swift初心者ではありますが、以前から興味があったCoreMLで機械学習にチャレンジしてみました。
機械学習と聞くと、なんとなく難しそうでハードルが高いイメージがあったのですが、実際に触れてみると想像よりも簡単に実装できましたのでまとめてみました。
そもそもCore MLとは?については、まとめられている記事がありましたので紹介させていだきます。
Appleの機械学習がヤバい
成果物
今回は、機械学習モデルを活用してiPhoneで撮影した画像の中の主要なオブジェクトを分類して、その中で1番割合を占めているオブジェクト名を表示する機能を作成していきます。
Navigation barにSiamese cat
と表示されました。
Siamese cat = シャム猫
のようです。(正解はラグドールなのでOKですかね?笑)
猫の種類まで検出するのすごい。。
一応猫を判別することに成功しました!
作成の流れ
1. Core MLを使用するための前準備
Core ML
を使用するためには、モデルのダウンロードとインポートが必要になります。
ここでは、こちらの工程を説明していきます。
1-1. Core MLモデルのダウンロード
今回は、画像識別を行うためのCore MLモデルの1つであるMobileNetV2
を使用します。
そのために、以下Apple developerサイトのモデル一覧からダウンロードする必要があります。
https://developer.apple.com/jp/machine-learning/models/
赤枠内のファイルをダウンロードすることで、今回使用するCore MLモデル
を入手することができます。
1-2. Core MLモデルをインポート
実際に使用するためにXcodeにCore MLモデル
をインポートしていきます。
とは言っても、実際にはドラッグ&ドロップ
するだけの作業になります。。
MobileNetV2.mlmodel
が追加されていれば準備作業は完了です。
続いて、実装作業に進んでいきます。
2. 実装
ここでは、
2-1. iPhoneで撮影した画像を表示する処理
2-2. 画像データを機械学習モデルで分類する処理
を順に実装していきます。
2-1. iPhoneで撮影した画像を表示する処理
2-1-1. StoryBoadに設置
今回は個人的に楽に実装しやすそうなNavigationBar
にCamera
を配置していきます。
撮影した写真を表示させるためにUIImageView
を配置します。
2-1-2. 機能を実装
先ほど設置したオブジェクトにアクションを追加していきます。
-
Camera
をタップするとカメラを起動させる -
UIImageView
に撮影した画像を表示させる
class ViewController: UIViewController, UINavigationControllerDelegate {
// 撮影した画像を表示するImageView
@IBOutlet weak var imageView: UIImageView!
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
// .photoLibraryにするとフォト内の写真を開くことができます。
imagePicker.sourceType = .camera
imagePicker.allowsEditing = false
}
/// NavigationbarItemのカメラをタップした時のアクション
@IBAction func didSelectCamera(_ sender: Any) {
present(imagePicker, animated: true, completion: nil)
}
}
/// UIImagePickerの処理
extension ViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let userSelectedImage = info[.originalImage] as? UIImage {
imageView.image = userSelectedImage
}
imagePicker.dismiss(animated: true, completion: nil)
}
}
UIImagePickerController:
https://developer.apple.com/documentation/uikit/uiimagepickercontroller
###2-1-3. info.plistでカメラ使用許可などを設定
カメラ使用などにユーザーの許可が必要になるためinfo.plistに設定を追加します。
コードではこちらになります。
<key>NSPhotoLibraryUsageDescription</key>
<string>こちらの機能にはフォトを使用します</string>
<key>NSCameraUsageDescription</key>
<string>こちらの機能にはカメラを使用します</string>
2-2. 機械学習の処理を実装
今回は、Core MLで画像の分類を行うためVisionフレームワークを使用して実装していきます。
2-2-1. 使用するフレームワークなどをimportする
import CoreML
import Vision
Core ML:
https://developer.apple.com/jp/documentation/coreml
Visionフレームワーク:
https://developer.apple.com/documentation/vision
2-2-2. Core MLモデルのインスタンス生成と処理
// 使用するCore MLモデルのインスタンスを生成
let model = VNCoreMLModel(for: MobileNetV2().model)
// これでVisionからリクエストを送りmodelを元に解析することができる
let request = VNCoreMLRequest(model: model) { (request, error) in
// 解析結果を分類情報として保存
guard let results = request.results as? [VNClassificationObservation] else {
return
}
}
VNCoreMLModel:
https://developer.apple.com/documentation/vision/vncoremlmodel
VNClassificationObservation:
https://developer.apple.com/documentation/vision/vnclassificationobservation
2-2-3. 画像の解析リクエストをする
2-2-2で作成したCore MLモデルの解析をリクエストする処理を書いていきます。
// Visionへリクエストを送るためにUIImage→CIImageへ変換する
let ciImage = CIImage(image: image)
// 画像解析をリクエスト
let handler = VNImageRequestHandler(ciImage: ciImage)
// リクエストを実行
do {
try handler.perform([request])
}
catch {
print(error)
}
CIImage:
https://developer.apple.com/documentation/coreimage/ciimage
VNImageRequestHandler:
https://developer.apple.com/documentation/vision/vnimagerequesthandler
3. 完成形
import UIKit
import CoreML
import Vision
class ViewController: UIViewController {
// 撮影した画像を表示するImageView
@IBOutlet weak var imageView: UIImageView!
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.allowsEditing = false
}
@IBAction func didSelectCamera(_ sender: Any) {
present(imagePicker, animated: true, completion: nil)
}
}
/// UIImagePickerの処理
extension ViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let userSelectedImage = info[.originalImage] as? UIImage {
imageView.image = userSelectedImage
// 画像からオブジェクトを検出し、出力する
detectImageObject(image: userSelectedImage)
}
imagePicker.dismiss(animated: true, completion: nil)
}
/// 画像からオブジェクトを検出・結果を出力
func detectImageObject(image: UIImage) {
// VNCoreMLModel(for: xx.modle): xxは使用するCore MLモデルによって変わります
guard let ciImage = CIImage(image: image), let model = try? VNCoreMLModel(for: MobileNetV2().model) else {
return
}
// Core MLモデルを使用して画像を処理する画像解析リクエスト
let request = VNCoreMLRequest(model: model) { (request, error) in
// 解析結果を分類情報として保存
guard let results = request.results as? [VNClassificationObservation] else {
return
}
// 画像内の一番割合が大きいオブジェクトを出力する
if let firstResult = results.first {
let objectArray = firstResult.identifier.components(separatedBy: ",")
if objectArray.count == 1 {
self.navigationItem.title = firstResult.identifier
} else {
self.navigationItem.title = objectArray.first
}
}
}
// 画像解析をリクエスト
let handler = VNImageRequestHandler(ciImage: ciImage)
// リクエストを実行
do {
try handler.perform([request])
}
catch {
print(error)
}
}
}
VisionおよびCore MLを使用した画像の分類
https://developer.apple.com/documentation/vision/classifying_images_with_vision_and_core_ml
まとめ
Core MLの情報はdeveloper.appleにサンプルコードなどがあり、手が出しやすい部類かなと思いました。また、用意されているCore MLモデル以外に他社製の機械学習モデルも変換してアプリで使用することができるようなので、かなりの可能性が秘めているなと感じました。ただ、まだ理解できてないところが多いので、実際にコードを書きながら理解を深めて記事でも書ければと思います。
また、本記事に間違い等ございましたら、
大変恐縮でありますがご指摘いただければと存じます。
よろしくお願いいたします。