2017-07-09 51 views
7

我使用ios 11視覺框架實時生成臉部地標點。我能夠獲得人臉標誌點,並將相機圖層與人臉標誌點的UIBezier路徑疊加。但是,我想獲得類似右下圖的內容。目前我有一些看起來像左圖的東西,我嘗試循環遍歷點並添加中點,但我不知道如何從點生成所有這些三角形。我將如何從左側的點生成右側的地圖?Swift 4:如何使用ios11視覺框架從臉部地標點創建臉部地圖

我不確定我能否滿足所有要點,並不是說它會幫助太大,但我也從整個臉部的邊界框中獲得了點數。最後,是否有任何框架可以讓我認識到我需要的所有要點,比如openCV或其他,請讓我知道。謝謝!

face_map

這裏是我已經從https://github.com/DroidsOnRoids/VisionFaceDetection使用的代碼:

func detectLandmarks(on image: CIImage) { 
    try? faceLandmarksDetectionRequest.perform([faceLandmarks], on: image) 
    if let landmarksResults = faceLandmarks.results as? [VNFaceObservation] { 

     for observation in landmarksResults { 

      DispatchQueue.main.async { 
       if let boundingBox = self.faceLandmarks.inputFaceObservations?.first?.boundingBox { 
        let faceBoundingBox = boundingBox.scaled(to: self.view.bounds.size) 
        //different types of landmarks 



        let faceContour = observation.landmarks?.faceContour 
        self.convertPointsForFace(faceContour, faceBoundingBox) 

        let leftEye = observation.landmarks?.leftEye 
        self.convertPointsForFace(leftEye, faceBoundingBox) 

        let rightEye = observation.landmarks?.rightEye 
        self.convertPointsForFace(rightEye, faceBoundingBox) 

        let leftPupil = observation.landmarks?.leftPupil 
        self.convertPointsForFace(leftPupil, faceBoundingBox) 

        let rightPupil = observation.landmarks?.rightPupil 
        self.convertPointsForFace(rightPupil, faceBoundingBox) 

        let nose = observation.landmarks?.nose 
        self.convertPointsForFace(nose, faceBoundingBox) 

        let lips = observation.landmarks?.innerLips 
        self.convertPointsForFace(lips, faceBoundingBox) 

        let leftEyebrow = observation.landmarks?.leftEyebrow 
        self.convertPointsForFace(leftEyebrow, faceBoundingBox) 

        let rightEyebrow = observation.landmarks?.rightEyebrow 
        self.convertPointsForFace(rightEyebrow, faceBoundingBox) 

        let noseCrest = observation.landmarks?.noseCrest 
        self.convertPointsForFace(noseCrest, faceBoundingBox) 

        let outerLips = observation.landmarks?.outerLips 
        self.convertPointsForFace(outerLips, faceBoundingBox) 
       } 
      } 
     } 
    } 

} 

func convertPointsForFace(_ landmark: VNFaceLandmarkRegion2D?, _ boundingBox: CGRect) { 
    if let points = landmark?.points, let count = landmark?.pointCount { 
     let convertedPoints = convert(points, with: count) 



     let faceLandmarkPoints = convertedPoints.map { (point: (x: CGFloat, y: CGFloat)) -> (x: CGFloat, y: CGFloat) in 
      let pointX = point.x * boundingBox.width + boundingBox.origin.x 
      let pointY = point.y * boundingBox.height + boundingBox.origin.y 

      return (x: pointX, y: pointY) 
     } 

     DispatchQueue.main.async { 
      self.draw(points: faceLandmarkPoints) 
     } 
    } 
} 


func draw(points: [(x: CGFloat, y: CGFloat)]) { 
    let newLayer = CAShapeLayer() 
    newLayer.strokeColor = UIColor.blue.cgColor 
    newLayer.lineWidth = 4.0 

    let path = UIBezierPath() 
    path.move(to: CGPoint(x: points[0].x, y: points[0].y)) 
    for i in 0..<points.count - 1 { 
     let point = CGPoint(x: points[i].x, y: points[i].y) 
     path.addLine(to: point) 
     path.move(to: point) 
    } 
    path.addLine(to: CGPoint(x: points[0].x, y: points[0].y)) 
    newLayer.path = path.cgPath 

    shapeLayer.addSublayer(newLayer) 
} 
+1

不是輕浮,但是什麼讓你認爲你*可以*?只要看額頭,就可以檢測到*零*點(從我的測試中可以得知),但你認爲你可以*十八個三角形? – dfd

+0

@dfd我已更新我的問題以反映您的問題。 – Ali

+1

充其量,邊界框會給你4點以上。我一直在玩這個GitHub的臉部細節(https://github.com/artemnovichkov/iOS-11-by-Examples),而且我用的頭髮每張臉都沒有額頭。一些想法,可能沒有太大的幫助:(1)最好的OpenCV/OpenGL,或者CoreImage/CoreGraphics,你可以用某種方式來分析事物,以便通過顏色來破解發際線和/或顴骨。但是那做了很多假設,包括沒有劉海或長髮,以及適當的照明。 (2)另一種可能性是機器學習 - 培訓你自己的模型並使用CoreML。 – dfd

回答

2

我確實最終找到了一個可行的解決方案。我通過https://github.com/AlexLittlejohn/DelaunaySwift使用了delaunay三角剖分,並將其修改爲與通過視覺框架的人臉標誌檢測請求生成的點一起工作。這不是一個簡單的代碼片段解釋,所以我已經鏈接我的github回購下面顯示我的解決方案。請注意,這不會從額頭獲得點數,因爲視覺框架只能從眉毛中獲得點數。

https://github.com/ahashim1/Face

+0

的下方看到我的回答你有沒有想過爲什麼面具會滯後於輸入框?如果你指向正確的方向,我可以玩弄它並製作一個公關。 –

+1

@AdityaGarg我認爲這是因爲面部標記請求是異步完成的,而三角形繪製在主線程上。不太清楚如何完成同步過程。祝你好運 – Ali

0

你想在右邊的圖像中什麼是Candide網。你需要將這些點映射到網格,這就是它。我不認爲你需要去評論中討論過的路線。

P.S我發現Candide時,通過一個着名的過濾器應用程序的APK內容(讓我想起casper) - 還沒有時間自己嘗試一下。