Добавьте эффект привязки к видео в реальном времени, основанный на отслеживании лиц пользователей в режиме реального времени в Swift

#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()