RV1126 NO.58:ROCKX+RV1126人脸识别推流项目之读取人脸数据库并保存到map

一.本章节介绍

本章节将介绍如何通过查询人脸数据库表格,将数据存储到map容器中。map容器基于内存操作,能够实现高效快速的数据查询。在本项目中,map主要发挥快速查询功能:其中key存储人脸结构体(People),value则存储具体的人脸数据(rockx_face_feature_t)。

二.读取数据库保存到map流程框图

该流程图展示了从数据库读取数据并加载到Map容器的完整流程,包含三个关键步骤:

  1. 建立连接:初始化并连接SQLite3数据库
  2. 执行查询:通过SELECT语句获取人脸表格数据
  3. 数据映射:将查询结果循环存入Map容器

三.读取数据库保存到map的代码截图

cpp 复制代码
void init_face_data()
{
    /*刚开始交叉编译sqlite3_operation_test.cpp文件到板子中运行,把人脸信息及特征值保存到sqlite数据库中,再调用QueryPeopleData()
    函数从中一一取出人脸信息(比如姓名,图片信息以及大小),最后返回组装好的容器*/
    Connection_sqlite3DataBase();
    int task_id = generate_unique_task_id();
    S_THREAD_MAP thread_map;
    //map<string, rockx_face_feature_t> maps = QueryFaceFeature();
    map<People, rockx_face_feature_t> maps = QueryPeopleData();
    //thread_map.thread_map = maps;
    thread_map.thread_people_map = maps;
    set_thread_map(task_id, &thread_map);
    printf("本次人脸数据绑定的 task_id:%d\n", task_id);
}

init_face_data 是一个用于读取数据库数据并存入 map 容器的自定义函数,主要包含三个关键步骤:首先通过 Connection_sqlite3DataBase 加载数据库,接着使用 QueryPeopleData 查询数据库信息并存入 Map 容器,最后通过 set_thread_map 将 Map 数据存储到全局变量中。

3.1. 加载并连接sqlite3数据库

cpp 复制代码
int Connection_sqlite3DataBase()
{
  rc = sqlite3_open("/userdata/face.db", &db);
  if (rc != SQLITE_OK)
  {
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
  }
  else
  {
    printf("You have opened a sqlite3 database named bind.db successfully!\nCongratulation! Have fun!\n");
  }
  return 0;
}

这个函数直接调用了sqlite3的api sqlite3_open来初始化人脸数据库,若返回值不等于SQLITE_OK则初始化数据库失败,否则就初始化成功。

3.2. 通过select查询人脸表格的数据

cpp 复制代码
rockx_face_feature_t rockx_face_feature = {0, 0};
  // 定义返回值:map容器,键=People(人名+图片),值=人脸特征
  map<People, rockx_face_feature_t> people_map;
  sqlite3_stmt *stmt = nullptr;
  static int i=0;
  char buf_sql[256];
  //char *sql = "select name, feature_size, face_feature, image_size, image_data from face_data_table";
  sprintf(buf_sql,"select name, feature_size, face_feature, image_size, image_data from face_data_table_%d",i++);


  int id = 0, len = 0;
  char *name;
  int feature_size;
  int feature_bytes;
  int image_size;
  vector<char> images;
  People first_people;

该SQL查询语句用于从人脸数据表face_data_table中检索数据,查询字段包括:

  • name(姓名)
  • feature_size(特征值长度)
  • face_feature(人脸特征数据)
  • image_size(图片尺寸)
  • image_data(图片数据)

查询执行时使用了sqlite3_prepare方法进行SQL语句预处理。

3.3. 读取查询的结果并循环插入map容器

cpp 复制代码
int ret = sqlite3_prepare(db, buf_sql, strlen(sql), &stmt, 0);
  if (ret == SQLITE_OK)
  {
    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
      name = (char *)sqlite3_column_text(stmt, 0);
      printf("name = %s\n", name);
      feature_size = sqlite3_column_int(stmt, 1);
      printf("feature_size = %d\n", feature_size);

      feature_bytes = feature * sizeof(float);
      const void *feature = sqlite3_column_blob(stmt, 2);
      memset(rockx_face_feature.feature, 0, feature_bytes);
      memcpy(rockx_face_feature.feature, feature, feature_bytes);
      rockx_face_feature.len = feature_bytes;

      image_size = sqlite3_column_int(stmt, 3);
      printf("image_size = %d\n", image_size);

      const char * image_data = (const char *)sqlite3_column_blob(stmt, 4);
      for (int i = 0; i < image_size; i++)
      {
         images.push_back(image_data[i]);
         images.clear(); // 新增:清空上一行的图片数据
      }

      first_people.people_name = string(name);
      first_people.images = images;

      string str(name);
      //people_map.insert(pair<const People, rockx_face_feature_t>(first_people, rockx_face_feature));
      people_map.insert(make_pair(first_people, rockx_face_feature));
      //people_map.insert(first_people, rockx_face_feature);
    }
  }
  //返回组装好的map容器
  return people_map;

这段代码实现了从SQLite3数据库读取数据并循环插入到map容器的功能。核心是通过sqlite3_step函数获取SELECT查询结果:当返回值为SQLITE_ROW时,表示当前行包含有效数据。

各列数据的读取方式如下:

  • sqlite3_column_text(stmt, 0):获取SELECT语句第一个字段(索引0),对应name字段(字符串类型)
  • sqlite3_column_int(stmt, 1):获取第二个字段(索引1),对应feature_size字段(整型)
  • sqlite3_column_blob(stmt, 2):获取第三个字段(索引2),对应face_feature字段(二进制类型)
  • sqlite3_column_int(stmt, 3):获取第四个字段(索引3),对应image_size字段(整型)
  • sqlite3_column_blob(stmt, 4):获取第五个字段(索引4),对应image_data字段(二进制类型)

完成数据读取后,将获取的所有字段值插入到map容器中。

四.完整代码

cpp 复制代码
map<People, rockx_face_feature_t> QueryPeopleData()
{
  rockx_face_feature_t rockx_face_feature = {0, 0};
  // 定义返回值:map容器,键=People(人名+图片),值=人脸特征
  map<People, rockx_face_feature_t> people_map;
  sqlite3_stmt *stmt = nullptr;
  static int i=0;
  char buf_sql[256];
  //char *sql = "select name, feature_size, face_feature, image_size, image_data from face_data_table";
  sprintf(buf_sql,"select name, feature_size, face_feature, image_size, image_data from face_data_table_%d",i++);


  int id = 0, len = 0;
  char *name;
  int feature_size;
  int feature_bytes;
  int image_size;
  vector<char> images;
  People first_people;

  int ret = sqlite3_prepare(db, buf_sql, strlen(sql), &stmt, 0);
  if (ret == SQLITE_OK)
  {
    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
      name = (char *)sqlite3_column_text(stmt, 0);
      printf("name = %s\n", name);
      feature_size = sqlite3_column_int(stmt, 1);
      printf("feature_size = %d\n", feature_size);

      feature_bytes = feature * sizeof(float);
      const void *feature = sqlite3_column_blob(stmt, 2);
      memset(rockx_face_feature.feature, 0, feature_bytes);
      memcpy(rockx_face_feature.feature, feature, feature_bytes);
      rockx_face_feature.len = feature_bytes;

      image_size = sqlite3_column_int(stmt, 3);
      printf("image_size = %d\n", image_size);

      const char * image_data = (const char *)sqlite3_column_blob(stmt, 4);
      for (int i = 0; i < image_size; i++)
      {
         images.push_back(image_data[i]);
         images.clear(); // 新增:清空上一行的图片数据
      }

      first_people.people_name = string(name);
      first_people.images = images;

      string str(name);
      //people_map.insert(pair<const People, rockx_face_feature_t>(first_people, rockx_face_feature));
      people_map.insert(make_pair(first_people, rockx_face_feature));
      //people_map.insert(first_people, rockx_face_feature);
    }
  }
  //返回组装好的map容器
  return people_map;
}


int Connection_sqlite3DataBase()
{
  rc = sqlite3_open("/userdata/face.db", &db);
  if (rc != SQLITE_OK)
  {
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    exit(1);
  }
  else
  {
    printf("You have opened a sqlite3 database named bind.db successfully!\nCongratulation! Have fun!\n");
  }
  return 0;
}


int generate_unique_task_id() {
    return g_next_task_id++;  // 每次调用自增,返回唯一ID
}

void init_face_data()
{
    /*刚开始交叉编译sqlite3_operation_test.cpp文件到板子中运行,把人脸信息及特征值保存到sqlite数据库中,再调用QueryPeopleData()
    函数从中一一取出人脸信息(比如姓名,图片信息以及大小),最后返回组装好的容器*/
    Connection_sqlite3DataBase();
    int task_id = generate_unique_task_id();
    S_THREAD_MAP thread_map;
    //map<string, rockx_face_feature_t> maps = QueryFaceFeature();
    map<People, rockx_face_feature_t> maps = QueryPeopleData();
    //thread_map.thread_map = maps;
    thread_map.thread_people_map = maps;
    set_thread_map(task_id, &thread_map);
    printf("本次人脸数据绑定的 task_id:%d\n", task_id);
}
相关推荐
一 乐6 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
MM_MS7 小时前
Halcon变量控制类型、数据类型转换、字符串格式化、元组操作
开发语言·人工智能·深度学习·算法·目标检测·计算机视觉·视觉检测
C_心欲无痕7 小时前
ts - tsconfig.json配置讲解
linux·前端·ubuntu·typescript·json
冰西瓜6007 小时前
国科大2025操作系统高级教程期末回忆版
linux
1.14(java)7 小时前
SQL数据库操作:从CRUD到高级查询
数据库
旅途中的宽~8 小时前
《European Radiology》:2024血管瘤分割—基于MRI T1序列的分割算法
人工智能·计算机视觉·mri·sci一区top·血管瘤·t1
HIT_Weston8 小时前
93、【Ubuntu】【Hugo】搭建私人博客:面包屑(一)
linux·运维·ubuntu
Full Stack Developme8 小时前
数据库索引的原理及类型和应用场景
数据库
cuijiecheng20188 小时前
Linux下Beyond Compare过期
linux·运维·服务器
HIT_Weston9 小时前
92、【Ubuntu】【Hugo】搭建私人博客:侧边导航栏(六)
linux·运维·ubuntu