Vision은 이미지와 비디오와 관련된 기능을 제공합니다.
사용할 CoreML Model을 드래그앤 드롭으로 가져옵니다.
저는 Resnet50 모델을 사용했습니다.
카메라 혹은 앨범에서 이미지를 가져와 그 이미지를 분석하여 어떤 물체인지 판별합니다.
그러기 위해서 가장 먼저 카메라를 사용할 수 있게 해야합니다.
카메라를 사용할 수 있게 Info에 Camera Usage Descrption을 추가해줍니다.
앨범에서도 이미지를 선택해 올 수 있게 Photo Library Usage Description도 추가해줍니다.
이미지를 선택할 수 있게 델리게이트를 만들어 줍니다.
이미지를 선택할수 있게 이미지 픽커를 설정해주고 델리게이트와 카메라를 설정해 줍니다.
특정 버튼을 눌렀을 때 카메라로 혹은, 앨범으로 넘어갈 수 있게 설정해 줍니다.
이제 앨범에서 이미지를 선택할 때 사용할 함수를 설정해 줍니다.
이미지를 분석하기 위해서는 CGImage 혹은 CIImage로 변경해주어야 합니다.
CIImage로 변경해주고 Resnet50모델을 사용하고 Vision을 이용하여 분석해줍니다.
VNCoreMLModel을 이용하여 CoreML을 Vision 모델로 래핑시켜줍니다.
래핑된 모델을 분석할 수 있게 모델을 요청하고 요청한 값을 분석시킵니다.
분석된 값들 중 제일 확률이 높은 값이 노트북이라면 레이블을 바꾸어줍니다.
가져온 이미지를 분석하기 위해서는 핸들러가 필요합니다.
가져온 이미지를 핸들러로 래핑해주고 래핑된 값을 perform을 통해서 분석시키게 합니다.
완성~
Vision을 이용하여 분석하는데 가장 중요한 부분, 그러니까 ML이 사용되는 플로우는
- VNCoreMLModel을 통해 모델을 만들어주고 만들어진 모델을 통해
- VNImageRequestHandler로 이미지 분석을 요청하여
- VNCoreMLRequest를 통해 이미지를 식별요청하고
- 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)
}
}