pans
2016-12-20 0034d2bcd5408c55feff6d46428df78a0df32008
RtspFace/demo/sample_face_detect.cpp
@@ -1,442 +1,256 @@
#include <stdio.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <stdio.h>
#include <cv_face.h>
#include "time_helper.h"
#include "cv_face.h"
#include <windows.h>
#include <opencv2/opencv.hpp>
#define DEFAULT_THRESHOLD (0.5)
using namespace std;
using namespace cv;
// @获取人脸特征值
// @param bgr_image 需要提取特征值的图片
// @param handle_verify 已经初始化的人脸验证句柄
cv_feature_t * getFeature(Mat bgr_image,cv_handle_t handle_verify) {
//人脸验证
static cv_handle_t handle_verify = NULL;
//数据库操作
static cv_handle_t handle_db = NULL;
//静态人脸识别
static cv_handle_t handle_detect = NULL;
#define _MAX_PATH 260
//提取图片特征值
cv_feature_t *extract_feature(Mat image_color) {
   Mat image_color_color;
   //   cvtColor(image_color, image_color_color, CV_BGR2BGRA);    // CV_PIX_FMT_BGRA8888
   image_color_color = image_color;                          // CV_PIX_FMT_BGR888
   cv_feature_t *p_feature = NULL;
   Mat image_color;
   image_color = bgr_image;
   //调用句柄。用于保存函数及数据的句柄
   cv_handle_t handle_detect = NULL;
   //人脸信息结构体
   cv_face_t *p_face = NULL;
   int face_count = 0;
   //函数返回的错误代码类型
   cv_result_t cv_result = CV_OK;
   char *string_feature;
   do
   {
      // 创建静态图片人脸检测句柄
      cv_result = cv_face_create_detector(&handle_detect, NULL, CV_DETECT_ENABLE_ALIGN_21);
      if (cv_result != CV_OK) {
         fprintf(stderr, "fail to init detect handle, error code %d\n", cv_result);
         break;
      }
      // 人脸检测1.成功返回CV_OK,否则返回错误类型
      cv_result = cv_face_detect(handle_detect, image_color.data, CV_PIX_FMT_BGR888,
         image_color.cols, image_color.rows, image_color.step,
         CV_FACE_UP, &p_face, &face_count);
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_face_detect failed, error code : %d\n", cv_result);
         break;
      }
      if (face_count > 0) {
         //用于表示人脸特征信息
         float score;
         unsigned int feature_length = 0;
         // get feature
         __TIC__();
         //提取人脸特征1,可以把返回数组编码成字符串后存储起来以便以后使用
         cv_result = cv_verify_get_feature(handle_verify, image_color.data, CV_PIX_FMT_BGR888,
            image_color.cols, image_color.rows, image_color.step, p_face,
            &p_feature, &feature_length);
         __TOC__();
         if (cv_result != CV_OK) {
            fprintf(stderr, "cv_verify_get_feature failed, error code %d\n", cv_result);
            break;
         }
         if (feature_length > 0 ) {
            // test serial and deserial
            string_feature = new char[CV_ENCODE_FEATURE_SIZE(p_feature)];
            cv_verify_serialize_feature(p_feature, string_feature);
            //释放提取人脸特征时分配的空间
            cv_verify_release_feature(p_feature);
            break;
         } else {
            fprintf(stderr, "error, the feature length is 0!\n");
         }
         // 释放提取人脸特征时分配的空间
         cv_verify_release_feature(p_feature);
      } else {
         if (face_count == 0) {
            fprintf(stderr, "can't find face in \n");
         }
      }
   } while (0);
   cv_face_release_detector_result(p_face, face_count);
   return string_feature;
}
//测试确定人脸位置
int testface_detect(Mat bgr_image_color,char* output_image_path ){
   int points_size = 106;
   int config;
   if (points_size == 21) {
      config = CV_DETECT_ENABLE_ALIGN_21;
   }
   else if (points_size == 106) {
      config = CV_DETECT_ENABLE_ALIGN_106;
   }
   else {
      fprintf(stderr, "alignment point size error, must be 21 or 106\n");
      return -1;
   }
   // load image
   Mat image_color;
   //   cvtColor(bgr_image_color, image_color, CV_BGR2BGRA);    // CV_PIX_FMT_BGRA8888
   image_color = bgr_image_color;                          // CV_PIX_FMT_BGR888
   // init detect handle
   cv_handle_t handle_detect = NULL;
   cv_result_t cv_result = CV_OK;
   cv_face_t* p_face = NULL;
   int face_count = 0;
   do
   {
      cv_result = cv_face_create_detector(&handle_detect, NULL, config);
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_face_create_detector failed, error code %d\n", cv_result);
         break;
      }
      /*
      * test get and set threshold
      */
      float default_threshold;
      cv_result = cv_face_detect_get_threshold(handle_detect, &default_threshold);
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_face_detect_get_threshold failed, error code %d\n", cv_result);
         break;
      }
      fprintf(stderr, "default threshold : %f\n", default_threshold);
      cv_result = cv_face_detect_set_threshold(handle_detect, default_threshold);
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_face_detect_set_threshold failed, error code %d\n", cv_result);
         break;
      }
      fprintf(stderr, "threshold set : %f\n", default_threshold);
      // detect
      __TIC__();
      cv_result = cv_face_detect(handle_detect, image_color.data, CV_PIX_FMT_BGR888,
         image_color.cols, image_color.rows, image_color.step,
   cv_result_t st_result = CV_OK;
   //检测人脸
   st_result = cv_face_detect(handle_detect, image_color_color.data, CV_PIX_FMT_BGR888,
      image_color_color.cols, image_color_color.rows, image_color_color.step,
         CV_FACE_UP, &p_face, &face_count);
      __TOC__();
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_face_detect error %d\n", cv_result);
         break;
   if (face_count >= 1) {
      //获取人脸特征
      st_result = cv_verify_get_feature(handle_verify,
         (unsigned char *)image_color_color.data, CV_PIX_FMT_BGR888,
         image_color_color.cols, image_color_color.rows, image_color_color.step,
         p_face, &p_feature, NULL);
      if (st_result != CV_OK) {
         fprintf(stderr, "cv_verify_get_feature failed, error code %d\n", st_result);
      }
      if (face_count > 0) {
         // draw result
         for (int i = 0; i < face_count; i++) {
            rectangle(image_color, Point(p_face[i].rect.left, p_face[i].rect.top),
               Point(p_face[i].rect.right, p_face[i].rect.bottom),
               Scalar(0, 255, 0), 2, 8, 0);
            fprintf(stderr, "face number: %d\n", i + 1);
            fprintf(stderr, "face rect: [%d, %d, %d, %d]\n", p_face[i].rect.top,
               p_face[i].rect.left,
               p_face[i].rect.right, p_face[i].rect.bottom);
            fprintf(stderr, "score: %f\n", p_face[i].score);
            fprintf(stderr, "face pose: [yaw: %f, pitch: %f, roll: %f, eye distance: %f]\n",
               p_face[i].yaw,
               p_face[i].pitch, p_face[i].roll, p_face[i].eye_dist);
            fprintf(stderr, "face algin:\n");
            for (unsigned int j = 0; j < p_face[i].points_count; j++) {
               float x = p_face[i].points_array[j].x;
               float y = p_face[i].points_array[j].y;
               fprintf(stderr, "(%.2f, %.2f)\n", x, y);
               circle(image_color, Point2f(x, y), 2, Scalar(0, 0, 255), -1);
            }
            fprintf(stderr, "\n");
         }
         // save image
         imwrite(output_image_path, image_color);
      }
      else {
   } else {
         fprintf(stderr, "can't find face in ");
      }
   } while (0);
   // release the memory of face
   // 释放内存
   cv_face_release_detector_result(p_face, face_count);
   // destroy detect handle
   cv_face_destroy_detector(handle_detect);
   fprintf(stderr, "test finish!\n");
   return 0;
   return p_feature;
}
// @brief 测试人脸对比
// @param bgr_image_1 图像1
// @param bgr_image_1 图像2
int testface_verify(Mat bgr_image_1,Mat bgr_image_2){
//数据库添加数据,并返回记录得id
int db_add(cv_feature_t *p_feature) {
   /*cv_feature_t *p_feature = extract_feature(image_color);
   if (!p_feature) {
   return -1;
   }*/
   int idx;
   cv_result_t cv_result = cv_verify_add_face(handle_db, p_feature, &idx);
   if (cv_result != CV_OK) {
      fprintf(stderr, "cv_verify_add_face failed, error code %d\n", cv_result);
   }
   cv_verify_release_feature(p_feature);
   return idx;
}
   // 保存两个图片的原始数据
   Mat image_color_1,image_color_2;
   //   cvtColor(bgr_image_1, image_color_color_1, CV_BGR2BGRA);    // CV_PIX_FMT_BGRA8888
   image_color_1 = bgr_image_1;                                // CV_PIX_FMT_BGR888
   //   cvtColor(bgr_image_2, image_color_2, CV_BGR2BGRA);
   image_color_2 = bgr_image_2;
   int main_return = -1;
   //调用句柄。用于保存函数及数据的句柄
   cv_handle_t handle_detect = NULL;
   cv_handle_t handle_verify = NULL;
   //人脸信息结构体
   cv_face_t *p_face_1 = NULL;
   cv_face_t *p_face_2 = NULL;
   int face_count_1 = 0;
   int face_count_2 = 0;
   //函数返回的错误代码类型
//根据id删除记录
bool db_del(int idx) {
   if (idx < 0) {
      fprintf(stderr, "invalid idx!\n");
      return false;
   }
   cv_result_t cv_result = CV_OK;
   cv_result = cv_verify_delete_face(handle_db, idx);
   if (cv_result != CV_OK) {
      fprintf(stderr, "cv_verify_delete_face failed, error code %d\n", cv_result);
   } else {
      fprintf(stderr, "delete succeed\n");
   }
}
   do {
      cout<<"a"<<endl;
      // 创建静态图片人脸检测句柄
      cv_result = cv_face_create_detector(&handle_detect, NULL, CV_DETECT_ENABLE_ALIGN_21);
//数据库保存
bool db_save(char *db_path) {
   cv_result_t cv_result = CV_OK;
   cv_result = cv_verify_save_db(handle_db, db_path);
   if (cv_result != CV_OK) {
      fprintf(stderr, "cv_verify_save_db failed, error code %d\n", cv_result);
      return false;
   } else {
      fprintf(stderr, "save done!\n");
   }
   return true;
}
//数据库加载
bool db_load(char *db_path) {
   cv_result_t cv_result = CV_OK;
   cv_result = cv_verify_load_db(handle_db, db_path);
      if (cv_result != CV_OK) {
         fprintf(stderr, "fail to init detect handle, error code %d\n", cv_result);
         break;
      fprintf(stderr, "cv_verify_load_db failed, error code %d\n", cv_result);
      return false;
   } else {
      fprintf(stderr, "load done!\n");
      }
      // 人脸检测1.成功返回CV_OK,否则返回错误类型
      cv_result = cv_face_detect(handle_detect, image_color_1.data, CV_PIX_FMT_BGR888,
         image_color_1.cols, image_color_1.rows, image_color_1.step,
         CV_FACE_UP, &p_face_1, &face_count_1);
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_face_detect failed, error code : %d\n", cv_result);
         break;
   return true;
      }
      // 人脸检测2.成功返回CV_OK,否则返回错误类型
      cv_result = cv_face_detect(handle_detect, image_color_2.data, CV_PIX_FMT_BGR888,
         image_color_2.cols, image_color_2.rows, image_color_2.step,
         CV_FACE_UP, &p_face_2, &face_count_2);
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_face_detect failed, error code : %d\n", cv_result);
         break;
//搜索数据库
bool search_db(Mat image_color,char *db_path) {
   cv_feature_t *p_feature = extract_feature(image_color);
   if (p_feature == NULL) {
      fprintf(stderr, "extract failed !\n");
      return false;
      }
      // 人脸验证
      if (face_count_1 > 0 && face_count_2 > 0) {
         // 创建人脸验证句柄
         cv_result = cv_verify_create_handle(&handle_verify, "../../../models/verify.model");
         if (cv_result != CV_OK)
         {
            fprintf(stderr, "fail to init verify handle, error code %d\n", cv_result);
            break;
         }
         if (handle_verify) {
            int model_version = cv_verify_get_version(handle_verify);
            fprintf(stderr, "verify model version : %d\n", model_version);
            int feature_length = cv_verify_get_feature_length(handle_verify);
            fprintf(stderr, "verify model feature length : %d\n", feature_length);
            //用于表示人脸特征信息
            cv_feature_t *p_feature_1 = NULL, *p_feature_2 = NULL;
            float score;
            unsigned int feature_length_1 = 0, feature_length_2 = 0;
            // get feature
            __TIC__();
            //提取人脸特征1,可以把返回数组编码成字符串后存储起来以便以后使用
            cv_result = cv_verify_get_feature(handle_verify, image_color_1.data, CV_PIX_FMT_BGR888,
               image_color_1.cols, image_color_1.rows, image_color_1.step, p_face_1,
               &p_feature_1, &feature_length_1);
            __TOC__();
            if (cv_result != CV_OK) {
               fprintf(stderr, "cv_verify_get_feature failed, error code %d\n", cv_result);
               break;
            }
            //提取人脸特征1,可以把返回数组编码成字符串后存储起来以便以后使用
            cv_result = cv_verify_get_feature(handle_verify, image_color_2.data, CV_PIX_FMT_BGR888,
               image_color_2.cols, image_color_2.rows, image_color_2.step, p_face_2,
               &p_feature_2, &feature_length_2);
            if (cv_result != CV_OK) {
               fprintf(stderr, "cv_verify_get_feature failed, error code %d\n", cv_result);
               break;
            }
            if (feature_length_1 > 0 && feature_length_2 > 0) {
               cv_feature_header_t *p_feature_header = CV_FEATURE_HEADER(p_feature_1);
               fprintf(stderr, "Feature information:\n");
               fprintf(stderr, "    ver:\t0x%08x\n", p_feature_header->ver);
               fprintf(stderr, "    length:\t%d bytes\n", p_feature_header->len);
               // 人脸验证
               cv_result = cv_verify_compare_feature(handle_verify, p_feature_1,
                  p_feature_2, &score);
   db_load(db_path);
   //查询前10条
   int top_k = 10;
   int *top_idxs = new int[top_k];
   float *top_scores = new float[top_k];
   unsigned int result_length = 0;
   cv_result_t cv_result = cv_verify_search_face(handle_verify, handle_db,
      p_feature, top_k,
      top_idxs, top_scores, &result_length);
               if (cv_result == CV_OK) {
                  fprintf(stderr, "score: %f\n", score);
                  // comapre score with DEFAULT_THRESHOLD
                  // > DEFAULT_THRESHOLD => the same person
                  // < DEFAULT_THRESHOLD => different people
                  if (score > DEFAULT_THRESHOLD)
                     fprintf(stderr, "the same person.\n");
                  else
                     fprintf(stderr, "different people.\n");
                  main_return = 0;  // success
      //输出检查结果
      for (unsigned int t = 0; t < result_length; t++) {
         // const cv_feature_t item = result[t].item;
         fprintf(stderr, "%d\t", top_idxs[t]);
         fprintf(stderr, "%0.2f\n", top_scores[t]);
               }
               else {
                  fprintf(stderr, "cv_verify_compare_feature failed, error code : %d\n", cv_result);
   } else {
      fprintf(stderr, "cv_verify_search_face failed, error code %d\n", cv_result);
   }
   if (top_idxs) {
      delete[]top_idxs;
   }
   if (top_scores) {
      delete[]top_scores;
   }
   cv_verify_release_feature(p_feature);
   return true;
               }
               // test serial and deserial
               char *string_feature_1 = new char[CV_ENCODE_FEATURE_SIZE(p_feature_1)];
               cv_verify_serialize_feature(p_feature_1, string_feature_1);
               cout<<string_feature_1<<endl;
               cv_feature_t *p_feature_new_1 = cv_verify_deserialize_feature(string_feature_1);
               delete[]string_feature_1;
               char *string_feature_2;
               string_feature_2 = new char[CV_ENCODE_FEATURE_SIZE(p_feature_2)];
               cv_verify_serialize_feature(p_feature_2, string_feature_2);
               cout<<string_feature_2<<endl;
               cv_feature_t *p_feature_new_2 = cv_verify_deserialize_feature(string_feature_2);
               delete[]string_feature_2;
               score = 0.0;
               cv_result = cv_verify_compare_feature(handle_verify, p_feature_1,
                  p_feature_2, &score);
               fprintf(stderr, "after serial and deserial the feature compare score is %f  \n", score);
               cin>>string_feature_2;
               //释放提取人脸特征时分配的空间
               cv_verify_release_feature(p_feature_new_1);
               cv_verify_release_feature(p_feature_new_2);
            }
            else {
               fprintf(stderr, "error, the feature length is 0!\n");
            }
            // 释放提取人脸特征时分配的空间
            cv_verify_release_feature(p_feature_1);
            cv_verify_release_feature(p_feature_2);
         }
      }
      else {
         if (face_count_1 == 0) {
            fprintf(stderr, "can't find face in \n");
         }
         if (face_count_2 == 0) {
            fprintf(stderr, "can't find face in \n");
         }
      }
   } while (0);
   // release the memory of face
   cv_face_release_detector_result(p_face_1, face_count_1);
   cv_face_release_detector_result(p_face_2, face_count_2);
   // destroy detect handle
   cv_face_destroy_detector(handle_detect);
   // destroy verify handle
   cv_verify_destroy_handle(handle_verify);
   fprintf(stderr, "test finish!\n");
   return 0;
//批量导入图片进行分析
bool db_gen(char *image_list, char *db_path) {
   bool bresult = true;
   //读取图片列表
   FILE *fp_path = fopen(image_list, "r");
   if(!fp_path) {
      fprintf(stderr, "failed to load %s\n", image_list);
      return false;
}
int main() {
   //人脸特征信息  数据结构
   std::vector<cv_feature_t *> list_feature;
   list_feature.clear();
   //图片入口,现需经过OPENCV处理后被sdk使用。
   char* input_image_path = "../../test_image/face_06.jpg";
   char* output_image_path = "../../test_image/face_06out.jpg";
   for (;;) {
      char image_path[1024];
      int num = fscanf(fp_path, "%s", image_path);
      if (num != 1) {
         bresult = false;
         break;
      }
      fprintf(stderr, "extracting %s\n", image_path);
   // 创建人脸验证句柄并初始化
   //函数返回的错误代码类型
      // get the face feature
      Mat image_color = imread(image_path);
      if (!image_color.data) {
         return NULL;
      }
      cv_feature_t *p_feature = extract_feature(image_color);
      if (!p_feature) {
         fprintf(stderr, "failed to extract image: %s\n", image_path);
         continue;
      }
      list_feature.push_back(p_feature);
   }
   fclose(fp_path);
   cv_verify_destroy_db(handle_db);
   cv_result_t cv_result = CV_OK;
   cv_handle_t handle_verify =NULL;
   cv_verify_create_db(&handle_db);
   //创建新的数据库,应该改为判断,如果数据库存在则进行插入,否则新建。
   if(db_load(db_path)){
      for (int x = 0; x < list_feature.size(); x++) {
         db_add(list_feature[x]);
      }
   }else{
      cv_result = cv_verify_build_db(handle_db, &list_feature[0], list_feature.size());
      if (cv_result != CV_OK) {
         fprintf(stderr, "cv_verify_build_db failed, error code %d\n", cv_result);
         bresult = false;
      }
      for (int i = 0; i < list_feature.size(); i++) {
         cv_verify_release_feature(list_feature[i]);
      }
   }
   cv_verify_save_db(handle_db, db_path);
   return bresult;
}
int main(int argc, char *argv[]) {
   //文件路径
   char *db_path = "./out1.db";
   char *image_path = "../../test_image/face_08.jpg";
   char *image_list = "../../test_image/imglist";
   //创建静态人脸识别句柄,同时创建状态标量
   cv_result_t cv_result = cv_face_create_detector(&handle_detect, NULL, CV_DETECT_ENABLE_ALIGN_21);
   if (cv_result != CV_OK){
      fprintf(stderr, "create detect handle failed, error code %d\n", cv_result);
   }
   //创建人脸验证句柄并初始化
   cv_result = cv_verify_create_handle(&handle_verify, "../../../models/verify.model");
   if (cv_result != CV_OK)
   {
      fprintf(stderr, "fail to init verify handle, error code %d\n", cv_result);
   if (cv_result != CV_OK){
      fprintf(stderr, "create verify handle failed, error code %d\n", cv_result);
   }
   // 创建人脸数据库句柄
   cv_result = cv_verify_create_db(&handle_db);
   if (cv_result != CV_OK){
      fprintf(stderr, "create db handle failed, error code %d\n", cv_result);
   }
   //批量插入数据库
   db_gen(image_list,db_path);
   
   //-------测试人脸 识别位置 start-------
   Mat bgr_image_1 = imread(input_image_path);
   if (!bgr_image_1.data) {
   fprintf(stderr, "fail to read %s\n", input_image_path);
   return -1;
   }else
   {
   testface_detect(bgr_image_1,output_image_path);
   //待搜索的图像
   Mat image_color = imread(image_path);
   if (!image_color.data) {
      return NULL;
   }
   //-------测试人脸 识别位置 end-------
/*
   //-------测试人脸 验证 start-------
   output_image_path = "../../test_image/face_04.jpg";
   Mat bgr_image_2 = imread(output_image_path);
   if (!bgr_image_2.data) {
   fprintf(stderr, "fail to read %s\n", output_image_path);
   return -1;
   }else
   {
   testface_verify(bgr_image_color,bgr_image_2);
   //搜索数据库
   if(search_db(image_color,db_path)){
      cout<<"search db"<<endl;
   }
   //-------测试人脸 验证 end-------
   
   //-------测试提取人脸特征值 start-------
   Mat bgr_image_1 = imread(input_image_path);
   char *string_feature;
   if (!bgr_image_1.data) {
      fprintf(stderr, "fail to read %s\n", input_image_path);
      return -1;
   }else
   {
      string_feature=getFeature(bgr_image_1,handle_verify);
   }
   cout<<string_feature<<endl;
   //-------测试提取人脸特征值 end-------
*/
   //
   cin>>cv_result;
   Sleep(100);
   //回收内存
   cv_face_destroy_detector(handle_detect);
   cv_verify_destroy_db(handle_db);
   cv_verify_destroy_handle(handle_verify);
   return 0;
}