1.mp4
- iOS
- UIKit
- GCD (DispatchSemaphore)
- AVFoundation
- Vision
- CoreML
카메라 Output으로 받아오는 sampleBuffer에서 반려견 비문을 실시간으로 검출하기 위해 Vision 라이브러리를 사용하였습니다.
Vision 라이브러리에서 제공하는 VNCoreMLModel 은 CoreML 기반의 머신러닝/딥러닝 모델을 사용합니다.
때문에 Vision 코드에서 머신러닝/딥러닝 모델을 사용하기 위해서는 기존 모델을 CoreML 형태의 모델로 변환시키거나, 처음부터 CoreML 형태로 학습시키는 방법이 있습니다.
처음에는 Pytorch 로 학습된 YOLO 모델을 활용하여 전자의 방식대로 시도했지만 실제로 사용하는데에는 어려움이 있었고, 이후에는 후자의 방법으로 진행하였습니다.
정리하자면 Object Detection 모델인 YOLO 를 CoreML 형태로 학습하였고, 추출한 CoreML 모델(DogNoseDetector.mlmodel)을 Vision 라이브러리에 성공적으로 적용하였습니다.
또한 CoreML을 사용했기 때문에 온전히 모바일 컴퓨팅 파워를 사용하여 반려견의 코를 실시간으로 검출하게 되었습니다.
비문 촬영을 위한 커스텀 카메라를 구현하기 위해 Apple Standard Library 에서 제공하는 AVFoundation 의 AVCaptureVideoDataOutputSampleBufferDelegate 를 사용하였습니다.
AVCaptureVideoDataOutputSampleBufferDelegate에서 제공하는 captureOutput 함수가 호출될 때, 카메라에서 받아오는 sampleBuffer는 VNImageRequestHandler 함수를 거치게 되며, 해당 함수에서는 이미지 내에서 반려견의 코를 탐지하는 작업을 처리하게 됩니다.
정확하게는, VNImageRequestHandler 함수는 VNCoreMLRequest 로 생성된 이미지 처리 request를 sampleBuffer에 적용하는 작업을 수행합니다.
VNCoreMLRequest 객체를 생성할 때는 completionHandler 함수를 지정해줄 수 있는데, completionHandler 함수에서는 이미지 처리 결과값을 받아와 후처리 작업을 수행 할 수 있게 해줍니다.
후 처리 작업에서는 결과값으로 받아온 반려견의 코와 콧구멍의 좌표(0~1 사이 값으로 정규화된 좌표)들을 활용하여 Detection Overlay Layer 위에 사각형 테두리들을 그려줍니다.
또한 후 처리 작업을 수행할때마다 Detection Overlay Layer는 Preview Layer 위에서 계속 갱신됩니다.
NoseSelectionViewController에서는 유저가 선택한 여러 장의 비문 사진들이 조건에 부합하는지 (반려견의 코가 존재 하는지, 코가 너무 작지는 않은지) 검사하게 됩니다.
이미지가 조건에 부합하는지 검사하는 과정에는 VNImageRequestHandler 함수가 사용되는데, 이 때 비동기로 VNImageRequestHandler 작업을 수행하는 스레드와 UI 를 그려주는 메인 스레드간에 공통으로 사용되는 클래스 멤버 변수가 동기화되지 않는 문제가 발생합니다.
이 문제는 DispatchSemaphore에서 제공하는 wait과 signal 메소드를 사용하여 쉽게 해결 할 수 있었습니다.
- Server
- Flask
- MySQL
- AWS
- Machine Learning
- OpenCV
- Scikit learn
- Pytorch