項目地址
鏈接:http://pan.baidu.com/s/1miKdwFI
密碼:kow2
總體思路:
1、從相冊選擇帶人臉的一張圖
2、識別出有幾個人
3、根據識別出來的特徵來描繪人臉特徵 (畫圖)
識別效果
代碼實戰
STEP1 從相冊取出圖
extension ViewController : UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func chooseImage() {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .savedPhotosAlbum
present(picker, animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let uiImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("no image selected")
}
self.buttonOriginalImage.setBackgroundImage(uiImage, for: .normal)
self.processImage(image: uiImage)
}
}
STEP2 得到人臉數目
func preformRequestForFaceLandmarks(image: UIImage) {
selectedImage = image
self.resultLabel.text = "相片處理中。。。"
let handler = VNImageRequestHandler(cgImage: image.cgImage!, options: [:])
do {
let request = VNDetectFaceLandmarksRequest(completionHandler: handleFaceLandmarksDetection)
try handler.perform([request])
} catch {
print(error)
}
}
func handleFaceLandmarksDetection(request: VNRequest, error: Error?){
guard let observations = request.results as? [VNFaceObservation] else {
fatalError("could not get results from request")
}
self.resultLabel.text = "found \(observations.count) faces"
}
STEP3 得到人臉的特徵點
func addFaceFeature(forObservation face: VNFaceObservation, toView view: UIView) ->[VNFaceLandmarkRegion2D]{
// 找到所有的面部特徵 眼睛鼻子嘴巴。。。。
// 把他們畫出來
guard let landmarks = face.landmarks else { return [] }
var landmarkRegions: [VNFaceLandmarkRegion2D] = []
if let faceContour = landmarks.faceContour {
landmarkRegions.append(faceContour)
}
if let leftEye = landmarks.leftEye {
landmarkRegions.append(leftEye)
}
if let rightEye = landmarks.rightEye {
landmarkRegions.append(rightEye)
}
if let nose = landmarks.nose {
landmarkRegions.append(nose)
}
if let innerLips = landmarks.innerLips {
landmarkRegions.append(innerLips)
}
if let noesCrest = landmarks.noseCrest {
landmarkRegions.append(noesCrest)
}
if let medianLine = landmarks.medianLine {
landmarkRegions.append(medianLine)
}
if let outLips = landmarks.outerLips {
landmarkRegions.append(outLips)
}
if let lefEyebrow = landmarks.leftEyebrow {
landmarkRegions.append(lefEyebrow)
}
if let rightEyebrow = landmarks.rightEyebrow {
landmarkRegions.append(rightEyebrow)
}
return landmarkRegions
}
STEP4 把點畫成圖
func drawOnImage(source: UIImage,boundingRect: CGRect,faceLandmarkRegions: [VNFaceLandmarkRegion2D]) -> UIImage {
UIGraphicsBeginImageContextWithOptions(source.size, false, 1)
let context = UIGraphicsGetCurrentContext()!
context.translateBy(x: 0, y: source.size.height)
context.scaleBy(x: 1.0, y: -1.0)
// context.setBlendMode(CGBlendMode.colorBurn)
context.setBlendMode(CGBlendMode.colorDodge)
context.setLineJoin(.round)
context.setLineCap(.round)
context.setShouldAntialias(true)
context.setAllowsAntialiasing(true)
let rectWidth = source.size.width * boundingRect.size.width
let rectHeight = source.size.height * boundingRect.size.height
// ERROR
// let rect = CGRect(x: 0, y: 0, width: rectWidth, height: rectHeight)
let rect = CGRect(x: 0, y: 0, width: source.size.width, height: source.size.height)
context.draw(source.cgImage!, in: rect)
var fillColor = UIColor.green
fillColor.setFill()
context.addRect(CGRect(x: boundingRect.origin.x * source.size.width, y:boundingRect.origin.y * source.size.height, width: rectWidth, height: rectHeight))
context.drawPath(using: CGPathDrawingMode.stroke)
//draw overlay
fillColor = UIColor.blue
fillColor.setStroke()
context.setLineWidth(8.0)
for faceLandmarkRegion in faceLandmarkRegions {
var points: [CGPoint] = []
for i in 0..<faceLandmarkRegion.pointCount {
let point = faceLandmarkRegion.normalizedPoints[i]
let p = CGPoint(x: CGFloat(point.x), y: CGFloat(point.y))
points.append(p)
}
let mappedPoints = points.map { CGPoint(x: boundingRect.origin.x * source.size.width + $0.x * rectWidth, y: boundingRect.origin.y * source.size.height + $0.y * rectHeight) }
context.addLines(between: mappedPoints)
context.drawPath(using: CGPathDrawingMode.stroke)
}
let coloredImg : UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return coloredImg
}