Разработка приложения, используя SDK Анализ лица (мимики)
Шаг 2
На втором шаге конфигурируется интерфейс PXCFaceAnalysis. Приложение перечисляет поддерживаемые конфигурации, используя функцию QueryProfile. Каждый профиль описывает поддерживаемые конфигурации. Приложение устанавливает желаемые конфигурационные параметры используя функцию SetProfile.
// Configure the face analysis interface PXCFaceAnalysis::ProfileInfo faInfo; faceAnalyzer->QueryProfile(0, &faInfo); faceAnalyzer->SetProfile(&faInfo);5. Конфигурация интерфейса анализа лица
Профиль "0" - это первый профиль и обычно профиль интерфейса по умолчанию. PXCFaceAnalysis::ProfileInfo представляет информацию с видео потока и основных параметров, которые являются общими для различных модулей анализа лица (обнаружения, контрольных точек и т.д.). Так после QueryProfile устройство захвата и видео поток могут быть сконфигурированы для процедур анализа лица согласно перечисленным PXCFaceAnalysis::ProfileInfo. Следовательно, конфигурации интерфейса PXCFaceAnalysis и устройства захвата должны быть установлены совместно, как следующие:
// Configure the face analysis interface PXCFaceAnalysis::ProfileInfo faInfo; faceAnalyzer->QueryProfile(0, &faInfo); // Find capture device UtilCaptureFile capture(session,0,0); capture.LocateStreams(&faInfo.inputs); // Set the face analysis interface faceAnalyzer->SetProfile(&faInfo);6. Установка конфигураций интерфейса PXCFaceAnalysis и устройства захвата
Здесь инструмент UtilCaptureFile используется для упрощенного подхода применения устройства захвата и установки соответствующего захватываемого потока.
Шаг 3
Теперь в приложении необходимо отдельно сконфигурировать несколько или все модули анализа, например, такие как обнаружение лица и его контрольных точек, или другие применяемые модули анализа лица. Процедуры конфигурации этих модулей похожи. Так например, для конфигурирования обнаружения лица приложение получает определяющий интерфейс от интерфейса PXCFaceAnalysis используя функцию DynamicCast и затем вызывает функции QueryProfile и SetProfile.
// Configure the face detector interface PXCFaceAnalysis::Detection *faceDetector; faceDetector=faceAnalyzer->DynamicCast<PXCFaceAnalysis::Detection>(); // Set the face detector profile PXCFaceAnalysis::Detection::ProfileInfo dInfo={0}; faceDetector->QueryProfile(0, &dInfo); faceDetector->SetProfile(&dInfo);7. Конфигурация интерфейса и установка профиля определения
The PXCFaceAnalysis::Detection::ProfileInfo описывает поддерживаемые углы обзора алгоритма обнаружения. По умолчанию ViewAngle установлен как VIEW_ANGLE_MULTI, что эквивалентно углам обзора 0, 45, 135 и 180 градусов и фронтальному положению камеры. Похожие шаги используются для конфигурации модуля обнаружения контрольных точек лица.
// Configure the face detector interface PXCFaceAnalysis::Landmark *landmarkDetector; landmarkDetector=faceAnalyzer->DynamicCast<PXCFaceAnalysis::Landmark>(); // Set the face landmark detector profile PXCFaceAnalysis::Landmark::ProfileInfo lInfo={0}; landmarkDetector->QueryProfile(1, &lInfo); landmarkDetector->SetProfile(&lInfo);8. Конфигурация интерфейса и установка профиля определения контрольных точек лица
Установка количества контрольных точек (7 или 8) определяется в QueryProfile как 0 или 1 соответственно.
Шаг 4
Приложение выполняет анализа лица, вызывая функцию ProcessImageAsync. Если анализируемое лицо находится на неподвижном изображении, приложение предоставляет изображение на входе. Если анализируемое лицо находится на видеоряде, приложение передает один видео кадр за раз в основной цикл. ProcessImageAsync функция возвращает SP, которое приложение может синхронизировать перед получением результатов анализа.
PXCSmartArray<PXCImage> images; // declare image interface PXCSmartSPArray sps(2); //declare Sync points for asynchronous execution // Read frame pxcStatus sts = capture.ReadStreamAsync(images,&sps[0]); // Process frame using face detection sts = faceAnalyzer->ProcessImageAsync(images, &sps[1]); if (sts<PXC_STATUS_NO_ERROR) break; // Synchronize both sync points sts = sps.SynchronizeEx(); if (sps[0]->Synchronize(0)<PXC_STATUS_NO_ERROR) break; // test for EOF9. Анализ лица
Для каждого полученного фрейма выполняется асинхронный конвейер, который состоит из чтения фреймов и затем обрабатывается текущий фрейм используя любой из конфигурируемых алгоритмов анализа лица. Следует отметить, что ничего не обрабатывается в асинхронном конвейер пока Sync Points синхронизируется вызывая функцию SynchronizeEx.
Шаг 5
Для нахождения результатов обнаружения лица приложению необходимо использовать функцию QueryData в интерфейсе обнаружения. QueryFace вызывается в первую очередь для перечисления всех определенных лиц в течении обработки анализа лица.
for (int fidx = 0; ; fidx++) { pxcUID fid = 0; pxcU64 timeStamp = 0; sts = faceAnalyzer->QueryFace(fidx, &fid, &timeStamp); if (sts < PXC_STATUS_NO_ERROR) break; // no more faces detected PXCFaceAnalysis::Detection::Data face_data; faceDetector->QueryData(fid, &face_data); }10. Вывода результатов обнаружения лица
Для нахождения результатов определения контрольных точек лица приложению необходимо передать QueryData для меток в уже установленном профиле.
for (int fidx = 0; ; fidx++) { pxcUID fid = 0; pxcU64 timeStamp = 0; sts = faceAnalyzer->QueryFace(fidx, &fid, &timeStamp); if (sts < PXC_STATUS_NO_ERROR) break; // no more faces detected PXCFaceAnalysis::Landmark::ProfileInfo lInfo={0}; landmark->QueryProfile(&lInfo); PXCFaceAnalysis::Landmark::LandmarkData data[7]; pxcStatus sts=landmark->QueryLandmarkData(fid,lInfo.labels,&data[0]); }11. Выводов результатов обнаружения контрольных точек лица
Общий код программы по обнаружению лица и его контрольных точек.
#include "pxcsession.h" #include "pxccapture.h" #include "pxcsmartptr.h" #include "face_render.h" #include "util_capture_file.h" #include "util_cmdline.h" #include "pxcface.h" int wmain(int argc, wchar_t* argv[]) { // Create a session PXCSmartPtr<PXCSession> session; pxcStatus sts=PXCSession_Create(&session); if (sts<PXC_STATUS_NO_ERROR) { wprintf_s(L"Failed to create the SDK session\n"); return 3; } UtilCmdLine cmdl(session); if (!cmdl.Parse(L"-sdname-nframes-file-record",argc,argv)) return 3; // Init Face analyzer PXCSmartPtr<PXCFaceAnalysis> faceAnalyzer; sts=session->CreateImpl(cmdl.m_iuid, PXCFaceAnalysis::CUID, (void**)&faceAnalyzer); if (sts<PXC_STATUS_NO_ERROR) { wprintf_s(L"Failed to locate a face module"); return 3; } // Retrieve the input requirements PXCFaceAnalysis::ProfileInfo faInfo; faceAnalyzer->QueryProfile(0, &faInfo); // Find capture device UtilCaptureFile capture(session,cmdl.m_recordedFile,cmdl.m_bRecord); if (cmdl.m_sdname) capture.SetFilter(cmdl.m_sdname); /*L"Integrated Camera"*/ sts=capture.LocateStreams(&faInfo.inputs); if (sts<PXC_STATUS_NO_ERROR) { wprintf_s(L"Failed to locate an input device that matches input for face analysis\n"); return 3; } faceAnalyzer->SetProfile(&faInfo); // Create detector instance PXCFaceAnalysis::Detection *faceDetector=faceAnalyzer->DynamicCast<PXCFaceAnalysis::Detection>(); if (!faceDetector) { wprintf_s(L"Failed to locate the face detection functionality\n"); return 3; } // Create landmark instance PXCFaceAnalysis::Landmark *landmarkDetector=landmarkDetector=faceAnalyzer->DynamicCast<PXCFaceAnalysis::Landmark>(); if (!landmarkDetector) { wprintf_s(L"Failed to locate the face landmark functionality\n"); return 3; } // Set landmark profile PXCFaceAnalysis::Landmark::ProfileInfo lInfo={0}; landmarkDetector->QueryProfile(0, &lInfo); landmarkDetector->SetProfile(&lInfo); // Create Renderer PXCSmartPtr<FaceRender> faceRender(new FaceRender(L"Landmark Detection Sample")); int fnum; for (fnum=0;fnum<cmdl.m_nframes;fnum++) { PXCSmartArray<PXCImage> images; PXCSmartSPArray sps(2); ///* read and process frame */ sts = capture.ReadStreamAsync(images,&sps[0]); if (sts<PXC_STATUS_NO_ERROR) break; // EOF sts = faceAnalyzer->ProcessImageAsync(images, &sps[1]); sts = sps.SynchronizeEx(); if (sps[0]->Synchronize(0)<PXC_STATUS_NO_ERROR) break; // EOF // loop all faces faceRender->ClearData(); for (int fidx = 0; ; fidx++) { pxcUID fid = 0; pxcU64 timeStamp = 0; sts = faceAnalyzer->QueryFace(fidx, &fid, &timeStamp); if (sts < PXC_STATUS_NO_ERROR) break; // no more faces // Query face detection results PXCFaceAnalysis::Detection::Data face_data; faceDetector->QueryData(fid, &face_data); faceRender->SetDetectionData(&face_data); // Query landmark points faceRender->SetLandmarkData(landmarkDetector, fid); faceRender->PrintLandmarkData(landmarkDetector, fid); wprintf_s(L"timestamp=%I64d, frame=%d\n", timeStamp, fnum); } if (!faceRender->RenderFrame(images[0])) break; } return 0; }