J'utilise le framework de vision iOS 11 pour générer les points de repère du visage en temps réel. Je peux obtenir les points de repère du visage et superposer le calque de caméra avec le chemin UIBezierPath des points de repère du visage. Cependant, j'aimerais obtenir quelque chose comme l'image en bas à droite. Actuellement, j'ai quelque chose qui ressemble à l'image de gauche et j'ai essayé de faire une boucle entre les points et d'ajouter des points médians, mais je ne sais pas comment générer tous ces triangles à partir des points. Comment pourrais-je générer la carte à droite à partir des points à gauche?
Je ne suis pas sûr de pouvoir le faire avec tous les points que j'ai, non pas que cela aide beaucoup, mais j'ai aussi des points dans la boîte de sélection de tout le visage. Enfin, existe-t-il un cadre qui me permettrait de reconnaître tous les points dont j'ai besoin, tels que openCV ou autre chose, faites-le-moi savoir. Merci!
Voici le code que j'utilise depuis 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)
}
J'ai fini par trouver une solution qui fonctionne. J'ai utilisé la triangulation de delaunay via https://github.com/AlexLittlejohn/DelaunaySwift , et je l'ai modifiée pour utiliser les points générés via la demande de détection de points de repère du visage de la structure de vision. Cela n’est pas facile à expliquer avec un extrait de code, j’ai donc lié mon dépôt github ci-dessous qui montre ma solution. Notez que cela ne prend pas les points du front, car la structure de vision ne les obtient que des sourcils.
Ce que vous voulez dans l'image de droite est un Candide mesh. Vous devez mapper ces points sur le maillage et ce sera tout. Je ne pense pas que vous deviez suivre la voie qui a été discutée dans les commentaires.
P.S J'ai trouvé Candide en parcourant le contenu APK d'une célèbre application filtres (ça me rappelle Casper) - je n'ai pas encore eu le temps de l'essayer moi-même.