冒用公司名做网站,做网站需要找什么客户,wordpress 文章 模板,九州建网站一、基础入门介绍这里为了能让大家对人脸识别SDK结合数据库有个初步了解#xff0c;我们先利用 ArcSoftFaceDemo #xff0c;讲解下此Demo是如何对人脸数据库进行管理的#xff0c;以及如何正确地注册到 ArcFace SDK 的引擎中#xff0c;以支持后续的人脸检测和识别功能。下…一、基础入门介绍这里为了能让大家对人脸识别SDK结合数据库有个初步了解我们先利用 ArcSoftFaceDemo 讲解下此Demo是如何对人脸数据库进行管理的以及如何正确地注册到 ArcFace SDK 的引擎中以支持后续的人脸检测和识别功能。下面结合代码分析整个管理流程。1、数据库环境准备在开始使用 ArcsoftFaceDemo 前需要先准备好 MySQL 数据库环境。为了快速搭建可以直接使用 Docker 启动一个数据库实例。使用 Docker 启动 MySQL 8.0执行以下命令启动 MySQL 容器docker run -d \--name arcsoft_mysql \-e MYSQL_ROOT_PASSWORDRoot123 \-e MYSQL_DATABASEarcsoft_face \-p 3306:3306 \registry.cn-hangzhou.aliyuncs.com/china-images/mysql:8.0说明--name arcsoft_mysql容器名称方便管理。MYSQL_ROOT_PASSWORDRoot123root 用户密码。MYSQL_DATABASEarcsoft_face初始化创建数据库 arcsoft_face。-p 3306:3306将容器端口映射到宿主机方便程序连接。registry.cn-hangzhou.aliyuncs.com/china-images/mysql:8.0指定使用 MySQL 8.0 阿里云镜像如果有外网环境可直接使用mysql:8.0代替。如果你想了解更多 Docker 使用方式可以参考其他 Docker 入门文档或教程。也可直接在物理操作系统上安装MySQL数据库连接信息启动完成后你就可以通过以下信息连接数据库URL物理机IP:3306用户名root密码Root123数据库arcsoft_face这样就完成了数据库环境的搭建为 ArcsoftFaceDemo 的人脸库管理做好了基础准备。2、工程导入与数据库配置在完成数据库环境准备后下一步是导入 ArcSoftFaceDemo 工程并将默认数据库配置改为 MySQL。导入工程从 ArcSoft 官网下载 ArcSoftFaceDemo 工程压缩包。解压后用 IntelliJ IDEA 打开工程目录。修改数据库配置工程默认使用的是 H2 内存数据库适合快速演示和测试。但在正式环境中建议切换到 MySQL 或其他持久化数据库。打开 application.properties 文件找到默认配置spring.datasource.urljdbc:h2:file:./data/arcdbspring.datasource.driver-class-nameorg.h2.Driverspring.datasource.usernamesaspring.datasource.passwordpasswordspring.h2.console.enabledtruespring.h2.console.path/h2-consolespring.sql.init.modealwaysspring.sql.init.schema-locationsclasspath:db/schema-h2.sql说明spring.datasource.urlH2 数据库文件路径。spring.datasource.driver-class-nameH2 数据库驱动。spring.datasource.username / spring.datasource.password数据库账号密码。spring.h2.console.*H2 Web 控制台相关配置方便调试。spring.sql.init.*初始化 SQL 文件路径用于创建示例表结构。H2切换为MySQL在正式环境中我们需要将默认 H2 配置改为 MySQL。打开 application.properties将数据库相关配置修改为 MySQL 连接信息spring.datasource.urljdbc:mysql://localhost:3306/arcsoft_face?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghaispring.datasource.driver-class-namecom.mysql.cj.jdbc.Driverspring.datasource.usernamerootspring.datasource.passwordRoot123spring.sql.init.modealwaysspring.sql.init.schema-locationsclasspath:db/schema-mysql.sql说明spring.datasource.urlMySQL 连接 URL包含数据库名 arcsoft_face字符集与时区设置。localhost地址根据实际数据库IP地址设置spring.datasource.driver-class-nameMySQL 驱动类。spring.datasource.username / spring.datasource.passwordMySQL 账号密码对应 Docker 启动 MySQL 时设置的用户名和密码。spring.sql.init.*初始化 SQL 文件路径用于创建用户表结构与 H2 不同需要使用 MySQL 版本 SQL。验证数据库连接启动 ArcSoftFaceDemo 工程。检查启动日志确认数据库连接成功HikariPool-1 - Starting...HikariPool-1 - Start completed.注意使用 MySQL 客户端如 mysql 命令行或 Navicat等连接数据库确认 arcsoft_face 数据库已创建成功。创建用户表如果 MySQL 数据库中没有表需要执行初始化 SQL 创建 user_info 表CREATE TABLE IF NOT EXISTS user_info (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(60) NOT NULL,extra_info VARCHAR(500),face_feature BLOB,image_url VARCHAR(120),create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,UNIQUE KEY user_info_name_uindex (name)) ENGINEInnoDB DEFAULT CHARSETutf8mb4;关键字段说明id用户唯一标识。name用户名。face_featureArcSoft SDK 提取的人脸特征二进制数据。这里也可以根据业务来使用text类型存储base64编码后的字符串数据image_url注册证存储地址。这样就完成了 MySQL 数据库接入 ArcSoftFaceDemo 的准备工作。3、人脸注册过程说明FaceService.javaFaceService 是整个系统的人脸注册与管理核心逻辑负责从数据库读取用户人脸信息注册/更新人脸到 ArcFace SDK 内存引擎删除人脸系统启动时批量加载人脸支持从数据库、本地图片、classpath 目录三种来源初始化下面详细说明各功能模块的逻辑。人脸注册核心方法addUserpublic void addUser(String name, byte[] faceFeature) {UserInfo userInfo userInfoMapper.selectOne(Wrappers.UserInfolambdaQuery().eq(UserInfo::getName, name));if (userInfo null) {UserInfo userInfoInsert new UserInfo();userInfoInsert.setId((int) (System.currentTimeMillis() % 1_000_000_000)); //如果是MySQL数据库可去掉这个利用数据库自增长id来生成userInfoInsert.setName(name);userInfoInsert.setFaceFeature(faceFeature);userInfoMapper.insert(userInfoInsert);faceEngineService.registerFaceFeature2Engine(userInfoInsert.getId(), name, faceFeature);} else {UserInfo userInfoUpdate new UserInfo();userInfoUpdate.setId(userInfo.getId());userInfoUpdate.setName(name);userInfoUpdate.setFaceFeature(faceFeature);userInfoMapper.updateById(userInfoUpdate);faceEngineService.removeFaceFeature2Engine(userInfo.getId());faceEngineService.registerFaceFeature2Engine(userInfo.getId(), name, faceFeature);}}功能说明addUser 是 ArcSoftFaceDemo 项目中最核心的人脸注册方法主要功能是将输入的人脸特征byte[]写入数据库将人脸特征注册到 ArcFace 引擎的内存特征库内存中的索引结构同步维护两端的数据一致性数据库 ↔ 识别引擎ArcFace SDK 的识别能力依赖于内存中的特征库因此每次注册、更新、删除都必须保持数据库与 SDK 内存库一致。在做新增的时候同步两边需同时新增保证数据一致性。这里注册存储的时候也可以同时带一些业务上的信息如人员id人员姓名人员注册照存放地址等。这些信息在数据库中可以以字段的形式进行存储归档可参考上面user_info表进行字段扩展优化。如果想通过SDK的searchFaceFeature接口获取到这些额外信息在registerFaceFeature接口中提供了faceTag的一个字符串类型用于存放业务数据可以把这些信息以JSON字符串形式存放到faceTag中去当然也可通过searchId再查询数据库的方式把对应的人员信息查询出来ArcFace SDK 提取的人脸特征是一个 byte[] 数组。5.0 的中模型特征长度在 2056字节大模型特征特征长度3080字节这里在做数据库字段大小的时候需要关注下两种存储方式SDK的特征类型是byte[]数组类型存储到数据库方式1、可以直接使用BLOB类型一般推荐用BLOB类型存储可以减少编解码带来的性能损失2、byte[]数组转成base64字符串数据库用TEXT类型进行存储如果涉及到网络传输可使用Base64字符串删除用户 removeUserpublic void removeUser(String name) {UserInfo userInfo userInfoMapper.selectOne(Wrappers.UserInfolambdaQuery().eq(UserInfo::getName, name));if (userInfo ! null) {faceEngineService.removeFaceFeature2Engine(userInfo.getId());userInfoMapper.deleteById(userInfo.getId());}}根据用户名查询用户从 SDK 内存引擎移除人脸从数据库删除记录系统启动时自动加载人脸PostConstructpublic void loadImage2Engine() {if (true.equals(faceImageClear)) {removeAllUser();initSystemFace();File file new File(testImagePath);if (file.isDirectory()) {File[] files file.listFiles();log.info(开始加载本地人脸图片到引擎中);for (File imageFile : files) {String name imageFile.getName();if (name.endsWith(.jpg) || name.endsWith(.png)) {String userName name.substring(0, name.lastIndexOf(.));register(userName, imageFile, null);}}log.info(加载本地人脸图片到引擎中完成);}}else {initDatabaseFace2Engine();}}系统启动后执行用于初始化内存人脸库为了加快识别速度建议每次启动服务后就直接把数据库里的人脸注册信息放到SDK引擎里减少下次识别读取数据库带来的耗时增加。Demo中提供了有两种模式根据配置文件的register.faceimage.clean进行切换register.faceimage.cleantrue每次启动会清空数据库重新加载本地图片进行注册同时存储到数据库和SDKregister.faceimage.cleanfalse每次启动从数据库读取特征加载到SDK。Demo为了测试会同时把本地本次未注册的图片进行存储和注册生产环境可只保留从数据库读取加载4、人脸识别方式这里再另外提一下SDK人脸识别主要有以下两种方案Demo采用的是第2种方案也可根据实际业务使用第1种方案①、使用 Map 列表 compareFaceFeature 接口原理将注册的人脸特征存放在 Map 或列表中通过 SDK 的 compareFaceFeature 接口进行循环比对。优点可灵活分组管理人脸库支持多线程并发比对。缺点当人脸库量大时频繁调用比对接口会增加性能损耗。②、使用 SDK 提供的原生接口注册原理利用registerFaceFeature、removeFaceFeature、updateFaceFeature、searchFaceFeature 组合接口实现对人脸的增删改查优点SDK 原生实现比对性能快资源消耗少。缺点不支持分组比对系统重启后需重新注册特征多引擎并发时每个引擎的人脸库需单独管理维护复杂。 为了实现长久保存和分布式共享人脸特征需进行合理存储5、人脸引擎说明FaceEngineService.javaFaceEngineService 是人脸SDK 的核心部分负责人脸检测、特征提取、活体检测、属性检测等人员信息的新增、删除、修改、人脸搜索下面详细说明各功能模块的逻辑。人员新增registerFaceFeature2Enginepublic void registerFaceFeature2Engine(int searchId, String faceTag, byte[] faceFeature) {FaceEngineFactory factory (FaceEngineFactory) faceEngineComparePool.getFactory();ListFaceEngine allObjects factory.getAllObjects();FaceFeatureInfo faceFeatureInfo new FaceFeatureInfo();faceFeatureInfo.setSearchId(searchId);faceFeatureInfo.setFaceTag(faceTag);faceFeatureInfo.setFeatureData(faceFeature);// log.info(Register: JSON.toJSONString(faceFeatureInfo));for (FaceEngine allObject : allObjects) {int res allObject.registerFaceFeature(faceFeatureInfo);}、、}这里重点说明下因为我们的FaceEngine用了线程池同时初始化了多个引擎所以我们在向SDK注册人员信息的时候需要给每个引擎进行注册删除同理。人员新增removeFaceFeature2Enginepublic void removeFaceFeature2Engine(int searchId) {FaceEngineFactory factory (FaceEngineFactory) faceEngineComparePool.getFactory();ListFaceEngine allObjects factory.getAllObjects();for (FaceEngine allObject : allObjects) {allObject.removeFaceFeature(searchId);}}删除同注册接口需要同步向所有FaceEngine库进行移除操作二、人脸特征三层存储与分布式管理上面已经介绍了基本的数据库接入和使用那么在实际人脸识别场景下系统的数据存储与识别通常采用三层设计MySQL负责持久化存储人脸特征信息实现可靠的长期保存。Redis用于异步更新与分布式缓存实现多机器环境下的人脸特征共享。内存ConcurrentHashMap / 特征池存储当前在线的活跃人脸特征实现毫秒级识别。这种设计保证了系统既能持久化存储又能在识别时获得最佳性能。在 Spring Boot 项目中实现人脸特征的管理可以从数据库建表、服务层加载、Redis缓存、特征注册与比对几个方面进行详细设计。在多台识别服务器部署的分布式环境中人脸特征需要在各节点之间保持一致性、高可用和高性能。结合内存、Redis 和数据库三层存储设计参考方案1、 启动加载策略流程每台识别服务器启动时先从 Redis 拉取最新的人脸特征到本地内存缓存。如果 Redis 中没有特征数据如初次部署则从 MySQL 数据库加载。Redis 可作为 内存缓存 异步更新机制保证各节点识别数据一致性加载后内存缓存即可支持毫秒级人脸识别。实现示例PostConstructpublic void loadFeaturesOnStartup() {SetString keys redisTemplate.keys(face:*);if (keys ! null !keys.isEmpty()) {for (String key : keys) {byte[] featureData (byte[]) redisTemplate.opsForValue().get(key);if (featureData ! null) {featureMap.put(key.replace(face:, ), featureData);}}} else {// Redis为空从数据库加载ListFaceFeature features repository.findAll();for (FaceFeature f : features) {featureMap.put(f.getUserId(), f.getFeature());redisTemplate.opsForValue().set(face: f.getUserId(), f.getFeature());}}}优势避免每次识别都访问数据库提高性能。启动即加载最新特征保证识别数据实时性。2、 特征更新与同步策略在分布式场景下用户新增、删除或更新人脸特征时需要保证所有节点内存保持一致更新顺序写内存立即更新本地内存缓存保证识别服务实时可用。写 Redis同步到 Redis作为分布式共享层。写数据库异步持久化到 MySQL保证长期数据安全。同步机制利用 Redis Pub/Sub 或消息队列Kafka、RabbitMQ广播更新事件。其他节点接收到更新事件后刷新本地内存特征缓存。示例逻辑public void updateFeature(String userId, byte[] feature) {// 更新本地内存featureMap.put(userId, feature);// 更新 RedisredisTemplate.opsForValue().set(face: userId, feature);// 发布更新事件通知其他节点redisTemplate.convertAndSend(face:update, userId);// 异步更新数据库asyncUpdateDatabase(userId, feature);}// 订阅事件刷新内存EventListenerpublic void handleRedisUpdateEvent(Message message) {String userId (String) message.getBody();String feature redisTemplate.opsForValue().get(face: userId);if (feature ! null) {featureMap.put(userId, feature);}}