前段時間研究人臉識別,正好也在學習swift,所以真好都總結一下。
步驟;
- 創(chuàng)建特征檢測器CIDetector,檢測類型人臉,高精度。
- 調用檢測器的featuresInImage方法,傳入圖片,會得到一個人臉的數(shù)組。
- 遍歷人臉數(shù)組,轉為CIFaceFeature類型,并根據(jù)其各個特征點進行操作,比如人臉,眼睛等位置。
下面是我的demo,就一個imageView和一個按鈕,點擊按鈕開始檢測,檢測到人臉后,在臉上加一個紅色的框。
檢測前:
image.png
檢測后
image.png
看一下,點擊檢測按鈕做了什么:
@IBAction func detect(_ sender: Any) {
// 取出照片并將其轉換為CIImage,使用Core Image時需要用CIImage
guard let picture = CIImage(image: pictureView.image!) else {
return
}
// 選擇高精度
let accuracy = [CIDetectorAccuracy:CIDetectorAccuracyHigh]
// 這里定義了一個屬于CIDetector類的faceDetector變量,并輸入之前創(chuàng)建的accuracy變量
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
// 調用faceDetector的featuresInImage方法,識別器會找到所給圖像中的人臉,最后返回一個人臉數(shù)組
let faces = faceDetector?.features(in: picture)
// 計算轉換坐標系的transform(這里取出來的size是圖片的原始尺寸)
let ciImageSize = picture.extent.size
var transform = CGAffineTransform(scaleX: 1, y: -1)
transform = transform.translatedBy(x: 0, y: -ciImageSize.height)
// 遍歷faces數(shù)組,把人臉數(shù)據(jù)轉換為CIFaceFeature類型
for face in faces as! [CIFaceFeature] {
print("發(fā)現(xiàn)人臉坐標= \(face.bounds)")
// 通過上邊transform轉換face的坐標
var faceViewBounds = face.bounds.applying(transform)
// 由于圖片的寬高比例可能會隨著容器pictureView的zize而被壓縮或者拉伸,這里計算框框在pictureView中的實際大小和位置
let viewSize = pictureView.bounds.size
let scale = min(viewSize.width / ciImageSize.width, viewSize.height / ciImageSize.height)
let offsetX = (viewSize.width - ciImageSize.width * scale) / 2
let offsetY = (viewSize.height - ciImageSize.height * scale) / 2
faceViewBounds = faceViewBounds.applying(CGAffineTransform(scaleX: scale, y: scale))
faceViewBounds.origin.x += offsetX
faceViewBounds.origin.y += offsetY
// 在人臉上畫個框
let faceCase = UIView(frame: faceViewBounds)
faceCase.layer.borderWidth = 3
faceCase.layer.borderColor = UIColor.red.cgColor
faceCase.backgroundColor = UIColor.clear
pictureView.addSubview(faceCase)
print("轉換后人臉坐標= \(faceCase.frame)")
if face.hasLeftEyePosition {
print("左眼位置=\(face.leftEyePosition)")
}
if face.hasRightEyePosition {
print("右眼位置=\(face.rightEyePosition)")
}
if face.hasMouthPosition {
print("檢測到嘴巴=\(face.mouthPosition)")
}
if face.hasFaceAngle {
print("人臉旋轉角度=\(face.faceAngle)")
}
}
}
image.png
坐標轉換
其中涉及到一個UIKit和CoreImage的坐標轉換,UIKit的坐標是左上角為頂點(0,0)向右下方展開,而CoreImage是以左下角為頂點(0,0)向右上方展開的,如圖所示:
image.png
由于取出來的CIImage圖片是原始尺寸,但是圖片真實顯示出來的size受到容器的限制,可能拉伸或者壓縮,所以坐標轉換后還需要根據(jù)比例來計算出人臉實際顯示的大小,然后再加框框。
總結
還有些特征點可以檢測,但是我試了一下,不是特別好使,總是檢測不到,比如微笑和閉眼的狀態(tài),如果你發(fā)現(xiàn)了問題所在,請告訴我,謝謝。
參考文章