mirror of
https://gitee.com/open-visual/face-search.git
synced 2025-07-25 19:41:42 +08:00
update:添加人脸比对1:1的接口服务
This commit is contained in:
parent
1dafa9f0e1
commit
2fbb092926
@ -29,6 +29,25 @@ public class Similarity {
|
|||||||
}
|
}
|
||||||
return (float) cosineSimilarity;
|
return (float) cosineSimilarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 两个向量可以为任意维度,但必须保持维度相同,表示n维度中的两点
|
||||||
|
* 欧式距离
|
||||||
|
* @param vector1
|
||||||
|
* @param vector2
|
||||||
|
* @return 两点间距离
|
||||||
|
*/
|
||||||
|
public static float euclideanDistance(float[] vector1, float[] vector2) {
|
||||||
|
double distance = 0;
|
||||||
|
if (vector1.length == vector2.length) {
|
||||||
|
for (int i = 0; i < vector1.length; i++) {
|
||||||
|
double temp = Math.pow((vector1[i] - vector2[i]), 2);
|
||||||
|
distance += temp;
|
||||||
|
}
|
||||||
|
distance = Math.sqrt(distance);
|
||||||
|
}
|
||||||
|
return (float) distance;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,28 @@
|
|||||||
package com.visual.face.search.server.controller.server.impl;
|
package com.visual.face.search.server.controller.server.impl;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import com.visual.face.search.server.controller.base.BaseController;
|
||||||
import com.visual.face.search.server.controller.server.api.FaceCompareControllerApi;
|
import com.visual.face.search.server.controller.server.api.FaceCompareControllerApi;
|
||||||
import com.visual.face.search.server.domain.common.ResponseInfo;
|
import com.visual.face.search.server.domain.common.ResponseInfo;
|
||||||
import com.visual.face.search.server.domain.request.FaceCompareReqVo;
|
import com.visual.face.search.server.domain.request.FaceCompareReqVo;
|
||||||
import com.visual.face.search.server.domain.response.FaceCompareRepVo;
|
import com.visual.face.search.server.domain.response.FaceCompareRepVo;
|
||||||
|
import com.visual.face.search.server.service.api.FaceCompareService;
|
||||||
|
import com.visual.face.search.server.utils.ResponseBuilder;
|
||||||
|
|
||||||
public class FaceCompareControllerImpl implements FaceCompareControllerApi {
|
|
||||||
|
public class FaceCompareControllerImpl extends BaseController implements FaceCompareControllerApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FaceCompareService faceCompareService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseInfo<FaceCompareRepVo> faceCompare(FaceCompareReqVo compareReq) {
|
public ResponseInfo<FaceCompareRepVo> faceCompare(FaceCompareReqVo compareReq) {
|
||||||
return null;
|
try {
|
||||||
|
return ResponseBuilder.success(faceCompareService.faceCompare(compareReq));
|
||||||
|
}catch (Exception e){
|
||||||
|
logger.error("do faceCompare exception:", e);
|
||||||
|
return ResponseBuilder.exception(e.getMessage(), null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.visual.face.search.server.service.api;
|
||||||
|
|
||||||
|
import com.visual.face.search.server.domain.request.FaceCompareReqVo;
|
||||||
|
import com.visual.face.search.server.domain.response.FaceCompareRepVo;
|
||||||
|
|
||||||
|
public interface FaceCompareService {
|
||||||
|
|
||||||
|
public FaceCompareRepVo faceCompare(FaceCompareReqVo compareReq);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.visual.face.search.server.service.impl;
|
||||||
|
|
||||||
|
import com.visual.face.search.core.domain.ExtParam;
|
||||||
|
import com.visual.face.search.core.domain.FaceImage;
|
||||||
|
import com.visual.face.search.core.domain.FaceInfo;
|
||||||
|
import com.visual.face.search.core.domain.ImageMat;
|
||||||
|
import com.visual.face.search.core.extract.FaceFeatureExtractor;
|
||||||
|
import com.visual.face.search.core.utils.Similarity;
|
||||||
|
import com.visual.face.search.server.domain.extend.CompareFace;
|
||||||
|
import com.visual.face.search.server.domain.extend.FaceLocation;
|
||||||
|
import com.visual.face.search.server.domain.request.FaceCompareReqVo;
|
||||||
|
import com.visual.face.search.server.domain.response.FaceCompareRepVo;
|
||||||
|
import com.visual.face.search.server.service.api.FaceCompareService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service("visualFaceCompareServiceImpl")
|
||||||
|
public class FaceCompareServiceImpl implements FaceCompareService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FaceFeatureExtractor faceFeatureExtractor;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FaceCompareRepVo faceCompare(FaceCompareReqVo compareReq) {
|
||||||
|
FaceInfo faceInfoA = getFaceInfo(compareReq.getFaceScoreThreshold(), compareReq.getImageBase64A());
|
||||||
|
if(null == faceInfoA){
|
||||||
|
throw new RuntimeException("image A is not face");
|
||||||
|
}
|
||||||
|
FaceInfo faceInfoB = getFaceInfo(compareReq.getFaceScoreThreshold(), compareReq.getImageBase64B());
|
||||||
|
if(null == faceInfoB){
|
||||||
|
throw new RuntimeException("image B is not face");
|
||||||
|
}
|
||||||
|
//计算余弦相似度
|
||||||
|
float simVal = Similarity.cosineSimilarity(faceInfoA.embedding.embeds, faceInfoA.embedding.embeds);
|
||||||
|
float confidence = (float) Math.floor(simVal * 10000)/100;
|
||||||
|
//欧式距离
|
||||||
|
float distance = Similarity.euclideanDistance(faceInfoA.embedding.embeds, faceInfoA.embedding.embeds);
|
||||||
|
//构建返回值
|
||||||
|
FaceCompareRepVo faceCompareRep = new FaceCompareRepVo();
|
||||||
|
faceCompareRep.setDistance(distance);
|
||||||
|
faceCompareRep.setConfidence(confidence);
|
||||||
|
if(compareReq.getNeedFaceInfo()){
|
||||||
|
CompareFace compareFace = new CompareFace();
|
||||||
|
compareFace.setFaceScoreA(faceInfoA.score);
|
||||||
|
compareFace.setFaceScoreB(faceInfoB.score);
|
||||||
|
FaceInfo.FaceBox boxA = faceInfoA.box;
|
||||||
|
compareFace.setLocationA(FaceLocation.build(boxA.leftTop.x, boxA.leftTop.y, boxA.width(), boxA.height()));
|
||||||
|
FaceInfo.FaceBox boxB = faceInfoB.box;
|
||||||
|
compareFace.setLocationB(FaceLocation.build(boxB.leftTop.x, boxB.leftTop.y, boxB.width(), boxB.height()));
|
||||||
|
faceCompareRep.setFaceInfo(compareFace);
|
||||||
|
}
|
||||||
|
//返回对象
|
||||||
|
return faceCompareRep;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片检测并提取人脸特征
|
||||||
|
* @param faceScoreThreshold
|
||||||
|
* @param imageBase64
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private FaceInfo getFaceInfo(float faceScoreThreshold, String imageBase64){
|
||||||
|
faceScoreThreshold = faceScoreThreshold < 0 ? 0 : faceScoreThreshold;
|
||||||
|
faceScoreThreshold = faceScoreThreshold > 100 ? 100 : faceScoreThreshold;
|
||||||
|
faceScoreThreshold = faceScoreThreshold > 1 ? faceScoreThreshold / 100 : faceScoreThreshold;
|
||||||
|
|
||||||
|
ExtParam extParam = ExtParam.build().setMask(true).setScoreTh(faceScoreThreshold).setIouTh(0).setTopK(1);
|
||||||
|
ImageMat imageMat = null;
|
||||||
|
FaceImage faceImage = null;
|
||||||
|
try {
|
||||||
|
imageMat = ImageMat.fromBase64(imageBase64);
|
||||||
|
faceImage = faceFeatureExtractor.extract(imageMat, extParam, new HashMap<>());
|
||||||
|
}finally {
|
||||||
|
if(null != imageMat){
|
||||||
|
imageMat.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(null == faceImage){
|
||||||
|
throw new RuntimeException("FeatureExtractor extract error");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FaceInfo> faceInfos = faceImage.faceInfos();
|
||||||
|
if(faceInfos.size() > 0){
|
||||||
|
return faceInfos.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user