얼굴인식 사용하기
얼굴 인식 기능 실습
얼굴 인식 기능은 Vision framework 를 사용한다.
import Vision
vision Framework
여러 명의 얼굴을 인식할 수 있는 이미지를 준비한 뒤, 이미지를 분석할 analyzeImage 함수를 정의한다
func analyzeImage(image: UIImage) {
let handler = VNImageRequestHandler(cgImage: image.cgImage!, options: [:])
let request = VNDetectFaceRectanglesRequest(completionHandler: handleFaceRecognition)
try! handler.perform([request])
}
func handleFaceRecognition(request: VNRequest, error: Error?) {
guard let foundFaces = request.results as? [VNFaceObservation] else {
fatalError("Can't find a face in the picture")
}
message = "Found \(foundFaces.count) faces in the picture"
}
얼굴 인식
VNImageRequestHandler
An object that processes one or more image analysis requests pertaining to a single image.
VNImageRequestHandler에는 core graphics Image, 줄여서 cgImage라는 싱글 이미지를 파라미터로 받는다. 그렇기 때문에 UIImage를 CGImage로 변환하여 VNImageRequestHandler를 초기화 한다.
이를 통해 단일 이미지를 Vision 프레임워크에 요청을 수행할 수 있는 핸들러를 인스턴스화할 수 있다.
그리고 이미지 안에 있는 페이스를 찾기 위한 요청(얼굴인식)인 VNDetectFaceRectanglesRequest를 초기화 한다. 얼굴 인식 작업 자체는 시간이 꽤 걸리는 작업이기에, 콜백함수. completionHandler 파라미터로 handleFaceRecognition 을 전달하는 것이다.
(handleFaceRecognition 함수는 얼굴 인식 작업이 완료된 후에 호출되는 클로저로, 즉시 실행되는 것이 아니라 비동기적으로 실행.)
그리고 아까 초기화한 handleFaceRecognition를 호출한다
요약
analyzeImage 함수 호출: UIImage 객체를 전달받아 시작.
핸들러 및 요청 객체 생성: VNImageRequestHandler와 VNDetectFaceRectanglesRequest 객체를 생성.
얼굴 인식 요청 수행: handler.perform([request])를 호출하여 비동기적으로 얼굴 인식 작업 시작.
얼굴 인식 작업 완료: 얼굴 인식 작업이 백그라운드에서 완료되면 handleFaceRecognition 함수가 호출됨.
결과 처리: handleFaceRecognition 함수에서 인식된 얼굴 수를 확인하고 메시지로 저장.
func perform(_ requests: [VNRequest]) throws
얼굴에 강조, 표시 기능 추가(드로잉)
인식한 얼굴에 드로잉을 추가해보겠다.
VNDetectFaceLandmarksRequest 를 사용.
func analyzeImage(image: UIImage) {
let handler = VNImageRequestHandler(cgImage: image.cgImage!, options: [:])
let request = VNDetectFaceLandmarksRequest(completionHandler: handleFaceRecognition)
try! handler.perform([request])
}
func handleFaceRecognition(request: VNRequest, error: Error?) {
guard let foundFaces = request.results as? [VNFaceObservation] else {
fatalError("Can't find a face in the picture")
}
message = "Found \(foundFaces.count) faces in the picture"
guard let image = UIImage(named: photoArray[arrayIndex]) else { return }
// 이미지 생성을 위한 컨텍스트 시작
UIGraphicsBeginImageContextWithOptions(image.size, false, 0.0)
// 컨텍스트 변수 가져오기
let context = UIGraphicsGetCurrentContext()!
// 컨텍스트 내에 이미지 그리기
image.draw(in: CGRect(origin: .zero, size: image.size))
// 이미지를 그린 후 좌표계를 변환합니다.
context.translateBy(x: 0, y: image.size.height)
context.scaleBy(x: 1.0, y: -1.0)
// 얼굴 주변 사각형을 그리기 위한 선 색상과 두께 설정
context.setStrokeColor(UIColor.red.cgColor)
context.setLineWidth(10)
for faceObservation in foundFaces {
// 정규화 된 얼굴 인식 위치값(CGRect) 가져오기
let faceRect = VNImageRectForNormalizedRect(faceObservation.boundingBox, Int(image.size.width), Int(image.size.height))
// 가져온 위치에 테두리 그리기
context.stroke(faceRect)
}
// 컨텍스트를 종료하고, 컨텍스트 결과를 이미지 변수에 할당
let newImage = UIGraphicsGetImageFromCurrentImageContext()
// 커밋 (위의 컨텍스트 명령을 실행함)
UIGraphicsEndImageContext()
// 만들어진 이미지를 화면에 출력
analyzedImage = newImage
}
위 코드에서 핵심은, 이미지를 그린 후 좌표계를 변환한 시점 부터의 코드다.
context에는 각각의 얼굴의 위치를 가지고 있는데, 여기에 setStrokeColor나 setLineWidth로 라인을 그려줄 수 있을 것이다.
실행결과
시뮬레이터나 프리뷰에서는 facial Recognition이 되지 않고, 실제 기기에서 테스트해볼 수 있다.