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);
}
相关推荐
卢锡荣12 分钟前
Type-c OTG数据与充电如何进行交互使用应用讲解
c语言·开发语言·计算机外设·电脑·音视频
188号安全攻城狮24 分钟前
【PWN】HappyNewYearCTF_8_ret2csu
linux·汇编·安全·网络安全·系统安全
Tansmjs41 分钟前
使用Python自动收发邮件
jvm·数据库·python
m0_5613596743 分钟前
用Python监控系统日志并发送警报
jvm·数据库·python
Dxy12393102161 小时前
MySQL INSERT ... ON DUPLICATE KEY UPDATE 与非主键唯一字段
数据库·mysql
工程师老罗1 小时前
什么是目标检测?
人工智能·目标检测·计算机视觉
zhousenshan1 小时前
springboot事务管理几种方式
数据库
Yana.nice2 小时前
openssl将证书从p7b转换为crt格式
java·linux
沃达德软件2 小时前
图像处理与复原技术
图像处理·人工智能·深度学习·神经网络·目标检测·计算机视觉·目标跟踪
布局呆星2 小时前
SQLite数据库的介绍与使用
数据库·python