-->

2020年4月30日木曜日

カメラ画像からリアルタイムで画像認識

環境
  • Xcode 11.4.1
  • Swift 5
  • iOS 13.4.1

参考にしたサイト

SceneDelegate.swift
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        //guard let _ = (scene as? UIWindowScene) else { return }
        
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)
        self.window = window
        window.rootViewController = ViewController(nibName: nil, bundle: nil)
        window.makeKeyAndVisible()
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.
    }


}
UIButtonの場合
 
import UIKit
import AVFoundation
import Vision

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
    
    let label: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Label"
        label.font = label.font.withSize(30)
        return label
    }()
    
    override func viewDidLoad() {
        // call the parent function
        super.viewDidLoad()
        
        // establish the capture session and add the label
        setupCaptureSession()
        view.addSubview(label)
        setupLabel()
    }
    
    override func didReceiveMemoryWarning() {
        // call the parent function
        super.didReceiveMemoryWarning()
        
        // Dispose of any resources that can be recreated.
    }
    
    func setupCaptureSession() {
        // create a new capture session
        let captureSession = AVCaptureSession()
        
        // find the available cameras
        let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices
        
        do {
            // select a camera
            if let captureDevice = availableDevices.first {
                captureSession.addInput(try AVCaptureDeviceInput(device: captureDevice))
            }
        } catch {
            // print an error if the camera is not available
            print(error.localizedDescription)
        }
        
        // setup the video output to the screen and add output to our capture session
        let captureOutput = AVCaptureVideoDataOutput()
        captureSession.addOutput(captureOutput)
        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.frame = view.frame
        view.layer.addSublayer(previewLayer)
        
        // buffer the video and start the capture session
        captureOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))
        captureSession.startRunning()
    }
    
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        // load our CoreML Pokedex model
        guard let model = try? VNCoreMLModel(for: MobileNetV2().model) else { return }
        // run an inference with CoreML
        let request = VNCoreMLRequest(model: model) { (finishedRequest, error) in
            // grab the inference results
            guard let results = finishedRequest.results as? [VNClassificationObservation] else { return }
            
            // grab the highest confidence result
            guard let Observation = results.first else { return }
            
            // create the label text components
            let predclass = "\(Observation.identifier)"
            let predconfidence = String(format: "%.02f%", Observation.confidence * 100)
            // set the label text
            DispatchQueue.main.async(execute: {
                self.label.text = "\(predclass) \(predconfidence)"
            })
        }
        
        // create a Core Video pixel buffer which is an image buffer that holds pixels in main memory
        // Applications generating frames, compressing or decompressing video, or using Core Image
        // can all make use of Core Video pixel buffers
        guard let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
        
        // execute the request
        try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]).perform([request])
    }
    
    func setupLabel() {
        // constrain the label in the center
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        // constrain the the label to 50 pixels from the bottom
        label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
    }
}

2016年1月7日木曜日

Add-Hocで公開

最近作ったアプリをAd-Hoc版としてwebからインストールできるようにした! Provisioning周りを久しぶりにいじってたけど、完全に忘れていた、、、

導入としては、下記リンク先の概念図が非常にわかりやすいと思う
http://qiita.com/fujisan3/items/d037e3c40a0acc46f618

iOS devの操作→Google Driveを使ってAd-Hoc公開までの手順は、
忘れないうちにまとめておこう…

2015年12月19日土曜日

UILabel, UIView, UIButtonの角を丸くする

UILabelとUIViewの場合
 
UILabel *label =  [UILabel alloc]init];
label.clipsToBounds = true;
label.layer.cornerRadius = 3.0f;

UIView *view = [UIView alloc]init];
view.clipsToBounds = true;
view.layer.cornerRadius = 3.0f;
UIButtonの場合
 
UIButton *button = [UIButton alloc]init];
button.layer.cornerRadius = 3.0f;

2015年12月14日月曜日

Xcodeで使える特殊タグ

// TODO: ToDoリストを記述する

// FIXME: 修正項目などを記述する

// !!!: 重要項目を記述する

// ???: 不明点を記述する

#pragma mark
//メソッドの区切りに使う

#warning 警告メッセージ

#error エラーメッセージ

2015年12月7日月曜日

継承したクラスのdelegateメソッドを表示

Xcodeを使ってて今更知ったこと

例えば、UITableViewを継承したカスタムクラスを作ったときに、
必要なdelegateメソッドを知る方法


「UITableViewDelegate」をcommandキーを押しながらクリック


必須のメソッドは
@required

オプションのメソッドは
@optional
で書いてあります。

2015年11月28日土曜日

新しいXcodeでカスタムセルを作ろうと…

久しぶりにアプリを作り始める

UITableViewCellを継承したカスタムセル作るぞー

 
Next(ぽち)

ん…?なんか違うような…
 
Next(ぽち)

えっ!!



正しくはこちら




 



2014年10月13日月曜日

UINavigationBarのtitle、backButtonのフォントを変える

まず、「AppDelegate.m」の『- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions』に、
 
    UIFont *barButtonTitleFont = [UIFont fontWithName:@"mplus-2p-light" size:13];
    UIColor *barButtonTitleColor = [UIColor whiteColor];
    [[UIBarButtonItem appearance] setTitleTextAttributes:@{UITextAttributeFont:barButtonTitleFont, UITextAttributeTextColor:barButtonTitleColor} forState:UIControlStateNormal];
を記述。これで、BackButtonのフォントが変わる

次に、NavigationControllerの『ViewDidLoad』に、
    UILabel* label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 44)];
    label.backgroundColor = [UIColor clearColor];
    label.font = [UIFont fontWithName:@"mplus-2p-light" size:22.0f];
    label.textColor = [UIColor flatWhiteColor];
    label.text = @"タイトル";
    label.textAlignment = NSTextAlignmentCenter;
    self.navigationItem.titleView = label;
を記述。これで、タイトルのフォントが変わる。

それはそうと、m+フォントってとても美しいよね