본문 바로가기
iOS/ML

CoreML + Vision을 사용해보자

by 융식 2022. 8. 24.

Vision은 이미지와 비디오와 관련된 기능을 제공합니다.

 

사용할 CoreML Model을 드래그앤 드롭으로 가져옵니다.

 

저는 Resnet50 모델을 사용했습니다.

 

 

 

카메라 혹은 앨범에서 이미지를 가져와 그 이미지를 분석하여 어떤 물체인지 판별합니다.

 

그러기 위해서 가장 먼저 카메라를 사용할 수 있게 해야합니다. 

 

 

카메라를 사용할 수 있게 Info에 Camera Usage Descrption을 추가해줍니다.

 

앨범에서도 이미지를 선택해 올 수 있게 Photo Library Usage Description도 추가해줍니다.

 

이미지를 선택할 수 있게 델리게이트를 만들어 줍니다.

 

 

이미지를 선택할수 있게 이미지 픽커를 설정해주고 델리게이트와 카메라를 설정해 줍니다.

 

 

 

특정 버튼을 눌렀을 때 카메라로 혹은, 앨범으로 넘어갈 수 있게 설정해 줍니다.

 

 

이제 앨범에서 이미지를 선택할 때 사용할 함수를 설정해 줍니다.

 

이미지를 분석하기 위해서는 CGImage 혹은 CIImage로 변경해주어야 합니다. 

 

 

CIImage로 변경해주고 Resnet50모델을 사용하고 Vision을 이용하여 분석해줍니다.

 

VNCoreMLModel을 이용하여 CoreML을 Vision 모델로 래핑시켜줍니다.  

 

 

래핑된 모델을 분석할 수 있게 모델을 요청하고 요청한 값을 분석시킵니다. 

 

분석된 값들 중 제일 확률이 높은 값이 노트북이라면 레이블을 바꾸어줍니다. 

 

 

가져온 이미지를 분석하기 위해서는 핸들러가 필요합니다. 

 

가져온 이미지를 핸들러로 래핑해주고 래핑된 값을 perform을 통해서 분석시키게 합니다.

 

 

완성~

 

 

Vision을 이용하여 분석하는데 가장 중요한 부분, 그러니까 ML이 사용되는 플로우는 

 

  1. VNCoreMLModel을 통해 모델을 만들어주고 만들어진 모델을 통해
  2. VNImageRequestHandler로 이미지 분석을 요청하여
  3. VNCoreMLRequest를 통해 이미지를 식별요청하고
  4. VNClassificationObservation로 이미지를 분석하여 결과를 도출합니다.

 

 

 

 

풀 코드

 

import UIKit
import CoreML
import Vision

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    @IBOutlet weak var imageView: UIImageView!
    
    let imagePicker = UIImagePickerController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        imagePicker.delegate = self
        // .camera 카메라 사용, .photoLibrary 사진앨범 이동
        imagePicker.sourceType = .camera
        imagePicker.allowsEditing = false    //사용자가 사진을 편집할 수 있게 할지(자르기, 크기 조절 등)
        
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        // 사용자가 이미지를 선택해옴
        if let userPickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
            // 뷰를 선택된 이미지로 변경
            self.imageView.image = userPickedImage
            // CIImage로 변경
            guard let ciImage = CIImage(image: userPickedImage) else {
                fatalError("Failed to CIImage")
            }
            // ML로 분석
            detect(image: ciImage)
        }
        
        imagePicker.dismiss(animated: true)
        
    }
    
    // 선택한 이미지를 ML을 통해 분석
    func detect(image: CIImage) {
        // Model을 VisionModel로 변환
        guard let model = try? VNCoreMLModel(for: Resnet50().model) else {
            fatalError("Loading CoreML Model Failed")
        }
        // Vision ML 요청값
        let request = VNCoreMLRequest(model: model) { request, error in
            // 요청한 결과 값 저장
            guard let results = request.results as? [VNClassificationObservation] else {
                fatalError("model failed to process image")
            }
            if let firstresult = results.first {
                self.navigationItem.title = firstresult.identifier.contains("keypad")
            }
//            print(results)
        }
//        print(request)
        // 핸들러를 통해 이미지를 분석
        let handler = VNImageRequestHandler(ciImage: image)
        do {
            try handler.perform([request])
        } catch {
            print(error)
        }
    }
    
    @IBAction func cameraTapped(_ sender: UIBarButtonItem) {
        present(imagePicker, animated: true, completion: nil)
    }
    
}