#swift #face-detection #apple-vision
#swift #распознавание лиц #apple-видение
Вопрос:
Я хочу добавить эффект привязки к видео в реальном времени, основанный на отслеживании лиц пользователей в режиме реального времени. Мой дизайн хотел бы разместить потоки частиц, исходящие от бровей, глаз или губ. У меня уже есть гибкая библиотека эффектов, которая может размещать нужные потоки в любых выбранных точках экрана, которые могут обновляться в режиме реального времени.
Apple предоставляет демонстрационный проект Swift, который я скачал по этой ссылке:https://developer.apple.com/documentation/vision/tracking_the_user_s_face_in_real_time
Если вы загрузите и запустите этот проект без каких-либо изменений, он покажет вам наложение, содержащее ориентиры лица, такие как левая и правая брови, глаза, нос, губы и т.д., Которые отслеживают лицо человека в режиме реального времени.
Там было не так много документации по системе координат, рисованию слоев и т.д. чтобы я мог извлекать значения CGPoint, которые соответствовали бы ориентирам лица, таким как точки на левой брови, например.
Я добился некоторого прогресса в анализе кода чертежа, используемого в демо-версии Apple, но добился лишь ограниченного успеха в получении желаемых координат.
Левая бровь, по-видимому, состоит из массива из 6 точек на контуре, соединенных линиями. Я просто хотел бы получить CGPoint, который указывает текущее местоположение одной из точек на левой брови.
Apple предоставляет процедуру под названием addPoints.
addPoints вызывается как для открытых, так и для закрытых ориентиров.
Эта процедура вызывается для каждого ориентира лица. Поскольку бровь не является замкнутым контуром , она соответствует этому типу : openLandmarkRegions . Рот и глаза соответствуют немного другому типу, closedLandmarkRegions, поскольку они представляют собой замкнутые пути, где начальная и конечная точки одинаковы.
fileprivate func addPoints(in landmarkRegion: VNFaceLandmarkRegion2D, to path: CGMutablePath, applying affineTransform: CGAffineTransform, closingWhenComplete closePath: Bool)
На самом деле не имеет значения, открыт путь или закрыт. Все, о чем я забочусь, — это получить действительную точку CG на любом из ориентиров. В конце концов, у меня будут некоторые эффекты и для глаз и для рта, как только я выясню, как получить действительную точку CG только для одного из ориентиров лица.
Это то, что я пробовал. Я объявил некоторые глобальные переменные и добавил некоторую логику в код рисования Apple, чтобы попытаться помочь выделить точки CG на левой брови.
var sampleLeftEyebrowPoint = false
var mostRecentLeftEyebrowPoint = CGPoint()
Поскольку addPoints вызывается для циклов по всем ориентирам, мне пришлось попытаться выбрать цикл, соответствующий левой брови.
В addPoints у Apple есть эта строка кода, в которой они используют точки на любом заданном ориентире :
let points: [CGPoint] = landmarkRegion.normalizedPoints
Я добавил этот фрагмент кода сразу после этой строки кода :
if sampleLeftEyebrowPoint
{
mostRecentLeftEyebrowPoint = points[1]
mostRecentLeftEyebrowPoint = mostRecentLeftEyebrowPoint.applying(affineTransform)
sampleLeftEyebrowPoint = false
}
Обратите внимание, что точки [1] — это 2-я точка на брови, которая является одной из средних точек.
Обратите внимание, что я применяю то же аффинное преобразование к единственной точке, которое Apple применяет в своей логике.
Я установил sampleLeftEyebrowPoint в значение true в этой процедуре Apple с некоторой логикой, которая определяет, зацикливается ли левая бровь в данный момент :
fileprivate func addIndicators(to faceRectanglePath: CGMutablePath, faceLandmarksPath: CGMutablePath, for faceObservation: VNFaceObservation)
В этой процедуре Apple выполняет цикл for для открытых ориентиров, как показано ниже. Я добавил некоторую логику для установки sampleLeftEyebrowPoint, чтобы логика в addPoints распознала, что левая бровь в настоящее время находится в работе, чтобы она могла установить.
for openLandmarkRegion in openLandmarkRegions where openLandmarkRegion != nil {
if openLandmarkRegion == landmarks.leftEyebrow
{
sampleLeftEyebrowPoint = true
}
Самая недавняя точка броска, которую я получаю, похоже, несколько соответствует моей желаемой точке CG, но не полностью. Кажется, что координата X отслеживается, но требует некоторого масштабирования. Но координата Y кажется инвертированной, возможно, происходит что-то еще.
Может ли кто-нибудь предоставить процедуру, которая даст мне желаемую CGPoint, соответствующую mostRecentLeftEyebrowPoint?
Как только у меня это получится, я уже выяснил, как скрыть ориентиры лица, чтобы был виден только мой эффект, и мой эффект будет отслеживать левую бровь в режиме реального времени. Чтобы скрыть отображаемые строки распознавания лиц, просто закомментируйте вызов Apple в :
// self.updateLayerGeometry()