seetaface6的编译安装过程
我的环境是MSVC x64,编译工具:CMake
源代码下载地址:https://github.com/SeetaFace6Open/index
编译顺序说明
OpenRoleZoo 为常用操作的集合,SeetaAuthorize 为模型解析工程,
TenniS 为前向计算框架。需要重点说明的是,
此次 TenniS 同时放出了 GPU 计算源码,可以编译出 GPU 版本进行使用。上述三个模块为基础模块,
各个 SDK 的编译均依赖上述模块,因此需要优先编译出 OpenRoleZoo, SeetaAuthorize 和 TenniS,
然后再进行其他 SDK 模块的编译。
编译OpenRoleZoo模块
使用cmake开始编译OpenRoleZoo,出现了cmake 编译版本不对的错误:
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
Compatibility with CMake < 3.5 has been removed from CMake.
Update the VERSION argument <min> value. Or, use the <min>...<max> syntax
to tell CMake that the project requires at least <min> but has been updated
to work with policies introduced by <max> or earlier.
Or, add -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to try configuring anyway.
Configuring incomplete, errors occurred!
解决方法:
直接去改cmake的编译版本依赖
cmake_minimum_required(VERSION 3.5...3.31)
记得修改安装路径,不然会出现等会install的时候,没有权限的错误:
错误 MSB3073 命令“setlocal...”
尽管如此,还是会出现错误:
找不到 std::function...
解决方法:
用任何文本编辑器打开 OpenRoleZoo/include/orz/mem/pot.h 文件,在文件开头的 #include 部分,添加一行 #include <functional>
修改后的文件开头看起来像这样:
//
// Created by Lby on 2017/8/12.
//
#ifndef ORZ_MEM_POT_H
#define ORZ_MEM_POT_H
#include <functional> // 就是添加这一行
#include <mutex>
#include <memory>
// ... 文件剩余内容保持不变
终于可以安心的生成和install了
这一步到此为止
编译SeetaAuthorize模块
出现了以下错误:
Selecting Windows SDK version 10.0.26100.0 to target Windows 10.0.26200.
Platform: x64
Configuration: Release
Build with ORZ
E:/seetaface/orc
E:/seetaface/orc/lib/x64
Configuring done (0.0s)
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
LIB_ORZ_PATH
linked by target "SeetaAuthorize" in directory E:/seetaface/index/SeetaAuthorize
Generating done (0.0s)
解决方法:
cmake设置
LIB_ORZ_PATH为你的lib路径,例如我的路径为:E:/seetaface/orc/lib/ORZ_static.lib
编译TenniS模块
CMAKE_INSTALL_PREFIX 不要设置c盘基本就可以了
编译FaceBoxes模块-用于检测人脸
配置好SeetaAuthorize、TenniS的路径即可,编译完后,可以使用以下代码测试是否能正常检测到人脸:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <seeta/FaceDetector.h>
#include <seeta/Common/Struct.h>
int main() {
try {
// 1. 设置FaceBoxes模型路径
// 请根据您的实际模型文件路径修改
seeta::ModelSetting::Device device = seeta::ModelSetting::CPU;
int id = 0;
// 模型文件路径 - 请根据实际情况修改
std::string model_path = "models/face_detector.csta";
// 2. 初始化人脸检测器
seeta::ModelSetting setting(model_path, device, id);
seeta::FaceDetector detector(setting);
// 3. 设置检测器参数(可选)
detector.set(seeta::FaceDetector::PROPERTY_MIN_FACE_SIZE, 20); // 最小人脸尺寸
detector.set(seeta::FaceDetector::PROPERTY_THRESHOLD, 0.9); // 检测阈值
detector.set(seeta::FaceDetector::PROPERTY_MAX_IMAGE_WIDTH, 2000); // 最大图像宽度
detector.set(seeta::FaceDetector::PROPERTY_MAX_IMAGE_HEIGHT, 2000); // 最大图像高度
std::cout << "人脸检测器初始化成功!" << std::endl;
// 4. 打开摄像头
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "错误:无法打开摄像头!" << std::endl;
return -1;
}
std::cout << "摄像头已打开,按 'ESC' 键退出程序" << std::endl;
std::cout << "按 's' 键保存当前帧" << std::endl;
cv::Mat frame;
int frame_count = 0;
int64_t total_time = 0;
while (true) {
cap >> frame;
if (frame.empty()) {
std::cerr << "警告:读取空帧" << std::endl;
continue;
}
// 5. 准备SeetaImage数据
cv::Mat image = frame.clone();
SeetaImageData simg;
simg.data = image.data;
simg.width = image.cols;
simg.height = image.rows;
simg.channels = image.channels();
// 6. 执行人脸检测(计时)
int64_t start_time = cv::getTickCount();
auto faces = detector.detect(simg);
int64_t end_time = cv::getTickCount();
double detect_time = (end_time - start_time) * 1000.0 / cv::getTickFrequency();
total_time += detect_time;
// 7. 绘制检测结果
for (int i = 0; i < faces.size; ++i) {
auto& face = faces.data[i];
auto& pos = face.pos;
cv::rectangle(frame, cv::Rect(pos.x, pos.y, pos.width, pos.height), CV_RGB(0, 128, 128), 3);
}
// 9. 显示画面
cv::imshow("Face Detection - SeetaFace6", frame);
// 10. 键盘控制
char key = cv::waitKey(1);
if (key == 27) { // ESC键
break;
}
else if (key == 's' || key == 'S') { // 保存图片
std::string filename = cv::format("face_detection_%d.jpg", frame_count);
cv::imwrite(filename, frame);
std::cout << "图片已保存: " << filename << std::endl;
}
}
// 11. 输出平均检测时间
std::cout << "程序运行结束" << std::endl;
std::cout << "总检测帧数: " << frame_count << std::endl;
std::cout << "平均检测时间: " << total_time / frame_count << " ms" << std::endl;
}
catch (const std::exception& e) {
std::cerr << "错误: " << e.what() << std::endl;
return -1;
}
cv::destroyAllWindows();
return 0;
}
编译landmarker模块-用于检测特征点
配置好SeetaAuthorize、TenniS的路径即可
编译FaceRecognizer6模块
注意设置SeetaAuthorize的一些配置路径(TenniS同理)
SeetaAuthorize_DIR 设置为install后的cmake路径
SeetaAuthorize_INCLUDE_DIR 设置为install后的include路径
cmake最终生成成功如下(无视Warning):

install成功如下

最终代码如下:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <seeta/FaceDetector.h>
#include <seeta/FaceRecognizer.h>
#include <seeta/FaceLandmarker.h> // 添加关键点检测器头文件
#include <seeta/Common/Struct.h>
#include <vector>
#include <string>
#include <windows.h>
struct FaceData {
std::string name;
std::vector<float> features;
};
int main() {
try {
// 1. 初始化人脸检测器
seeta::ModelSetting detector_setting("models/face_detector.csta", seeta::ModelSetting::CPU, 0);
seeta::FaceDetector detector(detector_setting);
detector.set(seeta::FaceDetector::PROPERTY_MIN_FACE_SIZE, 20);
detector.set(seeta::FaceDetector::PROPERTY_THRESHOLD, 0.9);
// 2. 初始化关键点检测器(用于提取5个关键点)
seeta::ModelSetting landmarker_setting("models/face_landmarker_pts5.csta", seeta::ModelSetting::CPU, 0);
seeta::FaceLandmarker landmarker(landmarker_setting);
// 3. 初始化人脸识别器
seeta::ModelSetting rec_setting("models/face_recognizer.csta", seeta::ModelSetting::CPU, 0);
seeta::FaceRecognizer recognizer(rec_setting);
std::cout << "初始化成功!" << std::endl;
// 4. 加载人脸库
std::vector<FaceData> face_database;
std::string face_dir = "E:/faces/*.*";
std::cout << "正在加载人脸库..." << std::endl;
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile(face_dir.c_str(), &findData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
std::string filename = findData.cFileName;
std::string ext = filename.substr(filename.find_last_of(".") + 1);
if (ext == "jpg" || ext == "png" || ext == "jpeg" || ext == "bmp") {
std::string fullpath = "E:/faces/" + filename;
std::string name = filename.substr(0, filename.find_last_of("."));
cv::Mat img = cv::imread(fullpath);
if (img.empty()) continue;
SeetaImageData simg;
simg.data = img.data;
simg.width = img.cols;
simg.height = img.rows;
simg.channels = img.channels();
auto faces = detector.detect(simg);
if (faces.size > 0) {
// 获取关键点
std::vector<SeetaPointF> points(5);
landmarker.mark(simg, faces.data[0].pos, points.data());
// 提取特征
float features[1024];
recognizer.Extract(simg, points.data(), features);
FaceData fd;
fd.name = name;
fd.features.assign(features, features + 1024);
face_database.push_back(fd);
std::cout << "已加载: " << name << std::endl;
}
}
} while (FindNextFile(hFind, &findData) != 0);
FindClose(hFind);
}
std::cout << "人脸库加载完成,共 " << face_database.size() << " 人" << std::endl;
// 5. 打开摄像头
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "无法打开摄像头!" << std::endl;
return -1;
}
std::cout << "\n摄像头已打开,开始识别..." << std::endl;
std::cout << "按 ESC 键退出" << std::endl;
cv::Mat frame;
while (true) {
cap >> frame;
if (frame.empty()) continue;
SeetaImageData simg;
simg.data = frame.data;
simg.width = frame.cols;
simg.height = frame.rows;
simg.channels = frame.channels();
auto faces = detector.detect(simg);
for (int i = 0; i < faces.size; ++i) {
auto& face = faces.data[i];
// 绘制人脸框
cv::Rect rect(face.pos.x, face.pos.y, face.pos.width, face.pos.height);
// 获取关键点
std::vector<SeetaPointF> points(5);
landmarker.mark(simg, face.pos, points.data());
// 提取特征
float features[1024];
recognizer.Extract(simg, points.data(), features);
std::vector<float> current_feat(features, features + 1024);
// 识别
std::string recognized_name = "未知";
float max_similarity = 0.0f;
for (const auto& db_face : face_database) {
float sim = recognizer.CalculateSimilarity(
db_face.features.data(), current_feat.data());
if (sim > max_similarity && sim > 0.6f) {
max_similarity = sim;
recognized_name = db_face.name;
}
}
// 绘制人脸框
cv::rectangle(frame, rect, cv::Scalar(0, 255, 0), 2);
// 显示姓名
cv::Scalar color = (recognized_name == "未知") ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0);
cv::putText(frame, recognized_name,
cv::Point(rect.x, rect.y - 10),
cv::FONT_HERSHEY_SIMPLEX, 0.8, color, 2);
// 显示相似度
if (max_similarity > 0.6f) {
char sim_text[32];
sprintf(sim_text, "%.2f", max_similarity);
cv::putText(frame, sim_text,
cv::Point(rect.x, rect.y + rect.height + 20),
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255, 255, 0), 1);
}
// 绘制关键点
for (int j = 0; j < 5; j++) {
cv::circle(frame,
cv::Point(points[j].x, points[j].y),
2, cv::Scalar(0, 0, 255), -1);
}
}
// 显示人脸数量
char face_count[64];
sprintf(face_count, "Faces: %d", faces.size);
cv::putText(frame, face_count,
cv::Point(10, 30),
cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(255, 0, 0), 2);
cv::imshow("Face Recognition", frame);
if (cv::waitKey(1) == 27) break;
}
}
catch (const std::exception& e) {
std::cerr << "错误: " << e.what() << std::endl;
return -1;
}
cv::destroyAllWindows();
return 0;
}

浙公网安备 33010602011771号