一、技术栈与依赖引入
后端依赖 (pom.xml)
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>
<!-- 文件处理 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
前端依赖
无需额外依赖,利用原生 HTML5 API 和 Element UI 组件
二、配置文件设置
application.yml 配置
python
# 百度云人脸识别配置
baidu:
face:
appId: //
apiKey: //
secretKey: //
imageType: BASE64
groupId: 04 # 人脸库分组名称
# 文件路径保存
file:
upload-dir: D:/community/community-ui/src/photos(这里更改成自己的路径)
# 静态资源映射
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
资源映射配置 (WebConfig.java)
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${file.upload-dir}")
private String uploadDir;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/photos/**")
.addResourceLocations("file:" + uploadDir + "/");
}
}
三、后端核心实现
1. 百度 AI 工具类 (BaiduAiUtils.java)
java
@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() {
client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
}
// 人脸注册
public Boolean faceRegister(String userId, String image) {
HashMap<String, String> stringOptions = convertToMapString(options);
JSONObject res = client.addUser(image, IMAGE_TYPE, groupId, userId, stringOptions);
log.info("addUser result :{}", res);
return res.getInt("error_code") == 0;
}
// 人脸检测
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;
}
private HashMap<String, String> convertToMapString(HashMap<String, Object> objectMap) {
HashMap<String, String> stringMap = new HashMap<>();
for (HashMap.Entry<String, Object> entry : objectMap.entrySet()) {
stringMap.put(entry.getKey(), entry.getValue().toString());
}
return stringMap;
}
}
2. 实体类 (FaceForm.java)
java
@Data
public class FaceForm {
private Integer personId;
private String extName;
private String fileBase64;
}
3. 控制器 (PersonController.java)
java
@RestController
@RequestMapping("/sys/person")
public class PersonController {
@Autowired
private PersonService personService;
@Autowired
private BaiduAiUtils baiduAiUtils;
@Value("${file.upload-dir}")
private String uploadDir;
@RequestMapping("/addPerson")
public Result addPerson(@RequestBody FaceForm form) {
try {
Integer personId = form.getPersonId();
String fileBase64 = form.getFileBase64();
// 1.验证人员是否存在
PersonEntity person = personService.getById(personId);
if (person == null) {
return Result.error("人员不存在");
}
// 2.人脸检测
if (!baiduAiUtils.faceCheck(fileBase64)) {
return Result.error("未检测到人脸或多人脸");
}
// 3.人脸注册到百度人脸库
boolean aiResult = baiduAiUtils.faceRegister(personId.toString(), fileBase64);
if (!aiResult) {
return Result.error("人脸注册到人脸库失败");
}
// 4.保存图片到本地
String fileName = "person_"+personId+"_"+System.currentTimeMillis()+".png";
String filePath = Paths.get(uploadDir, fileName).toString();
File file = new File(uploadDir);
if (!file.exists()) {
file.mkdirs();
}
// 处理Base64数据
String base64Data = fileBase64.contains(",") ? fileBase64.split(",")[1] : fileBase64;
byte[] imageBytes = Base64.getDecoder().decode(base64Data);
Files.write(Paths.get(filePath), imageBytes);
// 5.更新人员信息
person.setFaceBase(fileBase64);
String fullUrl = "http://localhost:8080/photos/" + fileName;
person.setFaceUrl(fullUrl);
person.setState(2); // 更新为已验证状态
boolean updateResult = personService.updateById(person);
return updateResult ? Result.ok() : Result.error("人脸录入失败");
} catch (Exception e) {
e.printStackTrace();
return Result.error("系统异常:" + e.getMessage());
}
}
}
前端页面是如何展示出图片的,请参考
http://localhost:8080/photos/xxx.png的本地图片访问方案-CSDN博客
四、接口说明
人脸采集接口
- 请求 URL:
POST /sys/person/addPerson
- 请求参数:
json
{
"personId": 98,
"extName": "png",
"fileBase64": "iVBORw0KGgoAAAANSUhEUgAAAJsAAAC4CAYAAAD0WZ4UAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJ8pt02jBn6wUmcy/39/xgi2nSFeQGzAAAAAElFTkSuQmCC"
}
- 返回结果:
json
{
"msg": "操作成功",
"code": 200
}