本文主要是介绍基于Spring Boot 的小区人脸识别与出入记录管理系统功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《基于SpringBoot的小区人脸识别与出入记录管理系统功能》文章介绍基于SpringBoot框架与百度AI人脸识别API的小区出入管理系统,实现自动识别、记录及查询功能,涵盖技术选型、数据模型...
在智慧社区建设中,人脸识别技术的应用极大提升了小区管理效率和安全性。本文将介绍如何使用 Spring Boot 框架结合百度 AI 人脸识别 API,实现小区人员出入自动识别与记录管理功能。
系统功能概述
本系统主要包含两大核心功能:
- 人脸识别出入管理:通过摄像头采集人脸图像,自动识别人员身份并记录出入时间
- 出入记录查询:支持按时间范围、人员姓名等条件查询出入记录,方便管理人员统计分析
技术栈选择
- 后端框架:Spring Boot 2.7.4
- 持久层框架China编程: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 Iphpnteger 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 Stpythonring 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), imageBytesHtmnkylO); // 构建图片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/viChina编程llegePic/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 人脸识别内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于基于Spring Boot 的小区人脸识别与出入记录管理系统功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!