- 投稿日:2020-09-23T23:44:44+09:00
モーダル、ポップオーバーメモ
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { detailPage() } func detailPage(){ let vc = XibCellDetailViewController()//navigationController?.pushViewController(vc, animated: true)
present(vc, animated: true, completion: nil) }//UITableViewControllerでのXib
class XibTableViewController: UITableViewController{すっごい雑メモでごめんなさい
時間見て編集しなおします
- 投稿日:2020-09-23T18:36:48+09:00
【Swift5】FirestoreとFirebase Storageでの画像の扱い方(初学者向け)
背景
Firebaseを使用して開発することが多く、画像をどのように扱うかを毎回忘れてしまうので
記事に残すことにした。画像の扱い方について
Firebaseを用いて画像を扱う場合によく使われる方法が2つあります。
①Storageから直接取得する
保存時の流れ
- Storageに画像を保存
取得時の流れ
- Storage Refを使用して画像を取得する
メリット
- Storageにセキュリティールールを設定できるので、セキュリティが高くなる
- Storage Refで取得できるので実装が簡単にできる
デメリット
- 画像の一括取得ができないので、リスト表示などをする際は時間がかかってしまう
②DownloadURLをFirestoreへ保存する
保存時の流れ
- Storageに画像を保存
- 保存した画像のdownloadURLを取得
- FirestoreへdownloadURLを保存
取得時の流れ
- FirestoreよりdownloadURLを取得する
メリット
- Firestoreから取得を行うので、一括取得ができる(リスト表示しやすい)
- URLなのでキャッシュできる
デメリット
- URLがわかれば誰でもアクセスできるようになる
- 保存時に何度か通信が行われるのでエラーハンドリングなど含めると実装がすこし複雑になる
今回は②の方の実装について書こうと思います。(エラーハンドリングは除く)
実装
保存時の処理
コメントを入れて解説してるので、少し長くなっていますが
一連の流れは以下になります。PostViewController.swiftclass PostViewController: UIViewController { // 省略 func saveToFirestore() { // nilチェック if let title = titleTextField.text, let content = contentTextField.text, let selectImage = imageView.image { // 今回はpostsというフォルダーの中に画像を保存する let reference = Storage.storage().reference().child("posts") // 今日日付をintに変換して被らない名前にする let imageName = "\(Date().timeIntervalSince1970).jpg" // 画像データがそのままだとサイズが大きかったりするので、サイズを調整 if let imageData = selectImage.jpegData(compressionQuality: 0.8) { // メタデータを設定 let metadata = StorageMetadata() metadata.contentType = "image/jpeg" // ①ここでstorageへの保存を行う reference.putData(imageData, metadata: metadata, completion:{(metadata, error) in if let _ = metadata { // ②storageへの保存が成功した場合はdownloadURLの取得を行う reference.downloadURL{(url,error) in if let downloadUrl = url { // downloadURLの取得が成功した場合 // String型へ変換を行う let downloadUrlStr = downloadUrl.absoluteString // ③firestoreへ保存を行う Firestore.firestore().collection("posts").document().setData([ "title": title, "content": content, "imageURL": downloadUrlStr, "createdAt": FieldValue.serverTimestamp() ]){ error in if let error = error { // firestoreへ保存が失敗した場合 } else { // firestoreへ保存が成功した場合 } } } else { // downloadURLの取得が失敗した場合の処理 } } } else { // storageの保存が失敗した場合の処理 } }) } } } }上記のように3回非同期の処理が入るので
エラーハンドリングを実装する必要があります。(今回は割愛します)取得時の処理
投稿データのモデルを以下のように定義
PostData.swiftclass PostData: NSObject{ var id: String var title: String? var content: String? var imageURL: String? var date: Date? init(document: QueryDocumentSnapshot) { self.id = document.documentID let postDic = document.data() self.title = postDic["title"] as? String self.content = postDic["content"] as? String self.imageURL = postDic["imageURL"] as? String let timestamp = postDic["createdAt"] as? Timestamp self.date = timestamp?.dateValue() } }ListViewController.swiftclass ListViewController: UIViewController, UITableViewDelegate,UITableViewDataSource { var listData:[PostData] = [] override func viewDidLoad() { super.viewDidLoad() // ④Firestoreからデータを取得 Firestore.firestore().collection("posts").getDocuments{ QuerySnapshot, error in if let snapshot = QuerySnapshot { listData = snapshot.documents.map { document in let postData = PostData(document: document) return postData } // tableViewなどに表示する場合はここでreloadDataを呼ぶ } } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return listData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 画像を表示する場合 // stringからURL型に変換 let imageUrl:URL = URL(string: listData[indexPath.row].imageURL as! String)! // URL型からData型に変換 let imageData:Data = try! Data(contentsOf: imageUrl) // 画像をセットする cell.imageView.image = UIImage(data: imageData)! return cell } }上記のようにFirestoreからURLを一括取得できるので、かなり楽にリスト表示をすることができます。
- 投稿日:2020-09-23T01:32:12+09:00
AirPods Proの加速度センサーの値を取得する【iOS14】
はじめに
皆さんは,AirPods ProのSpatial Audioと呼ばれる空間オーディオ再現技術試しましたか?
臨場感がすごいですよね.SpatialAudioは,AirPods Proに搭載されている加速度センサーやジャイロスコープを用いて音場をリマップして,,,
みたいなことをしているらしい.iOS14からCoreMotionの中にCMHeadphoneMotionManagerが追加され
簡単に取ってこれることがわかったのでちょっと調べてみました.いるもの
Xcode : 12.0+
iOS : 14.0+
AirPods ProInfo.plistに使用目的を記述
CoreMotionを使うのでInfo.plistにさくっと追加
実装
import UIKit import CoreMotion class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //AirPods Pro => APP :) let APP = CMHeadphoneMotionManager() guard APP.isDeviceMotionAvailable else { return } APP.startDeviceMotionUpdates(to: OperationQueue.current!, withHandler: {[weak self] _,error in guard error == nil else { return } self?.printData() }) } func printData() { guard APP.isDeviceMotionActive else { return } let data = APP.deviceMotion! // print(data.attitude) // 姿勢 pitch, roll, yaw // print(data.gravity) // 重力加速度 // print(data.rotationRate) // 角速度 // print(data.userAcceleration) // 加速度 // print(data.magneticField) // 磁気フィールド 磁気ベクトルを返す // print(data.heading) // 方位角 } }上記のコードでは,AirPodsを繋いでいたり,何も接続していない時など諸々の処理をする必要がありますが,
実行すると標準出力に取得してきたデータが出てくることがわかります.おわりに
今回は,AirPodsProの加速度センサの値を取得する方法を書きましたが,
今回取得できたデータを綺麗に整形してゴニョゴニョして使えば,頭の向きだけを使用したゲームが作れたりするんだろうなと感じました.
また,ARグラスを作っているなど噂もありますので今後どうなっていくのか期待ですね.今回のプロジェクト+αをGitHubに上げておきました
さくっと試したい方はクローンして使ってみてください.夜中に調べて作ったのでいろいろ間違いがあると思いますので,
間違いや改善点があればコメントで教えてください.参考文献
- CMHeadphoneMotionManager | Apple Developer Documentation
https://developer.apple.com/documentation/coremotion/cmheadphonemotionmanager
- 投稿日:2020-09-23T00:31:59+09:00
【Swift】機械学習(=ML)とAIとの違いを学んだのち、Core ML を実装してみる。〜機械学習を知る編〜
はじめに
こちらでCoreMLの簡単な実装をしています。
【Swift】機械学習(=ML)とAIとの違いを学んだのち、Core ML を実装してみる。〜実装編〜本記事と読み合わせて頂けますと、嬉しいです?
機械学習(= ML) とは?
機械学習は英語で、「
Machine Learning
」
簡単に言うと、以下を指します。
- 『AIが自律的に物事を学ぶための技術』
- 『機械に大量のデータ・パターン・ルールを学習させることにより、判別や予測をする技術』
ML は、意外と歴史のある AI 分野のひとつ
機械学習はAIという概念の中の、1つの分野です。
1959年、機械学習の「父」とされている Arthur Samuel は、
機械学習を以下のように定義しています。「明示的にプログラムしなくても学習する能力」を、コンピュータに与える研究分野。
“Field of study that gives computers the ability to learn without being explicitly programmed”
-- Arthur Samuel --「AI=機械学習」ではなく、
AI > 機械学習 > ディープラーニング
のイメージです。なぜ近年、「機械学習」が大きな話題となっているのか
必要性
これまで人間はデータを分析し、そのデータに基づいてシステムや手順を変更してきました。
しかし、世界のデータ量が増大し、管理できなくなってきており、
データから学習し、それに応じて適応できる自動システムが必要とされています。技術の進歩
- AI技術の進歩
- 大量データの出現
- コンピューター処理能力の向上
使用例
- アマゾンエコーは、機械を使用してトレーニングされた音声テキストと音声認識を使用します
- 疾患の早期発見のために、医学界でも使用されています
- 自動運転車は、機械学習に依存して自分自身を運転します
AI と ML と DL の違い
人工知能【Artificial Intelligence】
人間のような知能をもつアルゴリズム。
※ アルゴリズム ...
「何を」「どのような順番で」「何に対して行うのか」を記述したもの。機械学習【Machine Learning】
AIが自律的に物事を学ぶための技術。
ディープラーニング(= 深層学習)【Deep Learning】
多層のニューラルネットワークを活用し、物事の特徴を抽出する技術。
因みに...
機械学習が「人間が判断・調整する」のに対し、
ディープラーニングは「機械が自動的に行う」ことが特徴。ディープラーニングで、人間が見つけられない パターンやルールの発見、特徴量の設定が可能になり、
人の認識・判断では限界があった
画像認識・翻訳・自動運転
といった技術が飛躍的に上がった。機械学習は、3つに分けられる
機械学習の主な手法には、
「教師あり学習」
「教師なし学習」
「強化学習」
がある。教師あり学習 (= Supervised Learning)
正解データを元に、入力データの特徴やルールを学習します。
✅「過去のデータから、将来起こりそうな事象を予測すること」に使われます。
- 回帰: 連続する数値を予測する
- 分類: あるデータがどのクラスに属するかを予測する
例.
【回帰】 "天候"と"お弁当の販売個数" の関係を学習し、お弁当の販売個数を予測する、
不動産価値、商品価格、株価、会社業績 etc【分類】 果物をサイズ別に分ける、画像や音声を種類別に分ける、
電子メールがスパム(迷惑メール)かどうかを判定する etc教師なし学習 (= Unsupervised Learning)
正解データなしでデータの特徴やルールを学習します。
✅「データに潜む傾向を、見つけ出すため」に使われます。
- クラスタリング: データのグループ分け
- アソシエーション分析: データ間の関連を発見する
- 異常検知: 人による指導なく、正常なものと不正常なもの(異常)を検知する
例. 【クラスタリング】 FacebookやInstagramの「あなたの友達かも..?」機能
【アソシエーション分析】 紙おむつを購入する人はビールも購入するetc強化学習 (= Reinforcement Learning)
失敗や成功を繰り返させ、どの行動が最適か学習します。
✅ 成功に対して「報酬」を与えることで学習効率を上げる方法です。
ロボットの歩行制御
ロボットに「歩けた距離」を報酬として与えます。するとロボットは、
歩行距離を最大化するために、自らさまざまな歩き方を試行錯誤します。
そうすることで、歩行可能距離の長いアルゴリズムが構築されます。囲碁AIの「Alpha Go」
囲碁は手のパターンが膨大過ぎて、既存の最新のコンピュータでも、手を読み切ることは不可能です。
よって、強化学習により、勝ちまでの手を読み切る代わりに、「どの手を打てば勝ちに近づくか」を学習させます。
試合にて失敗や成功を繰り返すと、最適な行動のみを選択するようになります。こうして「Alpha Go」は強くなっていったのです。参考サイト
© 2020 データアーティスト株式会社
機械学習をどこよりもわかりやすく解説!Core ML を実装
Thread 1: Exception: "Source type 1 not available"Privacy - Camera Usage Description
おしまい。
- 投稿日:2020-09-23T00:27:46+09:00
【Swift】機械学習(=ML)とAIとの違いを学んだのち、Core ML を実装してみる。〜実装編〜
はじめに
こちらでCoreMLを学ぶのに必要な、機械学習のイロハについて解説しています。
【Swift】機械学習(=ML)とAIとの違いを学んだのち、Core ML を実装してみる。〜機械学習を知る編〜本記事と読み合わせて頂けますと、嬉しいです?
Core ML の実装
結果
約58%の確率で、インド象?
全ての無有機物の中から"インド象"だと認識していると考えたら、かなり高確率..!インドゾウ(学名:Elephas maximus indicus、英語名:Indian elephant)は、
哺乳綱- ゾウ目(長鼻目)- ゾウ科- アジアゾウ属に分類されるアジアゾウの、下位分類にあたる1亜種。// アジアゾウの1種、インド象である と58%の高確率で認識。 confidence=0.587781 "Indian elephant, Elephas maximus",// 因みに2番目の候補は tusker confidence=0.219008 "tusker"tusker .. 大きいきばの生えた動物 《ゾウ・イノシシなど》.
前提知識
Core ML
- Core MLはAppleの機械学習フレームワーク
- 機械学習系のiOSアプリを作るのに適する
- Pythonなど、他の言語を学ぶ必要が無い
Core ML model に学習させる
- テストデータを元に、モデルデータ(Core ML model) に学習させる
- Appleが既に用意してくれている、Core MLモデルをダウンロード可能
- (今回は画像認識モデルの1つである、MobileNetV2を使用。)
CaffeやKerasなど、Appleが提供している以外の機械学習フレームワークを使用する場合は、それらをMLモデルファイルに変換する必要があります。
下準備
- ダウンロードしたCore MLモデルを、Xcodeナビゲーションバーに D&D
- UIImagePickerControllerDelegate, UINavigationControllerDelegateを追加
UIImagePickerController()
のプロパティを設定func imagePickerController
を記述import UIKit import CoreML // 必要 import Vision // Imageをより簡単に処理できる、画像認識APIを提供するフレームワーク class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet weak var testImageView: UIImageView! let imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() // プロパティを設定 imagePicker.delegate = self imagePicker.sourceType = .photoLibrary //.cameraは、実機のみ imagePicker.allowsEditing = false } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { // データの値は Any なので、ダウンキャスト // let userPickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage if let userPickedImage = info[.originalImage] as? UIImage { testImageView.image = userPickedImage } //imagePickerを閉じたときの処理 imagePicker.dismiss(animated: true, completion: nil) } @IBAction func cameraTapped(_ sender: Any) { present(imagePicker, animated: true, completion: nil) } }補足
- Xcode10から、UIImagePickerControllerの仕様が少し変更になり、
info[.originalImage]
を使用。- delegateのイメージ画像 (
self
= ViewControllerクラス)カメラ機能を有効にする方法
カメラ
.camera
が使えるのは、実機のみ。
尚、info.plistでカメラ使用許可などを設定が必要。(参考)モデルから、画像認識 の結果を取得 【4ステップ】
UIImage を CIImage に変換
// UIImage -> CIImageへ変換 guard let ciImage = CIImage(image: userPickedImage) else { fatalError("UIImage から CIImage への変換に失敗しました") }Core MLモデルのインスタンスを生成
VNCore MLModelクラスの
「VN」
は、Vision と NSObjectの 頭文字(...かな?)func detect(image: CIImage) { // try? を使い、モデル取得に失敗するとnilを返す guard let model = try? VNCoreMLModel(for: MobileNetV2().model) else { fatalError("MobileNetV2モデルの取得に失敗しました") } }因みに
NS
は、NEXT STEP というシステムの名残らしい。アップルを追い出されたスティーブ・ジョブズが作り始めた新たなシステムがNEXT STEPで、その先進性もあって、Mac OS開発に行き詰っていたアップルに乗り込んで売り込み、返り咲きを果たしました。
今のMac OS は、このNEXTSTEPをもとに開発されました。
取得したモデルを使用して、CoreMLに画像認識をリクエストする
// 取得したモデルを使用して、CoreMLに画像認識を要求する let request = VNCoreMLRequest(model: model) { (request, error) in // リクエスト結果を、分類情報として保存 guard let results = request.results as? [VNClassificationObservation] else { fatalError("モデルは画像の処理に失敗しました。") } print(results) }
results
は[Any]?
型なので、アンラップ & ダウンキャストVNClassificationObservation
画像解析リクエストによって生成された、分類情報。完了ハンドラの
{ }
は以下を参考に。Trailing Closureとは?
関数の引数のうち 最後の引数がクロージャの場合、
クロージャを( )の外に書くことができる。リクエストを実行
先程書いたのは "リクエストした時"のコード。
下記VNImageRequestHandler
で実際に実行する。// VNImageRequestHandler で リクエストを実行 // image は引数 let handler = VNImageRequestHandler(ciImage: image) do { try handler.perform([request]) } catch { print(error) }VNImageRequestHandler
VNCoreMLRequest を実行するためのクラス。コード まとめ
- 関数
detect
の呼び出しを忘れがち..print(results)
をコメントアウトして、ナビゲーションバーのTitleに結果を表示。firstResult の
identifier
に"elephant"という単語がcontain
されていたら、self.navigationItem.titleに"This is elephant!!"と表示。//ナビゲーションバーのTitleに結果を表示。 if let firstResult = results.first { if firstResult.identifier.contains("elephant") { self.navigationItem.title = "This is elephant!!" } else { self.navigationItem.title = "Not elephant.." } }import UIKit import CoreML import Vision class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { @IBOutlet weak var testImageView: UIImageView! let imagePicker = UIImagePickerController() override func viewDidLoad() { super.viewDidLoad() imagePicker.delegate = self imagePicker.sourceType = .photoLibrary imagePicker.allowsEditing = false } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let userPickedImage = info[.originalImage] as? UIImage { testImageView.image = userPickedImage // UIImage -> CIImageへ変換 guard let ciImage = CIImage(image: userPickedImage) else { fatalError("UIImage から CIImage への変換に失敗しました") } // 関数の呼び出しを忘れずに detect(image: ciImage) } imagePicker.dismiss(animated: true, completion: nil) } func detect(image: CIImage) { // Core MLモデルのインスタンスを生成 guard let model = try? VNCoreMLModel(for: MobileNetV2().model) else { fatalError("MobileNetV2モデルの取得に失敗しました") } // 取得したモデルを使用して、CoreMLに画像認識を要求する let request = VNCoreMLRequest(model: model) { (request, error) in // リクエスト結果を、分類情報として保存 guard let results = request.results as? [VNClassificationObservation] else { fatalError("モデルは画像の処理に失敗しました。") } //print(results) //ナビゲーションバーのTitleに結果を表示。 if let firstResult = results.first { if firstResult.identifier.contains("elephant") { self.navigationItem.title = "This is elephant!!" } else { self.navigationItem.title = "Not elephant.." } } } // VNImageRequestHandler で リクエストを実行 let handler = VNImageRequestHandler(ciImage: image) do { try handler.perform([request]) } catch { print(error) } } @IBAction func cameraTapped(_ sender: Any) { present(imagePicker, animated: true, completion: nil) } }参考