diff --git a/bob/ip/flandmark/__init__.py b/bob/ip/flandmark/__init__.py
index 2e175b0bfdc512dd50ef29eebeef7144caddcd00..463647bf729a03450b3d7f9bb5f4f28983a9316c 100644
--- a/bob/ip/flandmark/__init__.py
+++ b/bob/ip/flandmark/__init__.py
@@ -12,13 +12,14 @@ def get_config():
   import bob.extension
   return bob.extension.get_config(__name__, version.externals)
 
+def _init():
+  # Setup default model for C-API
+  from pkg_resources import resource_filename
+  import os.path
+  from ._library import _set_default_model
+  _set_default_model(resource_filename(__name__, os.path.join('data', 'flandmark_model.dat')))
+
+_init()
 
 # gets sphinx autodoc done right - don't remove it
 __all__ = [_ for _ in dir() if not _.startswith('_')]
-
-# Setup default model for C-API
-from pkg_resources import resource_filename
-import os.path
-from ._library import __set_default_model__
-__set_default_model__(resource_filename(__name__, os.path.join('data', 'flandmark_model.dat')))
-del resource_filename, __set_default_model__, os
diff --git a/bob/ip/flandmark/cpp/flandmark_detector.cpp b/bob/ip/flandmark/cpp/flandmark_detector.cpp
index 328e29a69c21a5c272d640c8173d7d2b1f383ee2..bb9bab1b1f344ceb3630aa0cd1a4ae8e5ea4805c 100644
--- a/bob/ip/flandmark/cpp/flandmark_detector.cpp
+++ b/bob/ip/flandmark/cpp/flandmark_detector.cpp
@@ -12,755 +12,671 @@
 #include <stdlib.h>
 #include <string.h>
 #include <float.h>
+#include <stdexcept>
+#include <boost/format.hpp>
+#include <bob.ip.base/Affine.h>
 
 #include "liblbp.h"
 #include "flandmark_detector.h"
 
-void flandmark_write_model(const char* filename, FLANDMARK_Model* model)
-{
-	int * p_int = 0, tsize = -1, tmp_tsize = -1;
-	uint8_t * p_uint8 = 0;
-	uint32_t * p_uint32 = 0;
-
-	FILE *fout;
-	if ((fout = fopen(filename, "wb")) == NULL)
-	{
-		printf("Error opening file %s\n", filename);
-		exit(1);
-	}
-
-	// write constants (size of matrices, etc)
-	fprintf(fout, " %c ", model->data.options.M);
-	fprintf(fout, " %d %d ", model->data.options.bw[0], model->data.options.bw[1]);
-	fprintf(fout, " %d %d ", model->data.options.bw_margin[0], model->data.options.bw_margin[1]);
-	fprintf(fout, " %d %d ", model->W_ROWS, model->W_COLS);
-	fprintf(fout, " %d %d ", model->data.imSize[0], model->data.imSize[1]);
-	for (int idx = 0; idx < model->data.options.M; ++idx)
-	{
-		fprintf(fout, " %d %d ", model->data.lbp[idx].WINS_ROWS, model->data.lbp[idx].WINS_COLS);
-	}
-	for (int idx = 0; idx < 3; ++idx)
-	{
-		fprintf(fout, " %d %d ", model->data.options.PSIG_ROWS[idx], model->data.options.PSIG_COLS[idx]);
-		printf("model->data.options.PSIG_ROWS[%d] = %d; model->data.options.PSIG_COLS[%d] = %d; \n",
-				idx, model->data.options.PSIG_ROWS[idx],
-				idx, model->data.options.PSIG_COLS[idx] );
-	}
-
-	// write model->W
-	printf("Writing model->W to file... ");
-	if (fwrite(model->W, model->W_ROWS*sizeof(double), 1, fout) != 1)
-	{
-		fclose(fout);
-		printf("Error writing file %s\n", filename);
-		exit(1);
-	}
-	printf("done.\n");
-
-	// write model->mapTable
-	printf("Writing model->data.mapTable to file... ");
-	if (fwrite(model->data.mapTable, model->data.options.M*4*sizeof(int), 1, fout) != 1)
-	{
-		fclose(fout);
-		printf( "Error writing file %s\n", filename);
-		exit(1);
-	}
-	printf( "done.\n");
-
-	// write model->data.lbp ---------------------------------------------------
-	printf( "Writing model->data.lbp to file... \n");
-	for (int idx = 0; idx < model->data.options.M; ++idx)
-	{
-		printf( "lbp[%d]... ", idx);
-
-		// lbp{idx}.winSize
-		p_int = &(model->data.lbp[idx].winSize[0]);
-		if (fwrite(p_int, 2*sizeof(int), 1, fout) != 1)
-		{
-			fclose(fout);
-			printf( "Error writing file %s\n", filename);
-			exit(1);
-		}
-		printf( " winSize... ");
-
-		// lbp{idx}.hop
-		p_uint8 = &(model->data.lbp[idx].hop);
-		if (fwrite(p_uint8, sizeof(uint8_t), 1, fout) != 1)
-		{
-			fclose(fout);
-			printf( "Error writing file %s\n", filename);
-			exit(1);
-		}
-		printf( " hop... ");
-
-		// lbp{idx}.wins
-		p_uint32 = model->data.lbp[idx].wins;
-		tsize = model->data.lbp[idx].WINS_ROWS*model->data.lbp[idx].WINS_COLS;
-		if (fwrite(p_uint32, tsize*sizeof(uint32_t), 1, fout) != 1)
-		{
-			fclose(fout);
-			printf( "Error writing file %s\n", filename);
-			exit(1);
-		}
-		printf( " wins... done.\n");
-	}
-
-	// write model->data.options.S --------------------------------------------
-	printf( "Writing model->data.options.S to file... ");
-	p_int = &(model->data.options.S[0]);
-	if (fwrite(p_int, 4*model->data.options.M*sizeof(int), 1, fout) != 1)
-	{
-		fclose(fout);
-		printf( "Error writing file %s\n", filename);
-		exit(1);
-	}
-	printf( "done.\n");
-
-	// write model->data.options.PsiGS# -----------------------------------------
-	FLANDMARK_PSIG * PsiGi = NULL;
-	for (int psigs_idx = 0; psigs_idx < 3; ++psigs_idx)
-	{
-		printf("PsiGS for loop.\n");
-		switch (psigs_idx)
-		{
-			case 0:
-				printf( "Case 0 = PsiGS0 setting pointer...");
-				PsiGi = (model->data.options.PsiGS0);
-				printf( " done.\n");
-				break;
-			case 1:
-				printf( "Case 0 = PsiGS1 setting pointer...");
-				PsiGi = (model->data.options.PsiGS1);
-				printf( " done.\n");
-				break;
-			case 2:
-				printf( "Case 0 = PsiGS2 setting pointer...");
-				PsiGi = (model->data.options.PsiGS2);
-				printf( " done.\n");
-				break;
-		}
-
-		printf("calculating tsize\n");
-
-		tsize = model->data.options.PSIG_ROWS[psigs_idx]*model->data.options.PSIG_COLS[psigs_idx];
-
-		printf("tsize = %d\n", tsize);
-
-		for (int idx = 0; idx < tsize; ++idx)
-		{
-			// write ROWS and COLS size
-			p_int = &PsiGi[idx].ROWS;
-			if (fwrite(p_int, sizeof(int), 1, fout) != 1)
-			{
-				fclose(fout);
-				printf( "Error writing file %s\n", filename);
-				exit(1);
-			}
-			p_int = &PsiGi[idx].COLS;
-			if (fwrite(p_int, sizeof(int), 1, fout) != 1)
-			{
-				fclose(fout);
-				printf( "Error writing file %s\n", filename);
-				exit(1);
-			}
-			// write disp
-			tmp_tsize = PsiGi[idx].ROWS*PsiGi[idx].COLS;
-			if (fwrite(PsiGi[idx].disp, tmp_tsize*sizeof(int), 1, fout) != 1)
-			{
-				fclose(fout);
-				printf( "Error writing file %s\n", filename);
-				exit(1);
-			}
-		}
-	}
-
-	fclose(fout);
-}
+namespace bob { namespace ip { namespace flandmark {
 
-FLANDMARK_Model * flandmark_init(const char* filename)
+void flandmark_write_model(const char* filename, FLANDMARK_Model* model)
 {
-	int *p_int = 0, tsize = -1, tmp_tsize = -1;
-	uint8_t *p_uint8 = 0;
-
-	FILE *fin;
-	if ((fin = fopen(filename, "rb")) == NULL)
-	{
-		printf("Error opening file %s\n", filename);
-		return 0;
-	}
-
-	// allocate memory for FLANDMARK_Model
-	FLANDMARK_Model * tst = (FLANDMARK_Model*)malloc(sizeof(FLANDMARK_Model));
-
-    //int fscan_ret = -1;
-    if (fscanf(fin, " %c ", &tst->data.options.M) < 1)
+  int * p_int = 0, tsize = -1, tmp_tsize = -1;
+  uint8_t * p_uint8 = 0;
+  uint32_t * p_uint32 = 0;
+
+  FILE *fout;
+  if ((fout = fopen(filename, "wb")) == NULL)
+  {
+    printf("Error opening file %s\n", filename);
+    exit(1);
+  }
+
+  // write constants (size of matrices, etc)
+  fprintf(fout, " %c ", model->data.options.M);
+  fprintf(fout, " %d %d ", model->data.options.bw[0], model->data.options.bw[1]);
+  fprintf(fout, " %d %d ", model->data.options.bw_margin[0], model->data.options.bw_margin[1]);
+  fprintf(fout, " %d %d ", model->W_ROWS, model->W_COLS);
+  fprintf(fout, " %d %d ", model->data.imSize[0], model->data.imSize[1]);
+  for (int idx = 0; idx < model->data.options.M; ++idx)
+  {
+    fprintf(fout, " %d %d ", model->data.lbp[idx].WINS_ROWS, model->data.lbp[idx].WINS_COLS);
+  }
+  for (int idx = 0; idx < 3; ++idx)
+  {
+    fprintf(fout, " %d %d ", model->data.options.PSIG_ROWS[idx], model->data.options.PSIG_COLS[idx]);
+    printf("model->data.options.PSIG_ROWS[%d] = %d; model->data.options.PSIG_COLS[%d] = %d; \n",
+        idx, model->data.options.PSIG_ROWS[idx],
+        idx, model->data.options.PSIG_COLS[idx] );
+  }
+
+  // write model->W
+  printf("Writing model->W to file... ");
+  if (fwrite(model->W, model->W_ROWS*sizeof(double), 1, fout) != 1)
+  {
+    fclose(fout);
+    printf("Error writing file %s\n", filename);
+    exit(1);
+  }
+  printf("done.\n");
+
+  // write model->mapTable
+  printf("Writing model->data.mapTable to file... ");
+  if (fwrite(model->data.mapTable, model->data.options.M*4*sizeof(int), 1, fout) != 1)
+  {
+    fclose(fout);
+    printf( "Error writing file %s\n", filename);
+    exit(1);
+  }
+  printf( "done.\n");
+
+  // write model->data.lbp ---------------------------------------------------
+  printf( "Writing model->data.lbp to file... \n");
+  for (int idx = 0; idx < model->data.options.M; ++idx)
+  {
+    printf( "lbp[%d]... ", idx);
+
+    // lbp{idx}.winSize
+    p_int = &(model->data.lbp[idx].winSize[0]);
+    if (fwrite(p_int, 2*sizeof(int), 1, fout) != 1)
     {
-        return 0;
+      fclose(fout);
+      printf( "Error writing file %s\n", filename);
+      exit(1);
     }
+    printf( " winSize... ");
 
-    if (fscanf(fin, " %d %d ", &tst->data.options.bw[0], &tst->data.options.bw[1]) < 2)
+    // lbp{idx}.hop
+    p_uint8 = &(model->data.lbp[idx].hop);
+    if (fwrite(p_uint8, sizeof(uint8_t), 1, fout) != 1)
     {
-        return 0;
+      fclose(fout);
+      printf( "Error writing file %s\n", filename);
+      exit(1);
     }
+    printf( " hop... ");
 
-    if (fscanf(fin, " %d %d ", &tst->data.options.bw_margin[0], &tst->data.options.bw_margin[1]) < 2)
+    // lbp{idx}.wins
+    p_uint32 = model->data.lbp[idx].wins;
+    tsize = model->data.lbp[idx].WINS_ROWS*model->data.lbp[idx].WINS_COLS;
+    if (fwrite(p_uint32, tsize*sizeof(uint32_t), 1, fout) != 1)
     {
-        return 0;
+      fclose(fout);
+      printf( "Error writing file %s\n", filename);
+      exit(1);
     }
-
-    if (fscanf(fin, " %d %d ", &tst->W_ROWS, &tst->W_COLS) < 2)
+    printf( " wins... done.\n");
+  }
+
+  // write model->data.options.S --------------------------------------------
+  printf( "Writing model->data.options.S to file... ");
+  p_int = &(model->data.options.S[0]);
+  if (fwrite(p_int, 4*model->data.options.M*sizeof(int), 1, fout) != 1)
+  {
+    fclose(fout);
+    printf( "Error writing file %s\n", filename);
+    exit(1);
+  }
+  printf( "done.\n");
+
+  // write model->data.options.PsiGS# -----------------------------------------
+  FLANDMARK_PSIG * PsiGi = NULL;
+  for (int psigs_idx = 0; psigs_idx < 3; ++psigs_idx)
+  {
+    printf("PsiGS for loop.\n");
+    switch (psigs_idx)
     {
-        return 0;
+      case 0:
+        printf( "Case 0 = PsiGS0 setting pointer...");
+        PsiGi = (model->data.options.PsiGS0);
+        printf( " done.\n");
+        break;
+      case 1:
+        printf( "Case 0 = PsiGS1 setting pointer...");
+        PsiGi = (model->data.options.PsiGS1);
+        printf( " done.\n");
+        break;
+      case 2:
+        printf( "Case 0 = PsiGS2 setting pointer...");
+        PsiGi = (model->data.options.PsiGS2);
+        printf( " done.\n");
+        break;
     }
 
-    if (fscanf(fin, " %d %d ", &tst->data.imSize[0], &tst->data.imSize[1]) < 2)
+    printf("calculating tsize\n");
+
+    tsize = model->data.options.PSIG_ROWS[psigs_idx]*model->data.options.PSIG_COLS[psigs_idx];
+
+    printf("tsize = %d\n", tsize);
+
+    for (int idx = 0; idx < tsize; ++idx)
     {
-        return 0;
+      // write ROWS and COLS size
+      p_int = &PsiGi[idx].ROWS;
+      if (fwrite(p_int, sizeof(int), 1, fout) != 1)
+      {
+        fclose(fout);
+        printf( "Error writing file %s\n", filename);
+        exit(1);
+      }
+      p_int = &PsiGi[idx].COLS;
+      if (fwrite(p_int, sizeof(int), 1, fout) != 1)
+      {
+        fclose(fout);
+        printf( "Error writing file %s\n", filename);
+        exit(1);
+      }
+      // write disp
+      tmp_tsize = PsiGi[idx].ROWS*PsiGi[idx].COLS;
+      if (fwrite(PsiGi[idx].disp, tmp_tsize*sizeof(int), 1, fout) != 1)
+      {
+        fclose(fout);
+        printf( "Error writing file %s\n", filename);
+        exit(1);
+      }
     }
+  }
 
-	int M = tst->data.options.M;
+  fclose(fout);
+}
 
-    tst->data.lbp = (FLANDMARK_LBP*)malloc(M*sizeof(FLANDMARK_LBP));
-    for (int idx = 0; idx < M; ++idx)
-	{
-        if (fscanf(fin, " %d %d ", &tst->data.lbp[idx].WINS_ROWS, &tst->data.lbp[idx].WINS_COLS) < 2)
-        {
-            return 0;
-        }
-	}
+FLANDMARK_Model * flandmark_init(const char* filename)
+{
+  int *p_int = 0, tsize = -1, tmp_tsize = -1;
+  uint8_t *p_uint8 = 0;
+
+  FILE *fin;
+  if ((fin = fopen(filename, "rb")) == NULL)
+  {
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+  }
+
+  // allocate memory for FLANDMARK_Model
+  FLANDMARK_Model * tst = (FLANDMARK_Model*)malloc(sizeof(FLANDMARK_Model));
+
+  //int fscan_ret = -1;
+  if (fscanf(fin, " %c ", &tst->data.options.M) < 1)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+
+  if (fscanf(fin, " %d %d ", &tst->data.options.bw[0], &tst->data.options.bw[1]) < 2)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+
+  if (fscanf(fin, " %d %d ", &tst->data.options.bw_margin[0], &tst->data.options.bw_margin[1]) < 2)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+
+  if (fscanf(fin, " %d %d ", &tst->W_ROWS, &tst->W_COLS) < 2)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+
+  if (fscanf(fin, " %d %d ", &tst->data.imSize[0], &tst->data.imSize[1]) < 2)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+
+  int M = tst->data.options.M;
+
+  tst->data.lbp = (FLANDMARK_LBP*)malloc(M*sizeof(FLANDMARK_LBP));
+  for (int idx = 0; idx < M; ++idx){
+    if (fscanf(fin, " %d %d ", &tst->data.lbp[idx].WINS_ROWS, &tst->data.lbp[idx].WINS_COLS) < 2)
+      throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+  }
+
+  for (int idx = 0; idx < 3; ++idx){
+    if (fscanf(fin, " %d %d ", &tst->data.options.PSIG_ROWS[idx], &tst->data.options.PSIG_COLS[idx]) < 2)
+      throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+  }
+
+  // load model.W -----------------------------------------------------------
+  tst->W = (double*)malloc(tst->W_ROWS * sizeof(double));
+  if (fread(tst->W, tst->W_ROWS * sizeof(double), 1, fin) != 1)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+
+  // load model.data.mapTable -----------------------------------------------
+  p_int = (int*)malloc(M*4*sizeof(int));
+  tst->data.mapTable = (int*)malloc(M*4*sizeof(int));
+  if (fread(p_int, M*4*sizeof(int), 1, fin) != 1)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+  for (int i = 0; i < M*4; ++i)
+    tst->data.mapTable[i] = p_int[i];
+  free(p_int);
+
+  // load model.data.lbp ---------------------------------------------------
+  for (int idx = 0; idx < M; ++idx){
+    // lbp{idx}.winSize
+    p_int = (int*)malloc(2*sizeof(int));
+    if (fread(p_int, 2*sizeof(int), 1, fin) != 1)
+      throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+    for (int i = 0; i < 2; ++i)
+      tst->data.lbp[idx].winSize[i] = p_int[i];
+    free(p_int);
+
+    // lbp{idx}.hop
+    p_uint8 = (uint8_t*)malloc(sizeof(uint8_t));
+    if (fread(p_uint8, sizeof(uint8_t), 1, fin) != 1)
+      throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+    tst->data.lbp[idx].hop = p_uint8[0];
+    free(p_uint8);
+
+    // lbp{idx}.wins
+    tsize = tst->data.lbp[idx].WINS_ROWS*tst->data.lbp[idx].WINS_COLS;
+    tst->data.lbp[idx].wins = (uint32_t*)malloc(tsize * sizeof(uint32_t));
+    if (fread(tst->data.lbp[idx].wins, tsize * sizeof(uint32_t), 1, fin) != 1)
+      throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+  }
+
+  // load model.options.S --------------------------------------------------
+  p_int = (int*)malloc(4*M*sizeof(int));
+  tst->data.options.S = (int*)malloc(4*M*sizeof(int));
+  if (fread(p_int, 4*M*sizeof(int), 1, fin) != 1)
+    throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+  for (int i = 0; i < 4*M; ++i)
+    tst->data.options.S[i] = p_int[i];
+  free(p_int);
+
+  // load model.options.PsiG -----------------------------------------------
+  FLANDMARK_PSIG * PsiGi = NULL;
+  for (int psigs_idx = 0; psigs_idx < 3; ++psigs_idx){
+    tsize = tst->data.options.PSIG_ROWS[psigs_idx]*tst->data.options.PSIG_COLS[psigs_idx];
+
+    switch (psigs_idx){
+      case 0:
+        tst->data.options.PsiGS0 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG));
+        PsiGi = tst->data.options.PsiGS0;
+        break;
+      case 1:
+        tst->data.options.PsiGS1 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG));
+        PsiGi = tst->data.options.PsiGS1;
+        break;
+      case 2:
+        tst->data.options.PsiGS2 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG));
+        PsiGi = tst->data.options.PsiGS2;
+        break;
+    }
 
-	for (int idx = 0; idx < 3; ++idx)
-	{
-        if (fscanf(fin, " %d %d ", &tst->data.options.PSIG_ROWS[idx], &tst->data.options.PSIG_COLS[idx]) < 2)
-        {
-            return 0;
-        }
-	}
-
-	// load model.W -----------------------------------------------------------
-	tst->W = (double*)malloc(tst->W_ROWS * sizeof(double));
-	if (fread(tst->W, tst->W_ROWS * sizeof(double), 1, fin) != 1)
-	{
-		printf( "Error reading file %s\n", filename);
-		return 0;
-	}
-
-	// load model.data.mapTable -----------------------------------------------
-    p_int = (int*)malloc(M*4*sizeof(int));
-	tst->data.mapTable = (int*)malloc(M*4*sizeof(int));
-    if (fread(p_int, M*4*sizeof(int), 1, fin) != 1)
-	{
-		printf( "Error reading file %s\n", filename);
-		return 0;
-	}
-    for (int i = 0; i < M*4; ++i)
-	{
-		tst->data.mapTable[i] = p_int[i];
-	}
-	free(p_int);
-
-	// load model.data.lbp ---------------------------------------------------
-    for (int idx = 0; idx < M; ++idx)
-	{
-		// lbp{idx}.winSize
-		p_int = (int*)malloc(2*sizeof(int));
-		if (fread(p_int, 2*sizeof(int), 1, fin) != 1)
-		{
-			printf( "Error reading file %s\n", filename);
-			return 0;
-		}
-		for (int i = 0; i < 2; ++i)
-		{
-			tst->data.lbp[idx].winSize[i] = p_int[i];
-		}
-		free(p_int);
-
-		// lbp{idx}.hop
-		p_uint8 = (uint8_t*)malloc(sizeof(uint8_t));
-		if (fread(p_uint8, sizeof(uint8_t), 1, fin) != 1)
-		{
-			printf( "Error reading file %s\n", filename);
-			return 0;
-		}
-		tst->data.lbp[idx].hop = p_uint8[0];
-		free(p_uint8);
-
-		// lbp{idx}.wins
-		tsize = tst->data.lbp[idx].WINS_ROWS*tst->data.lbp[idx].WINS_COLS;
-		tst->data.lbp[idx].wins = (uint32_t*)malloc(tsize * sizeof(uint32_t));
-		if (fread(tst->data.lbp[idx].wins, tsize * sizeof(uint32_t), 1, fin) != 1)
-		{
-			printf( "Error reading file %s\n", filename);
-			return 0;
-			//exit(1);
-		}
-	}
-
-	// load model.options.S --------------------------------------------------
-    p_int = (int*)malloc(4*M*sizeof(int));
-	tst->data.options.S = (int*)malloc(4*M*sizeof(int));
-    if (fread(p_int, 4*M*sizeof(int), 1, fin) != 1)
-	{
-		printf( "Error reading file %s\n", filename);
-		return 0;
-		//exit(1);
-	}
-    for (int i = 0; i < 4*M; ++i)
-	{
-		tst->data.options.S[i] = p_int[i];
-	}
-	free(p_int);
-
-	// load model.options.PsiG -----------------------------------------------
-	FLANDMARK_PSIG * PsiGi = NULL;
-	for (int psigs_idx = 0; psigs_idx < 3; ++psigs_idx)
-	{
-		tsize = tst->data.options.PSIG_ROWS[psigs_idx]*tst->data.options.PSIG_COLS[psigs_idx];
-
-		switch (psigs_idx)
-		{
-			case 0:
-				tst->data.options.PsiGS0 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG));
-				PsiGi = tst->data.options.PsiGS0;
-				break;
-			case 1:
-				tst->data.options.PsiGS1 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG));
-				PsiGi = tst->data.options.PsiGS1;
-				break;
-			case 2:
-				tst->data.options.PsiGS2 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG));
-				PsiGi = tst->data.options.PsiGS2;
-				break;
-		}
-
-		for (int idx = 0; idx < tsize; ++idx)
-		{
-			// disp ROWS
-			p_int = (int*)malloc(sizeof(int));
-			if (fread(p_int, sizeof(int), 1, fin) != 1)
-			{
-				printf( "Error reading file %s\n", filename);
-				return 0;
-				//exit(1);
-			}
-			PsiGi[idx].ROWS = p_int[0];
-			free(p_int);
-			// disp COLS
-			p_int = (int*)malloc(sizeof(int));
-			if (fread(p_int, sizeof(int), 1, fin) != 1)
-			{
-				printf( "Error reading file %s\n", filename);
-				return 0;
-				//exit(1);
-			}
-			PsiGi[idx].COLS = p_int[0];
-			free(p_int);
-			// disp
-			tmp_tsize = PsiGi[idx].ROWS*PsiGi[idx].COLS;
-			PsiGi[idx].disp = (int*)malloc(tmp_tsize*sizeof(int));
-			if (fread(PsiGi[idx].disp, tmp_tsize*sizeof(int), 1, fin) != 1)
-			{
-				printf( "Error reading file %s\n", filename);
-				return 0;
-				//exit(1);
-			}
-		}
-	}
-
-	fclose(fin);
-
-    tst->normalizedImageFrame = (uint8_t*)calloc(tst->data.options.bw[0]*tst->data.options.bw[1], sizeof(uint8_t));
-
-    tst->bb = (double*)calloc(4, sizeof(double));
-
-    tst->sf = (float*)calloc(2, sizeof(float));
-
-	return tst;
+    for (int idx = 0; idx < tsize; ++idx){
+      // disp ROWS
+      p_int = (int*)malloc(sizeof(int));
+      if (fread(p_int, sizeof(int), 1, fin) != 1)
+        throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+      PsiGi[idx].ROWS = p_int[0];
+      free(p_int);
+      // disp COLS
+      p_int = (int*)malloc(sizeof(int));
+      if (fread(p_int, sizeof(int), 1, fin) != 1)
+        throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+      PsiGi[idx].COLS = p_int[0];
+      free(p_int);
+      // disp
+      tmp_tsize = PsiGi[idx].ROWS*PsiGi[idx].COLS;
+      PsiGi[idx].disp = (int*)malloc(tmp_tsize*sizeof(int));
+      if (fread(PsiGi[idx].disp, tmp_tsize*sizeof(int), 1, fin) != 1)
+        throw std::runtime_error((boost::format("Error opening file %s") % filename).str().c_str());
+    }
+  }
+
+  fclose(fin);
+
+  tst->normalizedImageFrame = (uint8_t*)calloc(tst->data.options.bw[0]*tst->data.options.bw[1], sizeof(uint8_t));
+
+  return tst;
 }
 
 EError_T flandmark_check_model(FLANDMARK_Model* model, FLANDMARK_Model* tst)
 {
-	bool flag = false;
-	int tsize = -1, tmp_tsize = -1;
-
-	// check model->data.options.M
-	printf("Checking mode->data.options.M...");
-	flag = true;
-	if (model->data.options.M != tst->data.options.M)
-	{
-		flag = false;
-		printf("\n: %d ; %d", model->data.options.M, tst->data.options.M);
-	}
-	flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-	if (!flag)
-	{
-		return ERROR_M;
-	}
-
-	int M = model->data.options.M;
-
-	// chceck model->data.options.bw
-	printf("Checking mode->data.options.bw...");
-	flag = true;
-	if (model->data.options.bw[0] != tst->data.options.bw[0] ||
-			model->data.options.bw[1] != tst->data.options.bw[1])
-	{
-		flag = false;
-		printf("\n: %d ; %d", model->data.options.bw[0], tst->data.options.bw[0]);
-		printf("\n: %d ; %d", model->data.options.bw[1], tst->data.options.bw[1]);
-	}
-	flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-	if (!flag)
-	{
-		return ERROR_BW;
-	}
-
-	// chceck model->data.options.bw_margin
-	printf("Checking mode->data.options.bw_margin...");
-	flag = true;
-	if (model->data.options.bw_margin[0] != tst->data.options.bw_margin[0] ||
-			model->data.options.bw_margin[1] != tst->data.options.bw_margin[1])
-	{
-		flag = false;
-		printf("\n: %d ; %d", model->data.options.bw_margin[0], tst->data.options.bw_margin[0]);
-		printf("\n: %d ; %d", model->data.options.bw_margin[1], tst->data.options.bw_margin[1]);
-	}
-	flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-	if (!flag)
-	{
-		return ERROR_BW_MARGIN;
-	}
-
-	// check model->W
-	printf( "Checking model->W... ");
-	flag = true;
-	for (int i = 0; i < tst->W_ROWS; ++i)
-	{
-		if (model->W[i] != tst->W[i])
-		{
-			flag = false;
-			printf( "\n%d: %f ; %f", i, model->W[i], tst->W[i]);
-			printf( "Error.");
-		}
-	}
-	flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-	if (!flag)
-	{
-		return ERROR_W;
-	}
-
-	// check model->data.mapTable
-	printf( "Checking model->data.mapTable... ");
-	flag = true;
-	for (int i = 0; i < M*4; ++i)
-	{
-		if (model->data.mapTable[i] != tst->data.mapTable[i])
-		{
-			flag = false;
-			printf( "\n%d: %d ; %d", i, model->data.mapTable[i], tst->data.mapTable[i]);
-			printf( "Error.");
-		}
-	}
-	flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-	if (!flag)
-	{
-		return ERROR_DATA_MAPTABLE;
-	}
-
-	// load model->data.lbp ---------------------------------------------------
-	for (int idx = 0; idx < model->data.options.M; ++idx)
-	{
-		flag = true;
-		printf( "checking lbp[%d]... ", idx);
-
-		for (int i = 0; i < 2; ++i)
-		{
-			if (tst->data.lbp[idx].winSize[i] != model->data.lbp[idx].winSize[i])
-			{
-				flag = false;
-				printf( "\n%d: %d ; %d", i, model->data.lbp[idx].winSize[i], tst->data.lbp[idx].winSize[i]);
-				printf( "Error.");
-			}
-		}
-
-		// lbp{idx}.hop
-		if (tst->data.lbp[idx].hop != model->data.lbp[idx].hop)
-		{
-			flag = false;
-			printf( "\n %d ; %d", model->data.lbp[idx].hop, tst->data.lbp[idx].hop);
-			printf( "Error.");
-		}
-
-		// lbp{idx}.wins
-		tsize = tst->data.lbp[idx].WINS_ROWS*tst->data.lbp[idx].WINS_COLS;
-		for (int i = 0; i < tsize; ++i)
-		{
-			if (model->data.lbp[idx].wins[i] != tst->data.lbp[idx].wins[i])
-			{
-				flag = false;
-				printf( "\n%d: %d ; %d", i, model->data.lbp[idx].wins[i], tst->data.lbp[idx].wins[i]);
-				printf( "Error.");
-			}
-		}
-		flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-		if (!flag)
-		{
-			return ERROR_DATA_LBP;
-		}
-	}
-
-	// check model->data.options.S
-	printf( "Checking model->data.options.S... ");
-	flag = true;
-	for (int i = 0; i < 4*M; ++i)
-	{
-		if (model->data.options.S[i] != tst->data.options.S[i])
-		{
-			flag = false;
-			printf( "\n%d: %d ; %d", i, model->data.options.S[i], tst->data.options.S[i]);
-			printf("Error.");
-		}
-	}
-	flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-	if (!flag)
-	{
-		return ERROR_DATA_OPTIONS_S;
-	}
-
-	// check model->data.options.PsiG
-	FLANDMARK_PSIG *PsiGi = NULL, *PsiGiTst = NULL;
-	for (int psig_idx = 0; psig_idx < 3; ++psig_idx)
-	{
-		switch(psig_idx)
-		{
-			case 0:
-				PsiGi = (model->data.options.PsiGS0);
-				PsiGiTst = (tst->data.options.PsiGS0);
-				break;
-			case 1:
-				PsiGi = (model->data.options.PsiGS1);
-				PsiGiTst = (tst->data.options.PsiGS1);
-				break;
-			case 2:
-				PsiGi = (model->data.options.PsiGS2);
-				PsiGiTst = (tst->data.options.PsiGS2);
-				break;
-		}
-		flag = true;
-		printf( "Checking model->data.options.PsiGS%d\n", psig_idx);
-		printf( "options.PSIG_ROWS[%d]; options.PSIG_COLS[%d]... ", psig_idx, psig_idx);
-		if (model->data.options.PSIG_ROWS[psig_idx] != tst->data.options.PSIG_ROWS[psig_idx] ||
-				model->data.options.PSIG_COLS[psig_idx] != tst->data.options.PSIG_COLS[psig_idx])
-		{
-			flag = false;
-			printf("Error.");
-		}
-		flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-		if (!flag)
-		{
-			return ERROR_DATA_OPTIONS_PSIG;
-		}
-		// disp
-		flag = true;
-		tsize = tst->data.options.PSIG_ROWS[psig_idx]*tst->data.options.PSIG_COLS[psig_idx];
-		printf( "options.PsiGS%d...", psig_idx);
-		for (int idx = 0; idx < tsize; ++idx)
-		{
-			if (PsiGi[idx].ROWS != PsiGiTst[idx].ROWS ||
-					PsiGi[idx].COLS != PsiGiTst[idx].COLS)
-			{
+  bool flag = false;
+  int tsize = -1, tmp_tsize = -1;
+
+  // check model->data.options.M
+  printf("Checking mode->data.options.M...");
+  flag = true;
+  if (model->data.options.M != tst->data.options.M)
+  {
+    flag = false;
+    printf("\n: %d ; %d", model->data.options.M, tst->data.options.M);
+  }
+  flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+  if (!flag)
+  {
+    return ERROR_M;
+  }
+
+  int M = model->data.options.M;
+
+  // chceck model->data.options.bw
+  printf("Checking mode->data.options.bw...");
+  flag = true;
+  if (model->data.options.bw[0] != tst->data.options.bw[0] ||
+      model->data.options.bw[1] != tst->data.options.bw[1])
+  {
+    flag = false;
+    printf("\n: %d ; %d", model->data.options.bw[0], tst->data.options.bw[0]);
+    printf("\n: %d ; %d", model->data.options.bw[1], tst->data.options.bw[1]);
+  }
+  flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+  if (!flag)
+  {
+    return ERROR_BW;
+  }
+
+  // chceck model->data.options.bw_margin
+  printf("Checking mode->data.options.bw_margin...");
+  flag = true;
+  if (model->data.options.bw_margin[0] != tst->data.options.bw_margin[0] ||
+      model->data.options.bw_margin[1] != tst->data.options.bw_margin[1])
+  {
+    flag = false;
+    printf("\n: %d ; %d", model->data.options.bw_margin[0], tst->data.options.bw_margin[0]);
+    printf("\n: %d ; %d", model->data.options.bw_margin[1], tst->data.options.bw_margin[1]);
+  }
+  flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+  if (!flag)
+  {
+    return ERROR_BW_MARGIN;
+  }
+
+  // check model->W
+  printf( "Checking model->W... ");
+  flag = true;
+  for (int i = 0; i < tst->W_ROWS; ++i)
+  {
+    if (model->W[i] != tst->W[i])
+    {
+      flag = false;
+      printf( "\n%d: %f ; %f", i, model->W[i], tst->W[i]);
+      printf( "Error.");
+    }
+  }
+  flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+  if (!flag)
+  {
+    return ERROR_W;
+  }
+
+  // check model->data.mapTable
+  printf( "Checking model->data.mapTable... ");
+  flag = true;
+  for (int i = 0; i < M*4; ++i)
+  {
+    if (model->data.mapTable[i] != tst->data.mapTable[i])
+    {
+      flag = false;
+      printf( "\n%d: %d ; %d", i, model->data.mapTable[i], tst->data.mapTable[i]);
+      printf( "Error.");
+    }
+  }
+  flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+  if (!flag)
+  {
+    return ERROR_DATA_MAPTABLE;
+  }
+
+  // load model->data.lbp ---------------------------------------------------
+  for (int idx = 0; idx < model->data.options.M; ++idx)
+  {
+    flag = true;
+    printf( "checking lbp[%d]... ", idx);
+
+    for (int i = 0; i < 2; ++i)
+    {
+      if (tst->data.lbp[idx].winSize[i] != model->data.lbp[idx].winSize[i])
+      {
+        flag = false;
+        printf( "\n%d: %d ; %d", i, model->data.lbp[idx].winSize[i], tst->data.lbp[idx].winSize[i]);
+        printf( "Error.");
+      }
+    }
+
+    // lbp{idx}.hop
+    if (tst->data.lbp[idx].hop != model->data.lbp[idx].hop)
+    {
+      flag = false;
+      printf( "\n %d ; %d", model->data.lbp[idx].hop, tst->data.lbp[idx].hop);
+      printf( "Error.");
+    }
+
+    // lbp{idx}.wins
+    tsize = tst->data.lbp[idx].WINS_ROWS*tst->data.lbp[idx].WINS_COLS;
+    for (int i = 0; i < tsize; ++i)
+    {
+      if (model->data.lbp[idx].wins[i] != tst->data.lbp[idx].wins[i])
+      {
+        flag = false;
+        printf( "\n%d: %d ; %d", i, model->data.lbp[idx].wins[i], tst->data.lbp[idx].wins[i]);
+        printf( "Error.");
+      }
+    }
+    flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+    if (!flag)
+    {
+      return ERROR_DATA_LBP;
+    }
+  }
+
+  // check model->data.options.S
+  printf( "Checking model->data.options.S... ");
+  flag = true;
+  for (int i = 0; i < 4*M; ++i)
+  {
+    if (model->data.options.S[i] != tst->data.options.S[i])
+    {
+      flag = false;
+      printf( "\n%d: %d ; %d", i, model->data.options.S[i], tst->data.options.S[i]);
+      printf("Error.");
+    }
+  }
+  flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+  if (!flag)
+  {
+    return ERROR_DATA_OPTIONS_S;
+  }
+
+  // check model->data.options.PsiG
+  FLANDMARK_PSIG *PsiGi = NULL, *PsiGiTst = NULL;
+  for (int psig_idx = 0; psig_idx < 3; ++psig_idx)
+  {
+    switch(psig_idx)
+    {
+      case 0:
+        PsiGi = (model->data.options.PsiGS0);
+        PsiGiTst = (tst->data.options.PsiGS0);
+        break;
+      case 1:
+        PsiGi = (model->data.options.PsiGS1);
+        PsiGiTst = (tst->data.options.PsiGS1);
+        break;
+      case 2:
+        PsiGi = (model->data.options.PsiGS2);
+        PsiGiTst = (tst->data.options.PsiGS2);
+        break;
+    }
+    flag = true;
+    printf( "Checking model->data.options.PsiGS%d\n", psig_idx);
+    printf( "options.PSIG_ROWS[%d]; options.PSIG_COLS[%d]... ", psig_idx, psig_idx);
+    if (model->data.options.PSIG_ROWS[psig_idx] != tst->data.options.PSIG_ROWS[psig_idx] ||
+        model->data.options.PSIG_COLS[psig_idx] != tst->data.options.PSIG_COLS[psig_idx])
+    {
+      flag = false;
+      printf("Error.");
+    }
+    flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+    if (!flag)
+    {
+      return ERROR_DATA_OPTIONS_PSIG;
+    }
+    // disp
+    flag = true;
+    tsize = tst->data.options.PSIG_ROWS[psig_idx]*tst->data.options.PSIG_COLS[psig_idx];
+    printf( "options.PsiGS%d...", psig_idx);
+    for (int idx = 0; idx < tsize; ++idx)
+    {
+      if (PsiGi[idx].ROWS != PsiGiTst[idx].ROWS ||
+          PsiGi[idx].COLS != PsiGiTst[idx].COLS)
+      {
                 printf( "\nPsiGS%d[%d].ROWS\n", psig_idx, idx);
-				flag = false;
-				printf("Error.");
-			}
-			tmp_tsize = PsiGiTst[idx].ROWS*PsiGiTst[idx].COLS;
-			for (int i = 0; i < tmp_tsize; ++i)
-			{
-				if (PsiGi[idx].disp[i] != PsiGiTst[idx].disp[i])
-				{
-					flag = false;
-					printf( "\nPsiGS%d[%d] =  %d; %d\n", psig_idx, idx, PsiGi[idx].disp[i], PsiGiTst[idx].disp[i]);
-					printf( "Error.");
-				}
-			}
-		}
-		flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
-		if (!flag)
-		{
-			return ERROR_DATA_OPTIONS_PSIG;
-		}
-	}
-	return NO_ERR;
+        flag = false;
+        printf("Error.");
+      }
+      tmp_tsize = PsiGiTst[idx].ROWS*PsiGiTst[idx].COLS;
+      for (int i = 0; i < tmp_tsize; ++i)
+      {
+        if (PsiGi[idx].disp[i] != PsiGiTst[idx].disp[i])
+        {
+          flag = false;
+          printf( "\nPsiGS%d[%d] =  %d; %d\n", psig_idx, idx, PsiGi[idx].disp[i], PsiGiTst[idx].disp[i]);
+          printf( "Error.");
+        }
+      }
+    }
+    flag == true ? printf( "passed. \n") : printf( "NOT passed.\n");
+    if (!flag)
+    {
+      return ERROR_DATA_OPTIONS_PSIG;
+    }
+  }
+  return NO_ERR;
 }
 
 void flandmark_free(FLANDMARK_Model* model)
 {
-	FLANDMARK_PSIG *PsiGi = NULL;
-	for (int psig_idx = 0; psig_idx < 3; ++psig_idx)
-	{
-		switch(psig_idx)
-		{
-			case 0:
-				PsiGi = (model->data.options.PsiGS0);
-				break;
-			case 1:
-				PsiGi = (model->data.options.PsiGS1);
-				break;
-			case 2:
-				PsiGi = (model->data.options.PsiGS2);
-				break;
-		}
-
-		int tsize = model->data.options.PSIG_ROWS[psig_idx] * model->data.options.PSIG_COLS[psig_idx];
-		for (int i = 0; i < tsize; ++i)
-		{
-			free(PsiGi[i].disp);
-		}
-		free(PsiGi);
-	}
-
-	free(model->W);
-	for (int i = 0; i < model->data.options.M; ++i)
-	{
-		free(model->data.lbp[i].wins);
-	}
-	free(model->data.lbp);
-	free(model->data.options.S);
-	free(model->data.mapTable);
-
-    //if (model->croppedImage)
-    //	cvReleaseImage(&model->croppedImage);
-
-    //if (model->resizedImage)
-    //	cvReleaseImage(&model->resizedImage);
-
-    if (model->normalizedImageFrame)
-		free(model->normalizedImageFrame);
-
-    if (model->bb)
-		free(model->bb);
-
-    if (model->sf)
-		free(model->sf);
-
-	free(model);
+  FLANDMARK_PSIG *PsiGi = NULL;
+  for (int psig_idx = 0; psig_idx < 3; ++psig_idx)
+  {
+    switch(psig_idx)
+    {
+      case 0:
+        PsiGi = (model->data.options.PsiGS0);
+        break;
+      case 1:
+        PsiGi = (model->data.options.PsiGS1);
+        break;
+      case 2:
+        PsiGi = (model->data.options.PsiGS2);
+        break;
+    }
+
+    int tsize = model->data.options.PSIG_ROWS[psig_idx] * model->data.options.PSIG_COLS[psig_idx];
+    for (int i = 0; i < tsize; ++i)
+    {
+      free(PsiGi[i].disp);
+    }
+    free(PsiGi);
+  }
+
+  free(model->W);
+  for (int i = 0; i < model->data.options.M; ++i)
+  {
+    free(model->data.lbp[i].wins);
+  }
+  free(model->data.lbp);
+  free(model->data.options.S);
+  free(model->data.mapTable);
+
+  if (model->normalizedImageFrame)
+    free(model->normalizedImageFrame);
+
+  free(model);
 }
 
 void flandmark_get_psi_mat(FLANDMARK_PSI* Psi, FLANDMARK_Model* model, int lbpidx)
 {
-	char * Features;
-    const uint8_t * Images = model->normalizedImageFrame;
-	uint32_t im_H = (uint32_t)model->data.imSize[0]; uint32_t im_W = (uint32_t)model->data.imSize[1];
-    const uint32_t * Wins = model->data.lbp[lbpidx].wins;
-	uint16_t win_H = (uint16_t)model->data.lbp[lbpidx].winSize[0]; uint16_t win_W = (uint16_t)model->data.lbp[lbpidx].winSize[1];
-	uint16_t nPyramids = model->data.lbp[lbpidx].hop;
-	uint32_t nDim = liblbp_pyr_get_dim(win_H, win_W, nPyramids); uint32_t nData = model->data.lbp[lbpidx].WINS_COLS;
-
-	Features = (char*)calloc(nDim*nData, sizeof(char));
-	if (Features == NULL)
-	{
-		printf( "Not enough memory for LBP features.\n");
-		exit(1);
-	}
-	Psi->PSI_ROWS = nDim; Psi->PSI_COLS = nData;
-
-    uint32_t cnt0, mirror, x, x1, y, y1, idx, *win;
-    const uint8_t *img_ptr;
-
-	win = (uint32_t*)malloc(win_H*win_W*sizeof(uint32_t));
-	if(win == NULL)
-	{
-		printf( "Not enough memory for cropped_window.\n");
-		exit(1);
-	}
-
-	for(uint32_t i = 0; i < nData; ++i)
-	{
-		idx = Wins[INDEX(0,i,4)]-1;
-		x1  = Wins[INDEX(1,i,4)]-1;
-		y1  = Wins[INDEX(2,i,4)]-1;
-		mirror = Wins[INDEX(3,i,4)];
-
-		img_ptr = &Images[idx*im_H*im_W];
-
-		cnt0 = 0;
-
-		if(mirror == 0)
-		{
-			for(x=x1; x < x1+win_W; x++)
-				for(y=y1; y < y1+win_H; y++)
-					win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
-		} else {
-			for(x=x1+win_W-1; x >= x1; x--)
-				for(y=y1; y < y1+win_H; y++)
-					win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
-		}
-		liblbp_pyr_features(&Features[nDim*i], nDim, win, win_H, win_W);
-	}
-	free(win);
-
-	Psi->data = Features;
+  char * Features;
+  const uint8_t * Images = model->normalizedImageFrame;
+  uint32_t im_H = (uint32_t)model->data.imSize[0]; uint32_t im_W = (uint32_t)model->data.imSize[1];
+  const uint32_t * Wins = model->data.lbp[lbpidx].wins;
+  uint16_t win_H = (uint16_t)model->data.lbp[lbpidx].winSize[0]; uint16_t win_W = (uint16_t)model->data.lbp[lbpidx].winSize[1];
+  uint16_t nPyramids = model->data.lbp[lbpidx].hop;
+  uint32_t nDim = liblbp_pyr_get_dim(win_H, win_W, nPyramids); uint32_t nData = model->data.lbp[lbpidx].WINS_COLS;
+
+  Features = (char*)calloc(nDim*nData, sizeof(char));
+  if (Features == NULL)
+    throw std::runtime_error("Not enough memory for LBP features.");
+  Psi->PSI_ROWS = nDim; Psi->PSI_COLS = nData;
+
+  uint32_t cnt0, mirror, x, x1, y, y1, idx, *win;
+  const uint8_t *img_ptr;
+
+  win = (uint32_t*)malloc(win_H*win_W*sizeof(uint32_t));
+  if(win == NULL)
+    throw std::runtime_error("Not enough memory for cropped_window.");
+
+  for(uint32_t i = 0; i < nData; ++i)
+  {
+    idx = Wins[INDEX(0,i,4)]-1;
+    x1  = Wins[INDEX(1,i,4)]-1;
+    y1  = Wins[INDEX(2,i,4)]-1;
+    mirror = Wins[INDEX(3,i,4)];
+
+    img_ptr = &Images[idx*im_H*im_W];
+
+    cnt0 = 0;
+
+    if(mirror == 0) {
+      for(x=x1; x < x1+win_W; x++)
+        for(y=y1; y < y1+win_H; y++)
+          win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
+    } else {
+      for(x=x1+win_W-1; x >= x1; x--)
+        for(y=y1; y < y1+win_H; y++)
+          win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
+    }
+    liblbp_pyr_features(&Features[nDim*i], nDim, win, win_H, win_W);
+  }
+  free(win);
+
+  Psi->data = Features;
 }
 
 void flandmark_get_psi_mat_sparse(FLANDMARK_PSI_SPARSE* Psi, FLANDMARK_Model* model, int lbpidx)
 {
-	t_index * Features;
-	uint8_t * Images = model->normalizedImageFrame;
-	uint32_t im_H = (uint32_t)model->data.imSize[0];
-	uint32_t im_W = (uint32_t)model->data.imSize[1];
-	uint32_t * Wins = model->data.lbp[lbpidx].wins;
-	uint16_t win_H = (uint16_t)model->data.lbp[lbpidx].winSize[0];
-	uint16_t win_W = (uint16_t)model->data.lbp[lbpidx].winSize[1];
-	uint16_t nPyramids = model->data.lbp[lbpidx].hop;
-	uint32_t nDim = liblbp_pyr_get_dim(win_H, win_W, nPyramids)/256;
-	uint32_t nData = model->data.lbp[lbpidx].WINS_COLS;
-
-    uint32_t cnt0, mirror, x, x1, y, y1, idx, *win;
-	uint8_t *img_ptr;
-
-	Features = (t_index*)calloc(nDim*nData, sizeof(t_index));
-	if (Features == NULL)
-	{
-		printf( "Not enough memory for LBP features.\n");
-		exit(1);
-	}
-
-	win = (uint32_t*)calloc(win_H*win_W, sizeof(uint32_t));
-	if(win == NULL)
-	{
-		printf( "Not enough memory for cropped_window.\n");
-		exit(1);
-	}
-
-	for(uint32_t i = 0; i < nData; ++i)
-	{
-		idx = Wins[INDEX(0,i,4)]-1;
-		x1  = Wins[INDEX(1,i,4)]-1;
-		y1  = Wins[INDEX(2,i,4)]-1;
-		mirror = Wins[INDEX(3,i,4)];
-
-		img_ptr = &Images[idx*im_H*im_W];
-
-		cnt0 = 0;
-
-		if(mirror == 0)
-		{
-			for(x=x1; x < x1+win_W; x++)
-				for(y=y1; y < y1+win_H; y++)
-					win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
-		} else {
-			for(x=x1+win_W-1; x >= x1; x--)
-				for(y=y1; y < y1+win_H; y++)
-					win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
-		}
-		liblbp_pyr_features_sparse(&Features[nDim*i], nDim, win, win_H, win_W);
-	}
-
-	Psi->PSI_COLS = nData;
-	Psi->PSI_ROWS = nDim;
-	Psi->idxs = Features;
-
-	free(win);
+  t_index * Features;
+  uint8_t * Images = model->normalizedImageFrame;
+  uint32_t im_H = (uint32_t)model->data.imSize[0];
+  uint32_t im_W = (uint32_t)model->data.imSize[1];
+  uint32_t * Wins = model->data.lbp[lbpidx].wins;
+  uint16_t win_H = (uint16_t)model->data.lbp[lbpidx].winSize[0];
+  uint16_t win_W = (uint16_t)model->data.lbp[lbpidx].winSize[1];
+  uint16_t nPyramids = model->data.lbp[lbpidx].hop;
+  uint32_t nDim = liblbp_pyr_get_dim(win_H, win_W, nPyramids)/256;
+  uint32_t nData = model->data.lbp[lbpidx].WINS_COLS;
+
+  uint32_t cnt0, mirror, x, x1, y, y1, idx, *win;
+  uint8_t *img_ptr;
+
+  Features = (t_index*)calloc(nDim*nData, sizeof(t_index));
+  if (Features == NULL)
+    throw std::runtime_error("Not enough memory for LBP features.");
+
+  win = (uint32_t*)calloc(win_H*win_W, sizeof(uint32_t));
+  if(win == NULL)
+    throw std::runtime_error("Not enough memory for cropped_window.");
+
+  for(uint32_t i = 0; i < nData; ++i)
+  {
+    idx = Wins[INDEX(0,i,4)]-1;
+    x1  = Wins[INDEX(1,i,4)]-1;
+    y1  = Wins[INDEX(2,i,4)]-1;
+    mirror = Wins[INDEX(3,i,4)];
+
+    img_ptr = &Images[idx*im_H*im_W];
+
+    cnt0 = 0;
+
+    if(mirror == 0){
+      for(x=x1; x < x1+win_W; x++)
+        for(y=y1; y < y1+win_H; y++)
+          win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
+    } else {
+      for(x=x1+win_W-1; x >= x1; x--)
+        for(y=y1; y < y1+win_H; y++)
+          win[cnt0++] = img_ptr[INDEX(y,x,im_H)];
+    }
+    liblbp_pyr_features_sparse(&Features[nDim*i], nDim, win, win_H, win_W);
+  }
+
+  Psi->PSI_COLS = nData;
+  Psi->PSI_ROWS = nDim;
+  Psi->idxs = Features;
+
+  free(win);
 }
 
 void flandmark_argmax(double *smax, FLANDMARK_Options *options, const int *mapTable, FLANDMARK_PSI_SPARSE *Psi_sparse, double **q, double **g)
@@ -776,39 +692,35 @@ void flandmark_argmax(double *smax, FLANDMARK_Options *options, const int *mapTa
 
     double * s1 = (double *)calloc(2*q1_length, sizeof(double));
     double * s1_maxs = (double *)calloc(q1_length, sizeof(double));
-    for (int i = 0; i < q1_length; ++i)
-    {
-        // dot product <g_5, PsiGS1>
-        flandmark_maximize_gdotprod(
-                //s2_maxs, s2_idxs,
-                &s1[INDEX(0, i, 2)], (double*)&s1[INDEX(1, i, 2)],
-                q[5], g[4], options->PsiGS1[INDEX(i, 0, options->PSIG_ROWS[1])].disp,
-                options->PsiGS1[INDEX(i, 0, options->PSIG_ROWS[1])].COLS, tsize
-                );
-        s1[INDEX(0, i, 2)] += q[1][i];
+    for (int i = 0; i < q1_length; ++i) {
+      // dot product <g_5, PsiGS1>
+      flandmark_maximize_gdotprod(
+              //s2_maxs, s2_idxs,
+              &s1[INDEX(0, i, 2)], (double*)&s1[INDEX(1, i, 2)],
+              q[5], g[4], options->PsiGS1[INDEX(i, 0, options->PSIG_ROWS[1])].disp,
+              options->PsiGS1[INDEX(i, 0, options->PSIG_ROWS[1])].COLS, tsize
+              );
+      s1[INDEX(0, i, 2)] += q[1][i];
     }
-    for (int i = 0; i < q1_length; ++i)
-    {
-        s1_maxs[i] = s1[INDEX(0, i, 2)];
+    for (int i = 0; i < q1_length; ++i) {
+      s1_maxs[i] = s1[INDEX(0, i, 2)];
     }
 
     // right branch (s2->s6) - store maximum and index of s6 for all positions of s2
     int q2_length = Psi_sparse[2].PSI_COLS;
     double * s2 = (double *)calloc(2*q2_length, sizeof(double));
     double * s2_maxs = (double *)calloc(q2_length, sizeof(double));
-    for (int i = 0; i < q2_length; ++i)
-    {
-        // dot product <g_6, PsiGS2>
-        flandmark_maximize_gdotprod(
-                //s2_maxs, s2_idxs,
-                &s2[INDEX(0, i, 2)], (double*)&s2[INDEX(1, i, 2)],
-                q[6], g[5], options->PsiGS2[INDEX(i, 0, options->PSIG_ROWS[2])].disp,
-                options->PsiGS2[INDEX(i, 0, options->PSIG_ROWS[2])].COLS, tsize);
-        s2[INDEX(0, i, 2)] += q[2][i];
+    for (int i = 0; i < q2_length; ++i){
+      // dot product <g_6, PsiGS2>
+      flandmark_maximize_gdotprod(
+              //s2_maxs, s2_idxs,
+              &s2[INDEX(0, i, 2)], (double*)&s2[INDEX(1, i, 2)],
+              q[6], g[5], options->PsiGS2[INDEX(i, 0, options->PSIG_ROWS[2])].disp,
+              options->PsiGS2[INDEX(i, 0, options->PSIG_ROWS[2])].COLS, tsize);
+      s2[INDEX(0, i, 2)] += q[2][i];
     }
-    for (int i = 0; i < q2_length; ++i)
-    {
-        s2_maxs[i] = s2[INDEX(0, i, 2)];
+    for (int i = 0; i < q2_length; ++i){
+      s2_maxs[i] = s2[INDEX(0, i, 2)];
     }
 
     // the root s0 and its connections
@@ -816,8 +728,7 @@ void flandmark_argmax(double *smax, FLANDMARK_Options *options, const int *mapTa
     double maxs0 = -FLT_MAX; int maxs0_idx = -1;
     double maxq10 = -FLT_MAX, maxq20 = -FLT_MAX, maxq30 = -FLT_MAX, maxq40 = -FLT_MAX, maxq70 = -FLT_MAX;
     double * s0 = (double *)calloc(M*q0_length, sizeof(double));
-    for (int i = 0; i < q0_length; ++i)
-    {
+    for (int i = 0; i < q0_length; ++i){
         // q10
         maxq10 = -FLT_MAX;
         flandmark_maximize_gdotprod(
@@ -851,17 +762,15 @@ void flandmark_argmax(double *smax, FLANDMARK_Options *options, const int *mapTa
                 q[7], g[6], options->PsiGS0[INDEX(i, 4, options->PSIG_ROWS[0])].disp,
                 options->PsiGS0[INDEX(i, 4, options->PSIG_ROWS[0])].COLS, tsize);
         // sum q10+q20+q30+q40+q70
-        if (maxs0 < maxq10+maxq20+maxq30+maxq40+maxq70+q[0][i])
-        {
-            maxs0_idx = i;
-            s0[INDEX(0, i, M)] = i;
-            maxs0 = maxq10+maxq20+maxq30+maxq40+maxq70+q[0][i];
+        if (maxs0 < maxq10+maxq20+maxq30+maxq40+maxq70+q[0][i]){
+          maxs0_idx = i;
+          s0[INDEX(0, i, M)] = i;
+          maxs0 = maxq10+maxq20+maxq30+maxq40+maxq70+q[0][i];
         }
     }
 
     // get indices
-    for (int i = 0; i < M; ++i)
-    {
+    for (int i = 0; i < M; ++i){
         indices[i] = (int)s0[INDEX(0, maxs0_idx, M)+i]+1;
     }
 
@@ -873,235 +782,183 @@ void flandmark_argmax(double *smax, FLANDMARK_Options *options, const int *mapTa
     // convert 1D indices to 2D coordinates of estimated positions
     //int * optionsS = &options->S[0];
     const int * optionsS = options->S;
-    for (int i = 0; i < M; ++i)
-    {
+    for (int i = 0; i < M; ++i){
         int rows = optionsS[INDEX(3, i, 4)] - optionsS[INDEX(1, i, 4)] + 1;
-        smax[INDEX(0, i, 2)] = float(COL(indices[i], rows) + optionsS[INDEX(0, i, 4)]);
-        smax[INDEX(1, i, 2)] = float(ROW(indices[i], rows) + optionsS[INDEX(1, i, 4)]);
+        // MG: changed order of returned landmarks to be (y,x)
+        smax[INDEX(1, i, 2)] = float(COL(indices[i], rows) + optionsS[INDEX(0, i, 4)]);
+        smax[INDEX(0, i, 2)] = float(ROW(indices[i], rows) + optionsS[INDEX(1, i, 4)]);
     }
     free(indices);
 }
 
-int flandmark_detect_base(uint8_t* face_image, FLANDMARK_Model* model, double * landmarks)
+void flandmark_detect_base(uint8_t* face_image, FLANDMARK_Model* model, double* landmarks)
 {
-	const int M = model->data.options.M;
-    const double * W = model->W;
-	int tsize = -1, cols = -1, rows = -1;
-    const int * mapTable = model->data.mapTable;
-
-	if (!model->normalizedImageFrame)
-	{
-		model->normalizedImageFrame = face_image;
-	} else {
-		//
-	}
-
-	// get PSI matrix
-    FLANDMARK_PSI_SPARSE * Psi_sparse = (FLANDMARK_PSI_SPARSE*)malloc(M*sizeof(FLANDMARK_PSI_SPARSE));
-	for (int idx = 0; idx < M; ++idx)
-	{
-		flandmark_get_psi_mat_sparse(&Psi_sparse[idx], model, idx);
-	}
-
-	// get Q and G
-	double ** q = (double**)calloc(M, sizeof(double*));
-	double ** g = (double**)calloc((M-1), sizeof(double*));
-
-	int idx_qtemp = 0;
-
-	for (int idx = 0; idx < M; ++idx)
-	{
-		// Q
-		tsize = mapTable[INDEX(idx, 1, M)] - mapTable[INDEX(idx, 0, M)] + 1;
-
-		double * q_temp = (double*)calloc(tsize, sizeof(double));
-		memcpy(q_temp, W+mapTable[INDEX(idx, 0, M)]-1, tsize*sizeof(double));
-
-		// sparse dot product <W_q, PSI_q>
-		cols = Psi_sparse[idx].PSI_COLS; rows = Psi_sparse[idx].PSI_ROWS;
-		uint32_t *psi_temp = Psi_sparse[idx].idxs;
-		q[idx] = (double*)malloc(cols*sizeof(double));
-		for (int i = 0; i < cols; ++i)
-		{
-			double dotprod = 0.0f;
-			for (int j = 0; j < rows; ++j)
-			{
-				idx_qtemp = psi_temp[(rows*i) + j];
-				dotprod += q_temp[ idx_qtemp ];
-			}
-			q[idx][i] = dotprod;
-		}
-		free(q_temp);
-
-		// G
-		if (idx > 0)
-		{
-			tsize = mapTable[INDEX(idx, 3, M)] - mapTable[INDEX(idx, 2, M)] + 1;
-			g[idx - 1] = (double*)malloc(tsize*sizeof(double));
-			memcpy(g[idx - 1], W+mapTable[INDEX(idx, 2, M)]-1, tsize*sizeof(double));
-		}
-	}
+  const int M = model->data.options.M;
+  const double * W = model->W;
+  int tsize = -1, cols = -1, rows = -1;
+  const int * mapTable = model->data.mapTable;
+
+  if (!model->normalizedImageFrame)
+  {
+    model->normalizedImageFrame = face_image;
+  }
+
+  // get PSI matrix
+  FLANDMARK_PSI_SPARSE * Psi_sparse = (FLANDMARK_PSI_SPARSE*)malloc(M*sizeof(FLANDMARK_PSI_SPARSE));
+  for (int idx = 0; idx < M; ++idx)
+  {
+    flandmark_get_psi_mat_sparse(&Psi_sparse[idx], model, idx);
+  }
+
+  // get Q and G
+  double ** q = (double**)calloc(M, sizeof(double*));
+  double ** g = (double**)calloc((M-1), sizeof(double*));
+
+  int idx_qtemp = 0;
+
+  for (int idx = 0; idx < M; ++idx)
+  {
+    // Q
+    tsize = mapTable[INDEX(idx, 1, M)] - mapTable[INDEX(idx, 0, M)] + 1;
+
+    double * q_temp = (double*)calloc(tsize, sizeof(double));
+    memcpy(q_temp, W+mapTable[INDEX(idx, 0, M)]-1, tsize*sizeof(double));
+
+    // sparse dot product <W_q, PSI_q>
+    cols = Psi_sparse[idx].PSI_COLS; rows = Psi_sparse[idx].PSI_ROWS;
+    uint32_t *psi_temp = Psi_sparse[idx].idxs;
+    q[idx] = (double*)malloc(cols*sizeof(double));
+    for (int i = 0; i < cols; ++i)
+    {
+      double dotprod = 0.0f;
+      for (int j = 0; j < rows; ++j)
+      {
+        idx_qtemp = psi_temp[(rows*i) + j];
+        dotprod += q_temp[ idx_qtemp ];
+      }
+      q[idx][i] = dotprod;
+    }
+    free(q_temp);
+
+    // G
+    if (idx > 0)
+    {
+      tsize = mapTable[INDEX(idx, 3, M)] - mapTable[INDEX(idx, 2, M)] + 1;
+      g[idx - 1] = (double*)malloc(tsize*sizeof(double));
+      memcpy(g[idx - 1], W+mapTable[INDEX(idx, 2, M)]-1, tsize*sizeof(double));
+    }
+  }
 
     // argmax
     flandmark_argmax(landmarks, &model->data.options, mapTable, Psi_sparse, q, g);
 
-	// cleanup Psi_sparse[].idxs
-	for (int i = 0; i < M; ++i)
-	{
-		free(Psi_sparse[i].idxs);
-	}
-	free(Psi_sparse);
-
-	// cleanup q
-	for (int i = 0; i < M; ++i)
-	{
-		free(q[i]);
-	}
-	free(q);
-	// cleanup g
-	for (int i = 0; i < M - 1; ++i)
-	{
-		free(g[i]);
-	}
-	free(g);
-
-	return 0;
+  // cleanup Psi_sparse[].idxs
+  for (int i = 0; i < M; ++i)
+  {
+    free(Psi_sparse[i].idxs);
+  }
+  free(Psi_sparse);
+
+  // cleanup q
+  for (int i = 0; i < M; ++i)
+  {
+    free(q[i]);
+  }
+  free(q);
+  // cleanup g
+  for (int i = 0; i < M - 1; ++i)
+  {
+    free(g[i]);
+  }
+  free(g);
+
 }
 
-int flandmark_detect(IplImage *img, int *bbox, FLANDMARK_Model *model, double *landmarks, int *bw_margin)
+void flandmark_detect(const blitz::Array<uint8_t,2>& image, int* bbox, FLANDMARK_Model *model, double *landmarks, int *bw_margin)
 {
-    int retval = 0;
-
-    if (bw_margin)
-	{
-		model->data.options.bw_margin[0] = bw_margin[0];
-		model->data.options.bw_margin[1] = bw_margin[1];
-	}
+  if (bw_margin)
+  {
+    model->data.options.bw_margin[0] = bw_margin[0];
+    model->data.options.bw_margin[1] = bw_margin[1];
+  }
+
+  int corrected_bbx[4];
+
+  // Get normalized image frame
+  flandmark_get_normalized_image_frame(image, bbox, corrected_bbx, model->normalizedImageFrame, model);
+
+  // Call flandmark_detect_base
+  flandmark_detect_base(model->normalizedImageFrame, model, landmarks);
+
+  // transform coordinates of detected landmarks from normalized image frame back to the original image
+  double sx = double(corrected_bbx[3] - corrected_bbx[1]) / model->data.options.bw[0];
+  double sy = double(corrected_bbx[2] - corrected_bbx[0]) / model->data.options.bw[1];
+  for (int i = 0; i < 2*model->data.options.M; i+=2)
+  {
+    landmarks[i]   = landmarks[i]*sy + corrected_bbx[0];
+    landmarks[i+1] = landmarks[i+1]*sx + corrected_bbx[1];
+  }
+}
 
-	// Get normalized image frame
-    retval = flandmark_get_normalized_image_frame(img, bbox, model->bb, model->normalizedImageFrame, model);
-    if (retval)
+void flandmark_maximize_gdotprod(double * maximum, double * idx, const double * first, const double * second, const int * third, const int cols, const int tsize)
+{
+  *maximum = -FLT_MAX;
+  *idx = -1;
+  for (int dp_i = 0; dp_i < cols; ++dp_i)
+  {
+    double dotprod = 0.0f;
+    for (int dp_j = 0; dp_j < tsize; ++dp_j)
     {
-        // flandmark_get_normlalized_image_frame ERROR;
-        return 1;
+      dotprod += second[dp_j]*(double)(third[dp_i*tsize+dp_j]);
     }
-
-    // Call flandmark_detect_base
-    retval = flandmark_detect_base(model->normalizedImageFrame, model, landmarks);
-    if (retval)
+    if (*maximum < first[dp_i]+dotprod)
     {
-        // flandmark_detect_base ERROR
-        return 2;
+      *idx = dp_i;
+      *maximum = first[dp_i]+dotprod;
     }
-
-	// transform coordinates of detected landmarks from normalized image frame back to the original image
-	model->sf[0] = (float)(model->bb[2]-model->bb[0])/model->data.options.bw[0];
-	model->sf[1] = (float)(model->bb[3]-model->bb[1])/model->data.options.bw[1];
-	for (int i = 0; i < 2*model->data.options.M; i += 2)
-	{
-		landmarks[i]   = landmarks[i]*model->sf[0] + model->bb[0];
-		landmarks[i+1] = landmarks[i+1]*model->sf[1] + model->bb[1];
-	}
-
-	return 0;
+  }
 }
 
-void flandmark_maximize_gdotprod(double * maximum, double * idx, const double * first, const double * second, const int * third, const int cols, const int tsize)
+void flandmark_imcrop(const blitz::Array<uint8_t, 2>& input, blitz::Array<uint8_t,2>& output, int* bbx)
 {
-	*maximum = -FLT_MAX;
-	*idx = -1;
-	for (int dp_i = 0; dp_i < cols; ++dp_i)
-	{
-		double dotprod = 0.0f;
-		for (int dp_j = 0; dp_j < tsize; ++dp_j)
-		{
-			dotprod += second[dp_j]*(double)(third[dp_i*tsize+dp_j]);
-		}
-		if (*maximum < first[dp_i]+dotprod)
-		{
-			*idx = dp_i;
-			*maximum = first[dp_i]+dotprod;
-		}
-	}
-}
+  if (bbx[0] < 0 or bbx[2] >= input.extent(0) or bbx[1] < 0 or bbx[3] >= input.extent(1))
+    throw std::runtime_error("Bounding box exceeds image resolution");
 
-//int flandmark_imcrop(IplImage *input, IplImage *output, const CvRect region, FLANDMARK_Model *model)
-int flandmark_imcrop(IplImage *input, IplImage *output, const CvRect region)
-{
-	if (input->width <= 0 || input->height <= 0 || region.width <= 0 || region.height <= 0)
-	{
-		return 1;
-	}
-
-	if (input->depth != IPL_DEPTH_8U)
-	{
-		return 1;
-	}
-
-	cvSetImageROI(input, region);
-    if (output->width < region.width || output->height < region.height)
-	{
-		cvReleaseImage(&output);
-        output = cvCreateImage(cvSize(region.width, region.height), IPL_DEPTH_8U, 1);
-	} else {
-		output->width = region.width;
-		output->height = region.height;
-	}
-	cvCopy(input, output, NULL);
-	cvResetImageROI(input);
-
-	return 0;
+  output.resize(bbx[2]-bbx[0]+1, bbx[3]-bbx[1]+1);
+  blitz::Range a = blitz::Range::all();
+  output(a,a) = input(blitz::Range(bbx[0], bbx[2]), blitz::Range(bbx[1], bbx[3]));
 }
 
-int flandmark_get_normalized_image_frame(IplImage *input, const int bbox[], double *bb, uint8_t *face_img, FLANDMARK_Model *model)
+void flandmark_get_normalized_image_frame(const blitz::Array<uint8_t, 2>& input, const int bbox[], int *corrected_bbx, uint8_t *face_img, FLANDMARK_Model *model)
 {
-	bool flag;
-	int d[2];
-	double c[2], nd[2];
-
-	// extend bbox by bw_margin
-	d[0] = bbox[2]-bbox[0]+1;  d[1] = bbox[3]-bbox[1]+1;
-	c[0] = (bbox[2]+bbox[0])/2.0f; c[1] = (bbox[3]+bbox[1])/2.0f;
-	nd[0] = d[0]*model->data.options.bw_margin[0]/100.0f + d[0];
-	nd[1] = d[1]*model->data.options.bw_margin[1]/100.0f + d[1];
-
-    bb[0] = (c[0] - nd[0]/2.0f);
-    bb[1] = (c[1] - nd[1]/2.0f);
-    bb[2] = (c[0] + nd[0]/2.0f);
-    bb[3] = (c[1] + nd[1]/2.0f);
-
-    flag = bb[0] > 0 && bb[1] > 0 && bb[2] < input->width && bb[3] < input->height
-		&& bbox[0] > 0 && bbox[1] > 0 && bbox[2] < input->width && bbox[3] < input->height;
-
-	if (!flag)
-	{
-		return 1;
-	}
-
-    IplImage *croppedImage = cvCreateImage(cvSize(input->width, input->height), IPL_DEPTH_8U, 1);
-
-    IplImage *resizedImage = cvCreateImage(cvSize(model->data.options.bw[0], model->data.options.bw[1]), IPL_DEPTH_8U, 1);
-
-	// crop and resize image to normalized frame
-    if(flandmark_imcrop(input, croppedImage, cvRect((int)bb[0], (int)bb[1], (int)bb[2]-(int)bb[0]+1, (int)bb[3]-(int)bb[1]+1)))
-	{
-		// something was bad
-		return 1;
-	}
-    // resize
-    cvResize(croppedImage, resizedImage, CV_INTER_CUBIC);
-
-	// tranform IplImage to simple 1D uint8 array representing 2D uint8 normalized image frame
-	for (int x = 0; x < model->data.options.bw[0]; ++x)
-	{
-		for (int y = 0; y < model->data.options.bw[1]; ++y)
-		{
-            face_img[INDEX(x, y, model->data.options.bw[1])] = (uint8_t)((resizedImage->imageData + resizedImage->widthStep*x)[y]);
-		}
-	}
-
-    cvReleaseImage(&croppedImage);
-    cvReleaseImage(&resizedImage);
-
-	return 0;
+  int d[2];
+  double c[2], nd[2];
+
+  // extend bbox by bw_margin
+  d[0] = bbox[2]-bbox[0]+1;
+  d[1] = bbox[3]-bbox[1]+1;
+  c[0] = (bbox[2]+bbox[0])/2.;
+  c[1] = (bbox[3]+bbox[1])/2.;
+  nd[0] = d[0]*model->data.options.bw_margin[1]/100. + d[0];
+  nd[1] = d[1]*model->data.options.bw_margin[0]/100. + d[1];
+
+  corrected_bbx[0] = int(c[0] - nd[0]/2.);
+  corrected_bbx[1] = int(c[1] - nd[1]/2.);
+  corrected_bbx[2] = int(c[0] + nd[0]/2.);
+  corrected_bbx[3] = int(c[1] + nd[1]/2.);
+
+  blitz::Array<uint8_t, 2> croppedImage;
+  blitz::Array<double, 2> scaledImage(model->data.options.bw[1], model->data.options.bw[0]);
+
+  flandmark_imcrop(input, croppedImage, corrected_bbx);
+  bob::ip::base::scale(croppedImage, scaledImage);
+
+  // tranform blitz array to simple 1D uint8 array representing 2D uint8 normalized image frame
+  for (int x = 0; x < model->data.options.bw[0]; ++x){
+    for (int y = 0; y < model->data.options.bw[1]; ++y){
+       face_img[INDEX(x, y, model->data.options.bw[1])] = (uint8_t)round(scaledImage(y,x));
+    }
+  }
 }
+
+} } } // namespace bob ip flandmark
diff --git a/bob/ip/flandmark/cpp/flandmark_detector.h b/bob/ip/flandmark/cpp/flandmark_detector.h
index 94de22320e1e44d276d9d627ec97e62affb48363..b93f511dfea1d1ad78d6a4048883e0d5c04a746f 100644
--- a/bob/ip/flandmark/cpp/flandmark_detector.h
+++ b/bob/ip/flandmark/cpp/flandmark_detector.h
@@ -12,14 +12,15 @@
 #define __FLANDMARK_DETECTOR_H_
 
 #include <stdint.h>
-#include <cv.h>
-#include <cvaux.h>
+#include <blitz/array.h>
 
 // index row-order matrices
 #define INDEX(ROW, COL, NUM_ROWS) ((COL)*(NUM_ROWS)+(ROW))
 #define ROW(IDX, ROWS) (((IDX)-1) % (ROWS))
 #define COL(IDX, ROWS) (((IDX)-1) / (ROWS))
 
+namespace bob { namespace ip { namespace flandmark {
+
 typedef struct psig_struct {
     int * disp;
     int ROWS, COLS;
@@ -52,8 +53,6 @@ typedef struct model_struct {
     int W_ROWS, W_COLS;
     FLANDMARK_Data data;
     uint8_t *normalizedImageFrame;
-    double *bb;
-    float *sf;
 } FLANDMARK_Model;
 
 typedef struct psi_struct {
@@ -156,13 +155,13 @@ void flandmark_maximize_gdotprod(double *maximum, double *idx, const double *fir
  *
  *
  */
-int flandmark_get_normalized_image_frame(IplImage *input, const int bbox[], double *bb, uint8_t *face_img, FLANDMARK_Model *model);
+void flandmark_get_normalized_image_frame(const blitz::Array<uint8_t,2>& input, const int bbox[], int *bb, uint8_t *face_img, FLANDMARK_Model *model);
 
 /**
  * Function imcrop
  *
  */
-int flandmark_imcrop(IplImage *input, IplImage *output, const CvRect region);
+void flandmark_imcrop(const blitz::Array<uint8_t,2>& input, blitz::Array<double,2>& output, const int* bbx);
 
 /**
  * Function argmax
@@ -180,7 +179,7 @@ void flandmark_argmax(double *smax, FLANDMARK_Options *options, const int *mapTa
  * \param[in, out] int array representing 2D array of size [2 x options.M] with estimated positions of landmarks
  * \return int indicator of success or fail of the detection
  */
-int flandmark_detect_base(uint8_t *face_image, FLANDMARK_Model *model, double *landmarks);
+void flandmark_detect_base(uint8_t *face_image, FLANDMARK_Model *model, double *landmarks);
 
 /**
  * Function flandmark_detect
@@ -188,6 +187,8 @@ int flandmark_detect_base(uint8_t *face_image, FLANDMARK_Model *model, double *l
  * Estimates positions of facial landmarks given the image and the bounding box of the detected face
  *
  */
-int flandmark_detect(IplImage *img, int * bbox, FLANDMARK_Model *model, double *landmarks, int * bw_margin = 0);
+void flandmark_detect(const blitz::Array<uint8_t,2>& img, int * bbox, FLANDMARK_Model *model, double *landmarks, int * bw_margin = 0);
+
+} } } // namespace bob ip flandmark
 
 #endif // __LIBFLD_DETECTOR_H_
diff --git a/bob/ip/flandmark/flandmark.cpp b/bob/ip/flandmark/flandmark.cpp
index 6aee28857aab2498088d5be4af9b701090f18efc..d7964b5bcab2efee652122f01105d9631b8177ac 100644
--- a/bob/ip/flandmark/flandmark.cpp
+++ b/bob/ip/flandmark/flandmark.cpp
@@ -17,7 +17,7 @@
 
 #include <cstring>
 
-#include "flandmark_detector.h"
+#include "cpp/flandmark_detector.h"
 
 /******************************************
  * Implementation of Localizer base class *
@@ -26,85 +26,66 @@
 #define CLASS_NAME "Flandmark"
 
 static auto s_class = bob::extension::ClassDoc(
-    BOB_EXT_MODULE_PREFIX "." CLASS_NAME,
-
-    "A key-point localization for faces using Flandmark",
-
-    "This class can be used to locate facial landmarks on pre-detected faces. "
-    "You input an image and a bounding-box specification and it returns you the "
-    "positions for multiple key-points for the given face image.\n"
-    "\n"
-    "Consult http://cmp.felk.cvut.cz/~uricamic/flandmark/index.php for more "
-    "information.\n"
-    "\n"
+  BOB_EXT_MODULE_PREFIX "." CLASS_NAME,
+
+  "A key-point localization for faces using Flandmark",
+
+  "This class can be used to locate facial landmarks on pre-detected faces. "
+  "You input an image and a bounding-box specification and it returns you the "
+  "positions for multiple key-points for the given face image.\n"
+  "\n"
+  "Consult http://cmp.felk.cvut.cz/~uricamic/flandmark/index.php for more "
+  "information.\n"
+  "\n"
+)
+.add_constructor(
+  bob::extension::FunctionDoc(
+    CLASS_NAME,
+    "Constructor",
+    "Initializes the key-point locator with a model."
     )
-    .add_constructor(
-        bob::extension::FunctionDoc(
-          CLASS_NAME,
-          "Constructor",
-          "Initializes the key-point locator with a model."
-          )
-        .add_prototype("[model]", "")
-        .add_parameter("model", "str (path), optional", "Path to the localization model. If not set (or set to ``None``), then use the default localization model, stored on the class variable ``__default_model__``)")
-        )
-    ;
+  .add_prototype("[model]", "")
+  .add_parameter("model", "str (path), optional", "Path to the localization model. If not set (or set to ``None``), then use the default localization model, stored on the class variable ``__default_model__``)")
+);
 
 typedef struct {
   PyObject_HEAD
-  FLANDMARK_Model* flandmark;
+  bob::ip::flandmark::FLANDMARK_Model* flandmark;
   char* filename;
 } PyBobIpFlandmarkObject;
 
-static int PyBobIpFlandmark_init
-(PyBobIpFlandmarkObject* self, PyObject* args, PyObject* kwds) {
-
+static int PyBobIpFlandmark_init(PyBobIpFlandmarkObject* self, PyObject* args, PyObject* kwds) {
+BOB_TRY
   /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {"model", 0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
+  char** kwlist = s_class.kwlist();
 
-  PyObject* model = 0;
+  const char* model = 0;
+  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &model)) return -1;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist,
-        &PyBobIo_FilenameConverter, &model)) return -1;
-
-  if (!model) { //use what is stored in __default_model__
-    PyObject* default_model = PyObject_GetAttrString((PyObject*)self,
-        "__default_model__");
+  if (!model) {
+    //use what is stored in __default_model__
+    PyObject* default_model = PyObject_GetAttrString((PyObject*)self,  "_default_model");
     if (!default_model) {
-      PyErr_Format(PyExc_RuntimeError, "`%s' needs a model to properly initialize, but the user has not passed one and `__default_model__' is not properly set", Py_TYPE(self)->tp_name);
+      PyErr_Format(PyExc_RuntimeError, "`%s' needs a model to properly initialize, but the user has not passed one and `_default_model' is not properly set", Py_TYPE(self)->tp_name);
       return -1;
     }
+    auto default_model_ = make_safe(default_model);
 
-    auto ok = PyBobIo_FilenameConverter(default_model, &model);
-    Py_DECREF(default_model);
-
-    if (!ok || !model) return -1;
+    model = PyString_AS_STRING(default_model);
   }
 
-  const char* c_filename = 0;
-
-# if PY_VERSION_HEX >= 0x03000000
-  c_filename = PyBytes_AS_STRING(model);
-# else
-  c_filename = PyString_AS_STRING(model);
-# endif
-  Py_DECREF(model);
-
-  //now we have a filename we can use
-  if (!c_filename) return -1;
-
-  self->flandmark = flandmark_init(c_filename);
-  if (!self->flandmark) {
-    PyErr_Format(PyExc_RuntimeError, "`%s' could not initialize from model file `%s'", Py_TYPE(self)->tp_name, c_filename);
+  self->flandmark = bob::ip::flandmark::flandmark_init(model);
+  if (!self->flandmark){
+    PyErr_Format(PyExc_RuntimeError, "`%s' could not initialize from model file `%s'", Py_TYPE(self)->tp_name, model);
     return -1;
   }
 
   //flandmark is now initialized, set filename
-  self->filename = strndup(c_filename, 256);
+  self->filename = strndup(model, 256);
 
   //all good, flandmark is ready
   return 0;
-
+BOB_CATCH_MEMBER("constructor", -1)
 }
 
 static void PyBobIpFlandmark_delete (PyBobIpFlandmarkObject* self) {
@@ -115,153 +96,79 @@ static void PyBobIpFlandmark_delete (PyBobIpFlandmarkObject* self) {
   Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
-static void delete_image(IplImage* i) {
-  cvReleaseImage(&i);
-}
-
-/**
- * Returns a list of key-point annotations given an image and an iterable over
- * bounding boxes.
- */
-static PyObject* call(PyBobIpFlandmarkObject* self,
-    boost::shared_ptr<IplImage> image, int nbbx, boost::shared_array<int> bbx) {
-
-  PyObject* retval = PyTuple_New(nbbx);
-  if (!retval) return 0;
-  auto retval_ = make_safe(retval);
-
-  for (int i=0; i<nbbx; ++i) {
-
-    //allocate output array _and_ Flandmark buffer within a single structure
-    Py_ssize_t shape[2];
-    shape[0] = self->flandmark->data.options.M;
-    shape[1] = 2;
-    PyObject* landmarks = PyArray_SimpleNew(2, shape, NPY_FLOAT64);
-    if (!landmarks) return 0;
-    auto landmarks_ = make_safe(landmarks);
-    double* buffer = reinterpret_cast<double*>(PyArray_DATA((PyArrayObject*)landmarks));
-
-    int result = 0;
-    Py_BEGIN_ALLOW_THREADS
-    result = flandmark_detect(image.get(), &bbx[4*i], self->flandmark, buffer);
-    Py_END_ALLOW_THREADS
-
-    if (result != NO_ERR) {
-      Py_INCREF(Py_None);
-      landmarks = Py_None;
-    }
-    else {
-      //swap keypoint coordinates (x, y) -> (y, x)
-      double tmp;
-      for (int k = 0; k < (2*self->flandmark->data.options.M); k += 2) {
-        tmp         = buffer[k];
-        buffer[k]   = buffer[k+1];
-        buffer[k+1] = tmp;
-      }
-      Py_INCREF(landmarks);
-    }
-
-    PyTuple_SET_ITEM(retval, i, landmarks);
-
-  }
-
-  Py_INCREF(retval);
-  return retval;
-
-}
-
-static auto s_call = bob::extension::FunctionDoc(
-    "locate",
-    "Locates keypoints on a **single** facial bounding-box on the provided image."
-    "This method will locate 8 keypoints inside the bounding-box defined "
-    "for the current input image, organized in this way:\n"
-    "\n"
-    "0. Face center\n"
-    "1. Canthus-rl (inner corner of the right eye).\n"
-    "\n"
-    "   .. note::\n"
-    "      \n"
-    "      The \"right eye\" means the right eye at the face w.r.t. the person "
-    "on the image. That is the left eye in the image, from the viewer's "
-    "perspective.\n"
-    "\n"
-    "2. Canthus-lr (inner corner of the left eye)\n"
-    "3. Mouth-corner-r (right corner of the mouth)\n"
-    "4. Mouth-corner-l (left corner of the mouth)\n"
-    "5. Canthus-rr (outer corner of the right eye)\n"
-    "6. Canthus-ll (outer corner of the left eye)\n"
-    "7. Nose\n"
-    "\n"
-    "Each point is returned as tuple defining the pixel positions in the form "
-    "(y, x).\n"
-    "\n"
-    )
-    .add_prototype("image, y, x, height, width", "landmarks")
-    .add_parameter("image", "array-like (2D, uint8)",
-      "The image Flandmark will operate on")
-    .add_parameter("y, x", "int", "The top left-most corner of the bounding box containing the face image you want to locate keypoints on.")
-    .add_parameter("height, width", "int", "The dimensions accross ``y`` (height) and ``x`` (width) for the bounding box, in number of pixels.")
-    .add_return("landmarks", "array (2D, float64)", "Each row in the output array contains the locations of keypoints in the format ``(y, x)``")
-    ;
-
-static PyObject* PyBobIpFlandmark_call_single(PyBobIpFlandmarkObject* self,
-    PyObject *args, PyObject* kwds) {
-
-  /* Parses input arguments in a single shot */
-  static const char* const_kwlist[] = {"image", "y", "x", "height", "width", 0};
-  static char** kwlist = const_cast<char**>(const_kwlist);
-
-  PyBlitzArrayObject* image = 0;
-  int y = 0;
-  int x = 0;
-  int height = 0;
-  int width = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&iiii", kwlist,
-        &PyBlitzArray_Converter, &image, &y, &x, &height, &width)) return 0;
+static auto s_locate = bob::extension::FunctionDoc(
+  "locate",
+  "Locates keypoints on a **single** facial bounding-box on the provided image.",
+  "This method will locate 8 keypoints inside the bounding-box defined for the current input image, organized in this way:\n"
+  "\n"
+  "0. Face center\n"
+  "1. Canthus-rl (inner corner of the right eye).\n"
+  "\n"
+  "   .. note::\n"
+  "      \n"
+  "      The \"right eye\" means the right eye at the face w.r.t. the person on the image. "
+  "      That is the left eye in the image, from the viewer's perspective.\n"
+  "\n"
+  "2. Canthus-lr (inner corner of the left eye)\n"
+  "3. Mouth-corner-r (right corner of the mouth)\n"
+  "4. Mouth-corner-l (left corner of the mouth)\n"
+  "5. Canthus-rr (outer corner of the right eye)\n"
+  "6. Canthus-ll (outer corner of the left eye)\n"
+  "7. Nose\n"
+  "\n"
+  "Each point is returned as tuple defining the pixel positions in the form ``(y, x)``.",
+  true
+)
+.add_prototype("image, y, x, height, width", "landmarks")
+.add_parameter("image", "array-like (2D, uint8)", "The image Flandmark will operate on")
+.add_parameter("y, x", "int", "The top left-most corner of the bounding box containing the face image you want to locate keypoints on.")
+.add_parameter("height, width", "int", "The dimensions accross ``y`` (height) and ``x`` (width) for the bounding box, in number of pixels.")
+.add_return("landmarks", "array (2D, float64)", "Each row in the output array contains the locations of keypoints in the format ``(y, x)``")
+;
+
+static PyObject* PyBobIpFlandmark_locate(PyBobIpFlandmarkObject* self,  PyObject *args, PyObject* kwds) {
+BOB_TRY
+  char** kwlist = s_locate.kwlist();
+
+  PyBlitzArrayObject* image;
+  int bbx[4];
+
+  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&iiii", kwlist,  &PyBlitzArray_Converter, &image, &bbx[0], &bbx[1], &bbx[2], &bbx[3])) return 0;
+
+  // create bounding box in format (top, left, bottom, right)
+  bbx[2] += bbx[0] - 1;
+  bbx[3] += bbx[1] - 1;
 
   auto image_ = make_safe(image);
 
-  //check
+  // check
   if (image->type_num != NPY_UINT8 || image->ndim != 2) {
     PyErr_Format(PyExc_TypeError, "`%s' input `image' data must be a 2D array with dtype `uint8' (i.e. a gray-scaled image), but you passed a %" PY_FORMAT_SIZE_T "d array with data type `%s'", Py_TYPE(self)->tp_name, image->ndim, PyBlitzArray_TypenumAsString(image->type_num));
     return 0;
   }
 
-  // converts to OpenCV's IplImage
-  boost::shared_ptr<IplImage> cv_image(cvCreateImage(cvSize(image->shape[1], image->shape[0]), IPL_DEPTH_8U, 1), std::ptr_fun(delete_image));
+  // detect
+  std::vector<double> detected(2*self->flandmark->data.options.M);
+  bob::ip::flandmark::flandmark_detect(*PyBlitzArrayCxx_AsBlitz<uint8_t, 2>(image), bbx, self->flandmark, &detected[0]);
 
-  // copy image data aligned (see http://chi3x10.wordpress.com/2008/05/07/be-aware-of-memory-alignment-of-iplimage-in-opencv)
-  for (int yy = 0; yy < image->shape[0]; ++yy)
-    std::copy(reinterpret_cast<char*>(image->data) + yy * image->shape[1], reinterpret_cast<char*>(image->data) + (yy+1) * image->shape[1], cv_image->imageData + yy * cv_image->widthStep);
-
-  //prepares the bbx vector
-  boost::shared_array<int> bbx(new int[4]);
-  bbx[0] = x;
-  bbx[1] = y;
-  bbx[2] = x + width;
-  bbx[3] = y + height;
-
-  PyObject* retval = call(self, cv_image, 1, bbx);
-  if (!retval) return 0;
-
-  //gets the first entry, return it
-  PyObject* retval0 = PyTuple_GET_ITEM(retval, 0);
-  if (!retval0) return 0;
-
-  Py_INCREF(retval0);
-  Py_DECREF(retval);
-
-  return retval0;
+  // extract landmarks
+  blitz::Array<double, 2> landmarks(self->flandmark->data.options.M, 2);
+  for (int k = 0; k < self->flandmark->data.options.M; ++k){
+    landmarks(k,0) = detected[2*k];
+    landmarks(k,1) = detected[2*k+1];
+  }
 
+  return PyBlitzArrayCxx_AsNumpy(landmarks);
+BOB_CATCH_MEMBER("locate", 0)
 };
 
 static PyMethodDef PyBobIpFlandmark_methods[] = {
   {
-    s_call.name(),
-    (PyCFunction)PyBobIpFlandmark_call_single,
+    s_locate.name(),
+    (PyCFunction)PyBobIpFlandmark_locate,
     METH_VARARGS|METH_KEYWORDS,
-    s_call.doc()
+    s_locate.doc()
   },
   {0} /* Sentinel */
 };
@@ -274,8 +181,7 @@ PyObject* PyBobIpFlandmark_Repr(PyBobIpFlandmarkObject* self) {
    * <bob.ip.flandmark(model='...')>
    */
 
-  PyObject* retval = PyUnicode_FromFormat("<%s(model='%s')>",
-      Py_TYPE(self)->tp_name, self->filename);
+  PyObject* retval = PyUnicode_FromFormat("<%s(model='%s')>",  Py_TYPE(self)->tp_name, self->filename);
 
 #if PYTHON_VERSION_HEX < 0x03000000
   if (!retval) return 0;
@@ -289,40 +195,31 @@ PyObject* PyBobIpFlandmark_Repr(PyBobIpFlandmarkObject* self) {
 }
 
 PyTypeObject PyBobIpFlandmark_Type = {
-    PyVarObject_HEAD_INIT(0, 0)
-    s_class.name(),                            /* tp_name */
-    sizeof(PyBobIpFlandmarkObject),            /* tp_basicsize */
-    0,                                         /* tp_itemsize */
-    (destructor)PyBobIpFlandmark_delete,       /* tp_dealloc */
-    0,                                         /* tp_print */
-    0,                                         /* tp_getattr */
-    0,                                         /* tp_setattr */
-    0,                                         /* tp_compare */
-    (reprfunc)PyBobIpFlandmark_Repr,           /* tp_repr */
-    0,                                         /* tp_as_number */
-    0,                                         /* tp_as_sequence */
-    0,                                         /* tp_as_mapping */
-    0,                                         /* tp_hash */
-    (ternaryfunc)PyBobIpFlandmark_call_single, /* tp_call */
-    (reprfunc)PyBobIpFlandmark_Repr,           /* tp_str */
-    0,                                         /* tp_getattro */
-    0,                                         /* tp_setattro */
-    0,                                         /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /* tp_flags */
-    s_class.doc(),                             /* tp_doc */
-    0,                                         /* tp_traverse */
-    0,                                         /* tp_clear */
-    0,                                         /* tp_richcompare */
-    0,                                         /* tp_weaklistoffset */
-    0,                                         /* tp_iter */
-    0,                                         /* tp_iternext */
-    PyBobIpFlandmark_methods,                  /* tp_methods */
-    0,                                         /* tp_members */
-    0,                                         /* tp_getset */
-    0,                                         /* tp_base */
-    0,                                         /* tp_dict */
-    0,                                         /* tp_descr_get */
-    0,                                         /* tp_descr_set */
-    0,                                         /* tp_dictoffset */
-    (initproc)PyBobIpFlandmark_init,           /* tp_init */
+  PyVarObject_HEAD_INIT(0, 0)
+  0
 };
+
+bool init_PyBobIpFlandmark(PyObject* module){
+  // initialize the type struct
+  PyBobIpFlandmark_Type.tp_name = s_class.name();
+  PyBobIpFlandmark_Type.tp_basicsize = sizeof(PyBobIpFlandmarkObject);
+  PyBobIpFlandmark_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+  PyBobIpFlandmark_Type.tp_doc = s_class.doc();
+  PyBobIpFlandmark_Type.tp_dict = PyDict_New();
+
+  // set the functions
+  PyBobIpFlandmark_Type.tp_new = PyType_GenericNew;
+  PyBobIpFlandmark_Type.tp_init = reinterpret_cast<initproc>(PyBobIpFlandmark_init);
+  PyBobIpFlandmark_Type.tp_dealloc = reinterpret_cast<destructor>(PyBobIpFlandmark_delete);
+  PyBobIpFlandmark_Type.tp_methods = PyBobIpFlandmark_methods;
+  PyBobIpFlandmark_Type.tp_call = reinterpret_cast<ternaryfunc>(PyBobIpFlandmark_locate);
+  PyBobIpFlandmark_Type.tp_str = reinterpret_cast<reprfunc>(PyBobIpFlandmark_Repr);
+  PyBobIpFlandmark_Type.tp_repr = reinterpret_cast<reprfunc>(PyBobIpFlandmark_Repr);
+
+  // check that everything is fine
+  if (PyType_Ready(&PyBobIpFlandmark_Type) < 0) return false;
+
+  // add the type to the module
+  Py_INCREF(&PyBobIpFlandmark_Type);
+  return PyModule_AddObject(module, "Flandmark", (PyObject*)&PyBobIpFlandmark_Type) >= 0;
+}
diff --git a/bob/ip/flandmark/main.cpp b/bob/ip/flandmark/main.cpp
index 9a18a8049833a27c0fabd42851bb5a8b0db215f0..ab2dc82cea3ce326dc067eb4ad61b174e0b94f4f 100644
--- a/bob/ip/flandmark/main.cpp
+++ b/bob/ip/flandmark/main.cpp
@@ -15,24 +15,24 @@
 #include <bob.extension/documentation.h>
 
 extern PyTypeObject PyBobIpFlandmark_Type;
+extern bool init_PyBobIpFlandmark(PyObject*);
 
 static auto s_setter = bob::extension::FunctionDoc(
-    "__set_default_model__",
-    "Internal function to set the default model for the Flandmark class"
-    )
-    .add_prototype("path", "")
-    .add_parameter("path", "str", "The path to the new model file")
-    ;
+  "_set_default_model",
+  "Internal function to set the default model for the Flandmark class"
+)
+.add_prototype("path", "")
+.add_parameter("path", "str", "The path to the new model file")
+;
 
 PyObject* set_flandmark_model(PyObject*, PyObject* o) {
-
-  int ok = PyDict_SetItemString(PyBobIpFlandmark_Type.tp_dict,
-      "__default_model__", o);
+BOB_TRY
+  int ok = PyDict_SetItemString(PyBobIpFlandmark_Type.tp_dict, "_default_model", o);
 
   if (ok == -1) return 0;
 
   Py_RETURN_NONE;
-
+BOB_CATCH_FUNCTION("_set_default_model", 0)
 }
 
 static PyMethodDef module_methods[] = {
@@ -60,12 +60,6 @@ static PyModuleDef module_definition = {
 
 static PyObject* create_module (void) {
 
-  //makes sure that PyBobIpFlandmark_Type has a dictionary on tp_dict
-  PyBobIpFlandmark_Type.tp_dict = PyDict_New();
-  if (!PyBobIpFlandmark_Type.tp_dict) return 0;
-
-  PyBobIpFlandmark_Type.tp_new = PyType_GenericNew;
-  if (PyType_Ready(&PyBobIpFlandmark_Type) < 0) return 0;
 
 # if PY_VERSION_HEX >= 0x03000000
   PyObject* module = PyModule_Create(&module_definition);
@@ -77,9 +71,7 @@ static PyObject* create_module (void) {
 # endif
   if (!module) return 0;
 
-  /* register the types to python */
-  Py_INCREF(&PyBobIpFlandmark_Type);
-  if (PyModule_AddObject(module, "Flandmark", (PyObject *)&PyBobIpFlandmark_Type) < 0) return 0;
+  if (!init_PyBobIpFlandmark(module)) return 0;
 
   /* imports dependencies */
   if (import_bob_blitz() < 0) return 0;
diff --git a/bob/ip/flandmark/test.py b/bob/ip/flandmark/test.py
index bed454ef0c6d9839e2d1358cd1bfcec880e1a756..61c9e7f8dc36f7302f560b809ce6a68b78d06544 100644
--- a/bob/ip/flandmark/test.py
+++ b/bob/ip/flandmark/test.py
@@ -33,23 +33,6 @@ MULTI_BBX = [
     [253, 42, 28, 28],
     ] #from OpenCV's cascade detector
 
-def opencv_detect(image):
-  """Detects a face using OpenCV's cascade detector
-
-  Returns a list of arrays containing (x, y, width, height) for each detected
-  face.
-  """
-
-  from cv2 import CascadeClassifier
-
-  cc = CascadeClassifier(F('haarcascade_frontalface_alt.xml'))
-  return cc.detectMultiScale(
-      image,
-      1.3, #scaleFactor (at each time the image is re-scaled)
-      4, #minNeighbors (around candidate to be retained)
-      0, #flags (normally, should be set to zero)
-      (20,20), #(minSize, maxSize) (of detected objects on that scale)
-      )
 
 def pnpoly(point, vertices):
   """Python translation of the C algorithm taken from:
@@ -80,19 +63,6 @@ def is_inside(point, box, eps=1e-5):
     ], dtype=float)
   return pnpoly((point[1], point[0]), vertices)
 
-def opencv_available(test):
-  """Decorator for detecting if OpenCV/Python bindings are available"""
-  from nose.plugins.skip import SkipTest
-
-  @functools.wraps(test)
-  def wrapper(*args, **kwargs):
-    try:
-      import cv2
-      return test(*args, **kwargs)
-    except ImportError:
-      raise SkipTest("The cv2 module is not available")
-
-  return wrapper
 
 def test_is_inside():
 
@@ -117,19 +87,6 @@ def test_is_outside():
   assert not is_inside((1.5, 1.5), box, eps=1e-10)
   assert not is_inside((-0.5, -0.5), box, eps=1e-10)
 
-@opencv_available
-def test_lena_opencv():
-
-  img = bob.io.base.load(LENA)
-  gray = bob.ip.color.rgb_to_gray(img)
-  (x, y, width, height) = opencv_detect(gray)[0]
-
-  flm = Flandmark()
-  keypoints = flm.locate(gray, y, x, height, width)
-  nose.tools.eq_(keypoints.shape, (8, 2))
-  nose.tools.eq_(keypoints.dtype, 'float64')
-  for k in keypoints:
-    assert is_inside(k, (y, x, height, width), eps=1)
 
 def test_lena():
 
@@ -144,21 +101,6 @@ def test_lena():
   for k in keypoints:
     assert is_inside(k, (y, x, height, width), eps=1)
 
-@opencv_available
-def test_multi_opencv():
-
-  img = bob.io.base.load(MULTI)
-  gray = bob.ip.color.rgb_to_gray(img)
-  bbx = opencv_detect(gray)
-
-  flm = Flandmark()
-  for (x, y, width, height) in bbx:
-    keypoints = flm.locate(gray, y, x, height, width)
-    nose.tools.eq_(keypoints.shape, (8, 2))
-    nose.tools.eq_(keypoints.dtype, 'float64')
-    for k in keypoints:
-      assert is_inside(k, (y, x, height, width), eps=1)
-
 def test_multi():
 
   img = bob.io.base.load(MULTI)
diff --git a/bob/ip/flandmark/version.cpp b/bob/ip/flandmark/version.cpp
index d8b969f19e0dab7fef8d089d3df9c963a8ba915f..254e0167c14620742e9f79e1c61a011e6f900f7a 100644
--- a/bob/ip/flandmark/version.cpp
+++ b/bob/ip/flandmark/version.cpp
@@ -12,8 +12,6 @@
 #include <bob.core/config.h>
 #include <bob.io.base/config.h>
 
-#include <cv.h>
-
 
 static PyObject* build_version_dictionary() {
 
@@ -21,7 +19,6 @@ static PyObject* build_version_dictionary() {
   if (!retval) return 0;
   auto retval_ = make_safe(retval);
 
-  if (!dict_steal(retval, "OpenCV", Py_BuildValue("s", CV_VERSION))) return 0;
   if (!dict_steal(retval, "Blitz++", blitz_version())) return 0;
   if (!dict_steal(retval, "Boost", boost_version())) return 0;
   if (!dict_steal(retval, "Compiler", compiler_version())) return 0;
diff --git a/setup.py b/setup.py
index fa1d32849d5ed3877c3f9372b49df44cedc8a9b2..9dbb352e4565af3ff01764f98d7296744422382f 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@
 """Bindings for flandmark
 """
 
-bob_packages = ['bob.core', 'bob.io.base']
+bob_packages = ['bob.core', 'bob.io.base', 'bob.sp', 'bob.ip.base']
 
 from setuptools import setup, find_packages, dist
 dist.Distribution(dict(setup_requires=['bob.extension', 'bob.blitz'] + bob_packages))
@@ -18,7 +18,7 @@ build_requires = load_requirements()
 # Define package version
 version = open("version.txt").read().rstrip()
 
-packages = ['boost', "opencv>=2.0"]
+packages = ['boost']
 boost_modules = ['system']
 
 setup(
@@ -39,8 +39,6 @@ setup(
     setup_requires = build_requires,
     install_requires = build_requires,
 
-
-
     ext_modules=[
       Extension("bob.ip.flandmark.version",
         [
@@ -54,8 +52,8 @@ setup(
 
       Extension("bob.ip.flandmark._library",
         [
-          "bob/ip/flandmark/flandmark_detector.cpp",
-          "bob/ip/flandmark/liblbp.cpp",
+          "bob/ip/flandmark/cpp/flandmark_detector.cpp",
+          "bob/ip/flandmark/cpp/liblbp.cpp",
           "bob/ip/flandmark/flandmark.cpp",
           "bob/ip/flandmark/main.cpp",
         ],
diff --git a/version.txt b/version.txt
index 0d0f1af82bee4308f9e49b2adb6e4aa498bda98a..1a78b34537ab70360822a5d0733a88ab70b02247 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-2.0.4b0
\ No newline at end of file
+2.1.0b0