CoreML이란? 간단한 글자인식 앱 만들기
iOS에서 머신러닝을 사용할 수 있게 해주는 CoreML 프레임워크에 대해 알아보자.
Overview

CoreML 프레임워크는 머신러닝 알고리즘을 training data에 적용하여 Model을 만든다. 이 Model을 사용하여 개발자는 새로운 input data에 대해 prediction을 만들어 낼 수 있고 우리가 코드로 작성하기 어렵거나 비현실적인 작업을 성취해 낼 수 있다. 예를들어, 사진을 분류하거나 특정한 대상이 포함된 사진을 찾아내는데 사용된다.
모델을 만들면, 모델을 앱에 통합하고 사용자의 기기에 배치한다. 앱은 CoreML API와 user data를 사용해서 prediction을 도출하거나, 모델을 훈련시키거나, 모델의 미세한 조정을 할 수 있다.
2가지 방법으로 모델을 사용할 수 있는데,
- Xcode에 포함된 Create ML app 을 사용해 모델을 Build하고 Train하는 방법
- 다른 라이브러리를 사용하고 Core ML Tools를 사용해 Core ML format으로 변환하는 방법
1번의 경우는 애플이 만든 Create ML App 을 사용해 처음부터 모델을 빌드 할 수 있는 방법이다. 아래와 같이 머신러닝의 도메인을 택하여 모델을 만들고 데이터를 통해 훈련시킬 수 있다.

2번의 경우는 TensorFlow 같이 다른 라이브러리에서 만들어진 모델을 애플의 Core ML Tools를 사용해 CoreML 모델 포맷으로 변환시켜 사용할 수 있다.

Core ML은 CPU, GPU, Neural Engine을 레버리징하고 메모리 사용량과 전력 소모량을 최소화하여 최적화를 한다. 네트워크 연결을 제한하여 모델을 실행하는 것은 사용자의 데이터를 지키고 앱의 반응성을 향상시킬 수 있다.
Core ML은 도메인 특화 프레임워크, 기능의 Foundation이다. 현재 애플은 4개의 도메인 특화 프레임워크를 지원한다.
- Vision - 이미지 분석
- Natural Language - 자연어 처리
- Speech - 음성 → 텍스트
- Sound Analysis - 소리 → 음성
Core ML은 가장 Low 레벨인 Accelerate and BNNS 와 Metal Performance Shaders 바로 위에 위치한다.

그렇다면 통신을 통해 머신러닝 모델을 활용하는 것 대비 CoreML을 사용하는게 어떤 장점이 있을까?
1. 사용자의 데이터를 보호할 수 있다.
2. 통신에서 자유롭기에 좀 더 좋은 앱 '반응성'과 '사용성'을 가져갈 수 있다.
반응성과 사용자 데이터 보호는 모바일 앱에 있어서 중요한 요소로, CoreML의 장점이 충분히 있다고 생각 할 수 있다.
Vision 프레임워크를 사용하여 간단한 텍스트 인식 앱 만들기
위에서 설명한 4개의 Domain-Specific 프레임워크들에서는 별도의 모델 없이 내장된 머신러닝 기능을 사용할 수 있는데, 그 중 하나인 텍스트 인식을 사용하여 간단한 앱을 만들어 보려 한다.
사용해 볼 API는 Vision 프레임워크의 VRRecognizeTextRequest이다.
먼저 사진이 표시될 UIImageView와 인식한 텍스트를 나타낼 UILabel을 화면에 표시해준다.

이제 recognizeText라는 메서드를 만들어보자. 이 메서드는 UIImage를 받아 텍스트 인식을 수행한다.
private func recognizeText(image: UIImage?) {
guard let cgImage = image?.cgImage else { return }
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
...
}
먼저 요청을 수행할 VNImageRequestHandler를 정의하고, 해당 요청의 대상이 되는 cgImage를 결정한다.

이제 실제 텍스트 인식을 수행하는 요청인 VNRecognizeTextRequest 타입을 생성하고, Completion Handler 내부에서 결과를 우리가 사용할 타입인 VRRecognizedTextObservation으로 타입캐스팅한다. 그 후 Label에 들어갈 text로 변환하기 위해서 각 Observation의 topCandidate를 하나씩 빼서 하나로 합친다.
let request = VNRecognizeTextRequest { [weak self] request, error in
guard let observations = request.results as? [VNRecognizedTextObservation], error == nil else {
return
}
let text = observations.compactMap({
$0.topCandidates(1).first?.string
}).joined(separator: ", ")
}
자 이제 이 메서드를 실행해주면?

위와 같이 인식이 잘 되는것을 확인할 수 있다! 눈으로 보기 힘든 작은 글자까지도 모두 인식하고, 정확도도 높다. 위에서 구분자를 , 로 설정했기에 각 Observation의 단위가 어떻게 되는지도 확인할 수 있다.
전체 코드
private func recognizeText(image: UIImage?) {
guard let cgImage = image?.cgImage else { return }
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
let request = VNRecognizeTextRequest { [weak self] request, error in
guard let observations = request.results as? [VNRecognizedTextObservation], error == nil else {
return
}
let text = observations.compactMap { $0.topCandidates(1).first?.string }.joined(separator: ", ")
DispatchQueue.main.async {
self?.label.text = text
}
}
do {
try handler.perform([request])
} catch {
print(error)
}
}CoreML의 맛보기로 기본 API를 사용해 봤는데, 다음 포스팅으로는 CoreML의 모델을 사용해서 앱을 만드는 실습을 진행해 보려한다.