在智慧社区建设中,人脸识别技术的应用极大提升了小区管理效率和安全性。本文将介绍如何使用 spring boot 框架结合百度 ai 人脸识别 api,实现小区人员出入自动识别与记录管理功能。
系统功能概述
本系统主要包含两大核心功能:
- 人脸识别出入管理:通过摄像头采集人脸图像,自动识别人员身份并记录出入时间
- 出入记录查询:支持按时间范围、人员姓名等条件查询出入记录,方便管理人员统计分析
技术栈选择
- 后端框架:spring boot 2.7.4
- 持久层框架:mybatis-plus 3.5.1
- 数据库:mysql
- 人脸识别:百度 ai 开放平台
- 工具类:hutool、lombok
- 前端交互:restful api
核心依赖配置
首先在pom.xml中添加核心依赖:
<!-- 百度ai sdk -->
<dependency>
<groupid>com.baidu.aip</groupid>
<artifactid>java-sdk</artifactid>
<version>4.16.19</version>
<exclusions>
<exclusion>
<groupid>org.slf4j</groupid>
<artifactid>slf4j-simple</artifactid>
</exclusion>
</exclusions>
</dependency>
<!-- spring boot核心依赖 -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-redis</artifactid>
</dependency>
<!-- 数据访问 -->
<dependency>
<groupid>com.baomidou</groupid>
<artifactid>mybatis-plus-boot-starter</artifactid>
<version>3.5.1</version>
</dependency>
<dependency>
<groupid>mysql</groupid>
<artifactid>mysql-connector-java</artifactid>
<scope>runtime</scope>
</dependency>
<!-- 工具类 -->
<dependency>
<groupid>org.projectlombok</groupid>
<artifactid>lombok</artifactid>
<optional>true</optional>
</dependency>
<dependency>
<groupid>cn.hutool</groupid>
<artifactid>hutool-all</artifactid>
<version>5.2.4</version>
</dependency>
<!-- 文件处理 -->
<dependency>
<groupid>commons-fileupload</groupid>
<artifactid>commons-fileupload</artifactid>
<version>1.3.1</version>
</dependency>数据模型设计
出入记录实体类
@data
@tablename("in_out_record")
public class inoutrecordentity implements serializable {
private static final long serialversionuid = 1l;
@tableid(value = "in_out_record_id", type = idtype.auto)
private integer inoutrecordid;
@tablefield("person_id")
private integer personid;
@tablefield("community_id")
private integer communityid;
@tablefield("in_time")
private localdatetime intime;
@tablefield("out_time")
private localdatetime outtime;
@tablefield("in_pic")
private string inpic;
@tablefield("out_pic")
private string outpic;
}出入记录查询表单
@data
public class inoutform {
private long page;
private long limit;
private string username;
@jsonformat(pattern = "yyyy-mm-dd hh:mm:ss")
private localdatetime startdate;
@jsonformat(pattern = "yyyy-mm-dd hh:mm:ss")
private localdatetime enddate;
}出入记录 vo 类(用于前端展示)
@data
public class inoutrecordvo {
@tableid(value = "in_out_record_id", type = idtype.auto)
private integer inoutrecordid;
private integer personid;
private integer communityid;
private localdatetime intime;
private localdatetime outtime;
private string inpic;
private string outpic;
// 扩展字段,用于展示
private string username;
private string communityname;
private string termname;
private string houseno;
}百度 ai 工具类实现
封装百度 ai 人脸识别相关操作:
@component
@slf4j
public class baiduaiutils {
@value("${baidu.face.appid}")
private string app_id;
@value("${baidu.face.apikey}")
private string api_key;
@value("${baidu.face.secretkey}")
private string secret_key;
@value("${baidu.face.imagetype}")
private string image_type;
@value("${baidu.face.groupid}")
private string groupid;
private aipface client;
private hashmap<string, object> options = new hashmap<>();
public baiduaiutils() {
// 设置图像质量控制
options.put("quality_control", "normal");
// 设置活体检测控制级别
options.put("liveness_control", "low");
}
@postconstruct
public void init() {
// 初始化百度ai客户端
client = new aipface(app_id, api_key, secret_key);
}
/**
* 人脸检测(检查是否有且仅有一张人脸)
*/
public boolean facecheck(string image) {
jsonobject res = client.detect(image, image_type, options);
log.info("detect result :{}", res);
if (res.has("error_code") && res.getint("error_code") == 0) {
jsonobject resultobject = res.getjsonobject("result");
integer facenum = resultobject.getint("face_num");
return facenum == 1;
}
return false;
}
/**
* 人脸搜索(匹配用户)
*/
public string facesearch(string image) {
jsonobject res = client.search(image, image_type, groupid, options);
log.info("search result :{}", res);
if (res.has("error_code") && res.getint("error_code") == 0) {
jsonobject result = res.getjsonobject("result");
jsonarray userlist = result.getjsonarray("user_list");
if (userlist.length() > 0) {
jsonobject user = userlist.getjsonobject(0);
double score = user.getdouble("score");
// 置信度大于80分认为匹配成功
if (score > 80) {
return user.getstring("user_id");
}
}
}
return null;
}
}业务逻辑实现
出入记录服务实现类
@service
public class inoutrecordserviceimpl extends serviceimpl<inoutrecordmapper, inoutrecordentity> implements inoutrecordservice {
@autowired
private inoutrecordmapper inoutrecordmapper;
@autowired
private personmapper personmapper;
@override
public inoutpagelistvo getinoutlist(inoutform form) {
page<inoutrecordentity> page = new page<>(form.getpage(), form.getlimit());
querywrapper<inoutrecordentity> querywrapper = new querywrapper<>();
// 时间范围查询
if (form.getstartdate() != null && form.getenddate() != null) {
querywrapper.between("in_time", form.getstartdate(), form.getenddate());
}
// 如果需要按用户名查询,可以在这里添加关联查询条件
page<inoutrecordentity> pages = inoutrecordmapper.selectpage(page, querywrapper);
list<inoutrecordvo> inoutrecordvolist = new arraylist<>();
// 转换为vo对象并补充关联信息
for(inoutrecordentity entity : pages.getrecords()){
inoutrecordvo vo = new inoutrecordvo();
beanutils.copyproperties(entity, vo);
personentity person = personmapper.selectbyid(entity.getpersonid());
if (person != null) {
vo.setusername(person.getusername());
vo.sethouseno(person.gethouseno());
}
// 获取小区名称
vo.setcommunityname(personmapper.selectcommunitynamebyid(entity.getcommunityid()));
inoutrecordvolist.add(vo);
}
// 封装分页结果
inoutpagelistvo result = new inoutpagelistvo();
result.setrecords(inoutrecordvolist);
result.settotalcount(pages.gettotal());
result.setpagesize(pages.getsize());
result.settotalpage(pages.getpages());
result.setcurrpage(pages.getcurrent());
return result;
}
@override
public inoutrecordentity findlatestrecord(integer personid) {
querywrapper<inoutrecordentity> querywrapper = new querywrapper<>();
querywrapper.eq("person_id", personid)
.orderbydesc("in_time")
.last("limit 1");
return this.getone(querywrapper);
}
}控制器实现
人脸识别与出入记录控制器
@restcontroller
@requestmapping("/sys/inout")
public class inoutrecordcontroller {
@autowired
private baiduaiutils baiduaiutils;
@autowired
private personservice personservice;
@autowired
private inoutrecordservice recordservice;
@value("${file.upload-dir}")
private string uploaddir;
/**
* 人脸识别接口
*/
@postmapping("/add")
public result add(@requestbody faceform faceform) {
// 提取base64图像数据
string filebase64 = faceform.getfilebase64();
if (filebase64.contains(",")) {
filebase64 = filebase64.split(",")[1];
}
// 1. 检测人脸
boolean hasvalidface = baiduaiutils.facecheck(filebase64);
if (!hasvalidface) {
return result.error("人脸检测失败");
}
// 2. 人脸搜索匹配用户
string userid = baiduaiutils.facesearch(filebase64);
if (userid == null) {
return result.ok().put("data", "人员信息不存在").put("status", "fail");
}
// 3. 查询用户信息
int personid;
try {
personid = integer.parseint(userid);
} catch (numberformatexception e) {
return result.error("用户id格式错误");
}
personentity person = personservice.getbyid(personid);
if (person == null) {
return result.ok().put("data", "人员信息不存在").put("status", "fail");
}
try {
// 4. 保存图片到本地
string filename = system.currenttimemillis() + ".png";
string filepath = paths.get(uploaddir, filename).tostring();
// 确保目录存在
file dir = new file(uploaddir);
if (!dir.exists()) {
dir.mkdirs();
}
// 解码并保存图片
byte[] imagebytes = base64.getdecoder().decode(filebase64);
files.write(paths.get(filepath), imagebytes);
// 构建图片url
string fullurl = "http://localhost:8080/photos/" + filename;
// 5. 查找最近记录判断是入场还是出场
inoutrecordentity latestrecord = recordservice.findlatestrecord(personid);
if (latestrecord == null || latestrecord.getouttime() != null) {
// 入场记录
inoutrecordentity newrecord = new inoutrecordentity();
newrecord.setcommunityid(faceform.getcommunityid());
newrecord.setpersonid(personid);
newrecord.setintime(localdatetime.now());
newrecord.setinpic(fullurl);
recordservice.save(newrecord);
return result.ok().put("data", person.getusername() + "进入小区").put("status", "success");
} else {
// 出场记录
latestrecord.setouttime(localdatetime.now());
latestrecord.setoutpic(fullurl);
recordservice.updatebyid(latestrecord);
return result.ok().put("data", person.getusername() + "离开小区").put("status", "success");
}
} catch (exception e) {
e.printstacktrace();
return result.error("操作失败: " + e.getmessage());
}
}
/**
* 出入记录查询接口
*/
@getmapping("/list")
public result list(inoutform form) {
// 获取分页数据
inoutpagelistvo pagelistvo = inoutrecordservice.getinoutlist(form);
// 构建返回结构
map<string, object> pagelistmap = new hashmap<>();
pagelistmap.put("totalcount", pagelistvo.gettotalcount());
pagelistmap.put("pagesize", pagelistvo.getpagesize());
pagelistmap.put("totalpage", pagelistvo.gettotalpage());
pagelistmap.put("currpage", pagelistvo.getcurrpage());
pagelistmap.put("list", pagelistvo.getrecords());
map<string, object> datamap = new hashmap<>();
datamap.put("pagelist", pagelistmap);
return result.ok().put("data", datamap);
}
}接口使用说明
人脸识别接口
请求地址:post /sys/inout/add
请求参数:
{
"communityid": 2,
"extname": "png",
"filebase64": "ivborw0kggoaaaansuheugaaaoaaaahgcayaaaa10dzkaaaaaxnsr0iars4c6qaaiabjrefuef7sxe2ohblu3bljtx1lqugyxevv9hmq5yizq239/8b8gtdpbgl/6caaaaasuvork5cyii="
}成功响应(人员进入):
{
"msg": "操作成功",
"code": 200,
"data": "张三进入小区",
"status": "success"
}失败响应(人员不存在):
{
"msg": "操作成功",
"code": 200,
"data": "人员信息不存在",
"status": "fail"
}出入记录查询接口
请求地址:get /sys/inout/list
请求参数:
{
"page": 1,
"limit": 10,
"username": "张三",
"startdate": "2023-07-20 12:59:54",
"enddate": "2023-07-20 23:00:00"
}响应结果:
{
"msg": "操作成功",
"code": 200,
"data": {
"pagelist": {
"totalcount": 1,
"pagesize": 10,
"totalpage": 1,
"currpage": 1,
"list": [
{
"inoutrecordid": 44,
"intime": "2023-07-19 16:51:55",
"outtime": "2023-07-19 16:52:07",
"inpic": "http://localhost:8181/villegepic/face/47b49187-a5e9-486a-b8ac-4409710b3323.png",
"outpic": "http://localhost:8181/villegepic/face/4cbfb2b9-a691-4d0a-a4d4-4bf602cb33ac.png",
"communityname": "栖海澐颂",
"termname": "8栋",
"houseno": "802",
"username": "丽丽"
}
]
}
}
}系统优化建议
- 性能优化:
- 对人脸图片进行压缩处理,减少传输和存储开销
- 对查询接口添加缓存,提高高频查询效率
- 安全性增强:
- 提高活体检测级别,防止照片、视频等欺骗手段
- 对敏感接口添加权限控制
- 对 base64 图片传输进行加密
- 功能扩展:
- 添加异常出入提醒功能
- 实现批量导出记录报表功能
- 增加访客临时授权功能
通过以上实现,我们构建了一个完整的小区人脸识别出入管理系统,该系统能够自动识别人员身份并记录出入信息,同时提供灵活的查询功能,为小区管理提供了便捷高效的解决方案。
到此这篇关于基于 spring boot 的小区人脸识别与出入记录管理系统功能的文章就介绍到这了,更多相关spring boot 人脸识别内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论