swift:CIDetectorを使ってみました
概要
CoreImage Libraryを使うと顔認識ができます。以下を参考にして、CIDetectorを使った顔認識をしてみました。
結果
顔のおおざっぱな位置を調べる目的には十分使えそうです。
笑っているかどうかをチェックできるのは興味深いと思いますが、本写真の結果はfalseになっていました。どのような写真だと笑顔を認識できるのか調べる必要がありそうです。
顔の輪郭を矩形として取得できる
CIFaceFeature.boundsで取得できます。
目の位置が取得できる
左右の目の位置を個別に取得できます。ただし、矩形ではなく、開始位置のみです。
- CIFaceFeature.leftEyePosition.x
- CIFaceFeature.leftEyePosition.y
- CIFaceFeature.rightEyePosition.x
- CIFaceFeature.rightEyePosition.y
口の位置が取得できる
口の位置を取得できます。ただし、矩形ではなく、開始位置のみです。
- CIFaceFeature.mouthPosition.x
- CIFaceFeature.mouthPosition.y
その他
顔の部分チェックができます。
左目があるか | hasLeftEyePosition |
右目があるか | hasRightEyePosition |
口があるか | hasMouthPosition |
笑っているか | hasSmile |
左目が閉じているか | leftEyeClosed |
右目が閉じているか | rightEyeClosed |
顔が傾いているか | hasFaceAngle |
関連資料
swift言語:Reflection APIを使ってみました
概要
swiftに含まれているReflection APIについて、The Swift Reflection API and what you can do with itを参考に、調べました。
ソースのコメントを見ると、PlaygroundやDebuggerなどで使うことが目的のようです。
$ cat ./stdlib/public/core/Mirror.swift
/// Mirrors are used by playgrounds and the debugger.
MirrorTypeも使えるようですが、使い方がわかりませんでした。
Reflection API
サンプルデータ
The Swift Reflection API and what you can do with itのサイトで説明に使っているデータです。
import Foundation.NSURL public class Store { let storesToDisk: Bool = true } public class BookmarkStore: Store { let itemCount: Int = 10 } public struct Bookmark { enum Group { case Tech case News } private let store = { return BookmarkStore() }() let title: String? let url: NSURL let keywords: [String] let group: Group } let aBookmark = Bookmark(title: "Appventure", url: NSURL(string: "appventure.me")!, keywords: ["Swift", "iOS", "OSX"], group: .Tech)
Mirror
Reflection APIを使うための最も簡単な方法は、Mirrorを作成することです。
// Mirror let aMirror = Mirror(reflecting: aBookmark) print(aMirror) // Mirror for Bookmark
「Mirror for Bookmark」が出力されます。これは以下のメソッド定義によります。
$ cat ./stdlib/public/core/Mirror.swift /// Reflection for `Mirror` itself. extension Mirror : CustomStringConvertible { public var description: String { return "Mirror for \(self.subjectType)" } }
Mirrorのメソッドは4つあります。
- Mirror.displayStyle
- Mirror.children
- Mirror.subjectType
- Mirror.superclassMirror:
Mirror.displayStyle
display styleを表示します。
print (aMirror.displayStyle)
Optional(Struct)が出力されます。データの型が出力されます。
public enum DisplayStyle { case Struct case Class case Enum case Tuple case Optional case Collection case Dictionary case Set }
Mirror.children
child要素を一覧します。
for case let (label?, value) in aMirror.children { print (label, value) }
Mirror.subjectType
型情報を出力します。
// subject type print(aMirror.subjectType) //prints : Bookmark print(Mirror(reflecting: 5).subjectType) //prints : Int print(Mirror(reflecting: "test").subjectType) //prints : String print(Mirror(reflecting: NSNull()).subjectType) //print : NSNull
Mirror.superclassMirror
スーパークラス情報を出力します。
// try our struct print(Mirror(reflecting: aBookmark).superclassMirror()) // prints: nil // try a class print(Mirror(reflecting: aBookmark.store).superclassMirror()) // prints: Optional(Mirror for Store)
関連資料
swift: UIRefreshControlを使ってみました
概要
画面を下に引っ張ってデータを更新する用UI部品、UIRefreshControlを使ってみました。UIRefreshControl Class Referenceでは、以下のような説明になっています。
UIRefreshControlは、Table Viewのコンテンツを更新するために使う標準コントロールを提供します。Table View Controllerはユーザージェスチャに応じてデータを更新する見た目を処理します。
UIRefreshControlを使ったサンプルコードはここから取得出来ます。
実装
UITableViewの準備
storyboardを使ってUITableViewControllerを使ったアプリを作成しました。これ以外にもUITableViewを作成する方法はあります。
UITableViewControllerクラスを継承したControllerを作成し、TableViewDataSourceプロトコルを実装します。
class TableViewController: UITableViewController { var items = [Item]() override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell cell.textLabel!.text = items[indexPath.row].title return cell } } class Item { var title = "" init(title: String) { self.title = title } }
UIRefreshControlを追加します
UITableViewControllerは、プロパティにUIRefreshControlを持っているので作成したインスタンスをセットします。addTargetで指定したメソッドが呼び出されます。
self.refreshControl = UIRefreshControl() self.refreshControl?.attributedTitle = NSAttributedString(string: "引っ張って更新") self.refreshControl?.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
イベント処理
データを更新しRefresh処理を終了します。Refresh処理終了メソッド(endRefreshing)を呼び出さないとずっとくるくる回ったままになります。
func refresh() { print("refresh...") let count = items.count items.append(Item(title: "item" + String(count + 1))) items.append(Item(title: "item" + String(count + 2))) items.append(Item(title: "item" + String(count + 3))) self.tableView.reloadData() self.refreshControl?.endRefreshing() }
画面キャプチャ
NavigationControlも追加していますが、これはUIRefreshControlの使い方には関係ありません。
関連資料
iPhoneの画面キャプチャをMacOSXで行う方法
概要
MacOSX(Yosemite)を使うとLightning ポートを装備した、iOS8以降のiOSデバイス(iPhone, iPad, iPod touch)の画面を録画できます。
手順
iOSデバイスを接続します
Lightning ポート経由でiOS8以降のiOSデバイスとMacOSX(Yosemite)を接続します。
QuickTimePlayerを起動します
ファイル-新規ムービー収録(option+Command+N)を実行します。
カメラをiOSデバイスに変更します
録画ボタンの右隣にあるアイコンをクリックして、iOSデバイスを選択します。
iOSデバイスの画面が表示されます。録画ボタンをクリックすると録画が始まります。もちろん、画面キャプチャもできます。
関連資料
【書籍】iPhoneアプリ開発「超」入門について
概要
絶対に挫折しない iPhoneアプリ開発「超」入門 増補改訂第4版【Swift 2 & iOS 9】完全対応は、プログラミング初心者向けiPhoneアプリ開発入門書として人気のある書籍です。swift言語に対応しています。
iOSアプリ開発を行うためには、3種類の知識、1)言語(swift)に関する知識、2)iOS(UIKit)に関する知識、3)開発環境(XCode)に関する知識が必要となります。
多くの開発入門書には、最初に言語仕様の説明がありますが、たいていかなり長く退屈です。この書籍は、最初に、必要最小限の言語仕様に関する説明を行い、後は、実際にアプリを作りながら、そのアプリを作成する上で必要な言語仕様の説明を行うというスタイルをとっています。そのため、書籍を最後まで読み通すというハードルを越えやすい構成になっています。
今回、本書籍のiOS9対応版が出版されました。何が変わったのか概要を調べました。
新しく、画面遷移、ネットワーク通信が追加され、より実践的なアプリ開発まで行うことができるようになっています。その分、難しくなっています。
目次
大きな変更点は2点あります。
総合演習追加
9章 「iPhone本体へのインストールと設定」が削除され、かわりに、10章 「今後につながる少し高度なアプリ開発 【総合演習】」が追加された。
補足を章に集約
12章 「アプリのリリース」と補足「公式ドキュメントの読み方/アプリで収益を上げる方法など」が合体して、「情報の収集方法とアプリの公開」になった。
章 | 補足 |
---|---|
Chapter 01 iPhoneアプリ開発の基礎知識 | 開発環境 |
Chapter 02 XcodeとiOSシミュレータの基本操作 | 開発環境 |
Chapter 03 今日からはじめるSwiftプログラミング【入門前夜】 | 言語(swift) |
Chapter 04 今日からはじめるSwiftプログラミング【超入門】 | 言語(swift) |
Chapter 05 クラスとインスタンス~UI部品の利用~ | 言語(swift) |
Chapter 06 iPhoneアプリ開発をはじめよう! | こんにちはアプリ |
Chapter 07 自作アプリで広告収入を得る方法 | SNSアプリ |
Chapter 08 SNSアプリ開発で学ぶボタン機能と画像配置 | アプリ |
Chapter 09 カメラアプリ開発で学ぶプロトコルとデリゲート | カメラアプリ |
Chapter 10 今後につながる少し高度なアプリ開発 【総合演習】 | ニュースリーダーアプリ |
Chapter 11 アプリ開発の仕上げ | アプリアイコン |
Chapter 12 情報の収集方法とアプリの公開 | その他 |
総合演習追加
10章 「今後につながる少し高度なアプリ開発 【総合演習】」が追加されました。
ニュースリーダアプリを例題に、ネットワーク通信、TableViewを使ったデータ表示、画面遷移が追加されました。
RSSデータの取得と解析
ネットワーク通信によるデータ取得とXML解析が追加されました。
RSSデータの表示
TableViewによるRSSデータ表示が追加されました。
画面遷移
セグエによる画面遷移が追加されました。
【補足】取得出来る文法一覧
swift言語: AVFoundationを使ってQRCodeReaderを作成してみました
概要
QRCode Reader Using Swift Tutorialを参考に、AVFoundationを使ってQRCodeReaderを作成してみました。
QRコード読取処理のライブラリ化を行いながら、AV Foundationについてもう少し調べていく予定です。
AV Foundation
AVFoundationは、時間ベースのオーディオビジュアルメディアの再生と作成に使用できるフレーム ワークで、時間ベースのオーディオビジュアルデータに関する作業を細かいレベルで行うための インターフェイスを提供します。詳細は、以下を参照してください。
- AV Foundation for iOS and OS X - Apple Developer
- About AVFoundation
- AVFoundationプログラミングガイド
- AVCam-iOS: Using AVFoundation to Capture Images and Movies
AV Foundationの各クラスの説明が、以下にあります。 AV Foundation Framework Reference
AVFoundationのswift実装については、以下のページが参考になります。 AVFoundation Changes for Swift
実装
以下の手順で実装します。
セッションを作成します
キャプチャデバイスを探し、セッションを作成します。
参考。
- AVCaptureDevice Class Reference
- AVCaptureDeviceInput Class Reference
- AVCaptureSession Class Reference
func configureVideoCapture() -> AVCaptureSession? { do { let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) let deviceInput = try AVCaptureDeviceInput(device: captureDevice) as AVCaptureDeviceInput let session = AVCaptureSession() session.addInput(deviceInput as AVCaptureInput) let metadataOutput = AVCaptureMetadataOutput() session.addOutput(metadataOutput) metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue()) metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode] return session } catch let error as NSError { let alertController: UIAlertController = UIAlertController(title: "Device Error", message: error.localizedFailureReason, preferredStyle: .Alert) let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil) alertController.addAction(defaultAction) presentViewController(alertController, animated: true, completion: nil) } return nil }
VideoPreviewLayerを作成します
キャプチャしている画像を表示するPreviewLayperを作成します。
参考。
func createVideoPreviewLayer(session: AVCaptureSession) -> AVCaptureVideoPreviewLayer? { let captureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session) if let preview = captureVideoPreviewLayer { preview.videoGravity = AVLayerVideoGravityResizeAspectFill preview.frame = view.layer.bounds return preview } return nil }
delegateメソッド実装
AVCaptureMetadataOutputObjectsDelegateプロトコルを実装する必要があります。
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) { if metadataObjects == nil || metadataObjects.count == 0 { didnotDetectQRCode(); return } let metadata: AVMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject didFindQRCode(metadata) } func didnotDetectQRCode() { qrcodeView!.frame = CGRectZero print("NO QRCode text detacted") } func didFindQRCode(metadata: AVMetadataMachineReadableCodeObject) { if metadata.type == AVMetadataObjectTypeQRCode { let barCode = captureVideoPreviewLayer!.transformedMetadataObjectForMetadataObject(metadata) as! AVMetadataMachineReadableCodeObject qrcodeView!.frame = barCode.bounds; if metadata.stringValue != nil { qrcodeView!.frame = CGRectZero let result = metadata.stringValue print(result) self.label.text = result self.captureVideoPreviewLayer!.removeFromSuperlayer() self.captureSession!.stopRunning() } } }
UI作成
QRコードを囲むUIViewを作成します。
func createQRView() -> UIView { let view = UIView() view.layer.borderColor = UIColor.redColor().CGColor view.layer.borderWidth = 5 return view }
scanボタン作成。
QRコード読取を開始するUIButtonを作成します。UIButtonクリックイベントに以下の処理を追加します。
@IBAction func doScan(sender: UIBarButtonItem) { self.captureSession = self.configureVideoCapture() if let session = self.captureSession { self.captureVideoPreviewLayer = self.createVideoPreviewLayer(session) if let preview = captureVideoPreviewLayer { self.view.layer.addSublayer(preview) session.startRunning() let view = self.createQRView() self.view.addSubview(view) self.view.bringSubviewToFront(view) self.qrcodeView = view } } }
ソースコード
関連資料
- QRCode Reader Using Swift Tutorial
- AV Foundation for iOS and OS X - Apple Developer
- About AVFoundation
- AVFoundationプログラミングガイド
- AVCam-iOS: Using AVFoundation to Capture Images and Movies
- AVFoundation Changes for Swift
- AV Foundation Framework Reference
- AVCaptureDevice Class Reference
- AVCaptureDeviceInput Class Reference
- AVCaptureSession Class Reference
- AVCaptureVideoPreviewLayer Class Reference
swift:QRCodeReaderアプリを作ってみました
概要
yannickl/QRCodeReader.swiftライブラリを使ってQRCodeReaderアプリを作ってみました。
今回使ったライブラリは、QRコードを読み取った後ハングしているようでした。何か処理を追加する必要があるかもしれません。今後使うかどうかは、もう少し使ってから判断したいと思います。
インストール
Carthageというライブラリ管理ツールを使いました。 Swift - Carthageを使ってビルド時間を短縮しよう - Qiitaを参考に行いました。
プラグインモジュール作成
Carthageファイルを作成します。
$ cat Carthage github "yannickl/QRCodeReader.swift" >= 5.2.0
carthage updateを実行して、Githubからソースをダウンロードしてモジュールのビルドを行います。
$ carthage update *** Cloning QRCodeReader.swift *** Checking out QRCodeReader.swift at "5.2.1" *** xcodebuild output can be found in /var/folders/bm/gfw2hl4d3zv5f29zchj4p_z40000gn/T/carthage-xcodebuild.8s8ORm.log *** Building scheme "QRCodeReader" in QRCodeReader.swift.xcodeproj 2015-12-25 06:15:18.916 xcodebuild[884:18782] [MT] PluginLoading: Required plug-in compatibility UUID F41BD31E-2683-44B8-AE7F-5F09E919790E for plug-in at path '~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/VVDocumenter-Xcode.xcplugin' not present in DVTPlugInCompatibilityUUIDs ...
プラグインモジュールをプロジェクトに追加
Generalタブから、carthage updateコマンドでビルドしたモジュールをEmbedします。
Build Phasesタブでから、Runscriptを追加します。carthageはHomebrewでインストールしました。違う方法でインストールした場合には、carthageのパスを調べて入力してください。
アプリ作成
QRCodeReaderライブラリを使ってアプリを作ります。QRCodeReaderライブラリを起動するボタンを追加するだけです。
ボタンを追加します
StoryBoardを使ってUIButtonを追加します。ラベル名をscanにします。
ボタンをタップしたときのアクションを追加します。
ViewControllerに以下の処理を追加します。
import UIKit import AVFoundation import QRCodeReader class ViewController: UIViewController { // QRコード読取ライブラリのView Controllerのインスタンスを作成します // lazyキーワード:必要になった時にインスタンスが作成されます。 lazy var reader = QRCodeReaderViewController(metadataObjectTypes: [AVMetadataObjectTypeQRCode]) @IBAction func scanAction(sender: UIButton) { // reader.delegate = self // closure pattern reader.completionBlock = { (result: String?) in print(result) } // Presents the reader as modal form sheet reader.modalPresentationStyle = .FormSheet presentViewController(reader, animated: true, completion: nil) }
アプリ実行
QRコードをキャプチャするとConsoleにその内容が出力されます。確かにデータは取得出来ているようです。
Optional("apply-est@est.seamall.jp")