A photograph of a road and rail line Between Hapuku and Mangamaunu, South Island, New Zealand

An incomplete, rough and ready guide to building, initial port, and installation of Face Analysis SDK for Windows. The original source requires a few rather specific dependencies and uses a POSIX compliant fork/process model. The solution below is nothing other than a rough hack to get this stuff running under windows and I'm certain that my direct translation of POSIX fork() with Win32 CreateProcess() is suboptimal to say the least. To be clear, this is your starting point, not the final solution!

This guide has been written in respose to a question I received on youtube about porting the code. NOTE: Whilst the face analysis SDK is open source and the code is freely available to read/use, my personal work is not and I therefore can not share the modified (ported) code base. I can however give an outline of the process needed to start your own port and a bit of code to help you get it done. This is what I have detailed below and if it happens to help someone else in the future then great.

Face Analysis SDK by CSIRO Computer Vision Lab



TL;DR

Just give me the code: GitHub

Dependencies

  • Qt 4.x source and build it (yep, it needs to be built from source as there are some bits of functionality not included in the binary). I used Qt4.8.3.
  • mingw-gcc440 (yep, it must be this version). This is required to build Qt.
  • Python 2.7
  • easy_install for Python
  • miktex
  • cmake
  • perl
  • OpenCV
  • Face Analysis SDK source

Install/build process

  • move mingw-gcc440 to C:\mingw
  • make your life easier and install cygwin then do all compilation inside using mingw32-make
  • install python 2.7
  • get easy_install (python)
  • easy_install numpy
  • easy_install setuptools
  • easy_install sphinx
  • install miktex
  • install cmake
  • get eigen and place in 3rd_party_deps folder in opencv
  • install perl
  • hack path to add mingw32-make and stuff
  • get Qt 4.x source and build it (requires mingw with gcc 440)
  • setx -m QTDIR C:/qt
  • add qt\bin to PATH
  • cmake opencv, configure mingw32-gcc, mingw32-g++ compilers (requires > gcc 4.6 .. latest mingw). Yes, this means you need to use two different version of mingw to build this thing!

Changes required to build face analysis SDK

src/scripts/CMakeLists.txt remove

  • COMMAND /usr/bin/install -m 755 ${_script} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_script}

add

  • COMMAND install -m 755 ${_script} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_script}

src/test/command-line-options.hpp add

  • #include <algorithm> //fixes issue with find_if

src/utils/helpers.hpp

add:

  • #include <stdarg.h> //fixes issue with va_args

src/map-list/main.cpp

  • port from unix POSIX process/threading model to Win32 (shown below).

Rewriting ForkRunner

A basic, straight port requires rewriting the ForkRunner class in src/map-list/main.cpp

Windows port of ForkRunner

class ForkRunner : public Runner
{
public:
  void perform(const std::string &command, const std::list<std::string> &arguments) {
    
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    
    if(!CreateProcess(NULL, "", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ //child process
      char *argv[arguments.size() + 2];
      argv[0] = (char *)command.c_str();
      argv[arguments.size() + 1] = 0;

      std::list<std::string>::const_iterator it = arguments.begin();
      for (size_t i = 0; i < arguments.size(); i++) {
        argv[i + 1] = (char *)it->c_str();
        it++;
      }

      int rv = _execvp(command.c_str(), argv);
      if (rv == -1) 
        throw make_runtime_error("Unable to create new process: %s.", strerror(errno));
    }
    else { // parent process
      throw make_runtime_error("CreateProcess failed (%d).\n", GetLastError() );
      return;
    }
    
    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
  }
};

There are a couple of import differences too:

Remove

#include <sys/wait.h>
#include <unistd.h>

Add

#include <windows.h>
#include <process.h>

The last thing left to do now is to compile face analysis SDK. Be sure to include the ffmpeg flag and stuff as explained in the docs (or check the box if you’re using CMake GUI). If everything went to plan (it probably wont), you can now execute the non-rigid face registration stuff in section 4.1 of the docs.

Running examples

To demostrate the “less than real-time” speed of this port, I present to you:

Face Analysis SDK running in Windows with pre-recorded video stream



Face Analysis SDK running in Windows with live web cam video stream



Final words

There are other “ready to play” face tracker libraries out there that work well on all platforms and have very well documented and easy to use API’s, so unless you really need to use this particular library, I’d be looking at other options such as NXT Beyond Reality Face tracking library and the like.





Related Articles

OpenCV and IP camera streaming with Python