You've already forked FrameTour-BE
百度人脸识别
This commit is contained in:
12
pom.xml
12
pom.xml
@ -70,6 +70,11 @@
|
|||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@ -181,6 +186,13 @@
|
|||||||
<artifactId>aliyun-java-sdk-facebody</artifactId>
|
<artifactId>aliyun-java-sdk-facebody</artifactId>
|
||||||
<version>2.0.12</version>
|
<version>2.0.12</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 百度智能云人脸识别 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baidu.aip</groupId>
|
||||||
|
<artifactId>java-sdk</artifactId>
|
||||||
|
<version>4.16.19</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.ycwl.basic.facebody;
|
package com.ycwl.basic.facebody;
|
||||||
|
|
||||||
import com.ycwl.basic.facebody.adapter.AliFaceBodyAdapter;
|
import com.ycwl.basic.facebody.adapter.AliFaceBodyAdapter;
|
||||||
|
import com.ycwl.basic.facebody.adapter.BceFaceBodyAdapter;
|
||||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||||
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
||||||
import com.ycwl.basic.facebody.exceptions.FaceBodyUnsupportedException;
|
import com.ycwl.basic.facebody.exceptions.FaceBodyUnsupportedException;
|
||||||
@ -25,6 +26,8 @@ public class FaceBodyFactory {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case ALI:
|
case ALI:
|
||||||
return new AliFaceBodyAdapter();
|
return new AliFaceBodyAdapter();
|
||||||
|
case BCE:
|
||||||
|
return new BceFaceBodyAdapter();
|
||||||
default:
|
default:
|
||||||
throw new FaceBodyUnsupportedException("不支持的Adapter类型");
|
throw new FaceBodyUnsupportedException("不支持的Adapter类型");
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import com.ycwl.basic.ratelimiter.FixedRateLimiter;
|
|||||||
import com.ycwl.basic.ratelimiter.IRateLimiter;
|
import com.ycwl.basic.ratelimiter.IRateLimiter;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -35,8 +36,9 @@ import java.util.stream.Collectors;
|
|||||||
public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
||||||
private static final Map<String, IRateLimiter> addEntityLimiters = new ConcurrentHashMap<>();
|
private static final Map<String, IRateLimiter> addEntityLimiters = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, IRateLimiter> addFaceLimiters = new ConcurrentHashMap<>();
|
private static final Map<String, IRateLimiter> addFaceLimiters = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, IRateLimiter> searchFaceLimiters = new ConcurrentHashMap<>();
|
|
||||||
private static final Map<String, IRateLimiter> addDbLimiters = new ConcurrentHashMap<>();
|
private static final Map<String, IRateLimiter> addDbLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> listDbLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> searchFaceLimiters = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, IRateLimiter> deleteDbLimiters = new ConcurrentHashMap<>();
|
private static final Map<String, IRateLimiter> deleteDbLimiters = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, IRateLimiter> deleteEntityLimiters = new ConcurrentHashMap<>();
|
private static final Map<String, IRateLimiter> deleteEntityLimiters = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@ -74,6 +76,11 @@ public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
addFaceLimiters.put(config.getAccessKeyId(), new FixedRateLimiter(600, TimeUnit.MILLISECONDS));
|
addFaceLimiters.put(config.getAccessKeyId(), new FixedRateLimiter(600, TimeUnit.MILLISECONDS));
|
||||||
}
|
}
|
||||||
return addFaceLimiters.get(config.getAccessKeyId());
|
return addFaceLimiters.get(config.getAccessKeyId());
|
||||||
|
case LIST_DB:
|
||||||
|
if (listDbLimiters.get(config.getAccessKeyId()) == null) {
|
||||||
|
listDbLimiters.put(config.getAccessKeyId(), new FixedRateLimiter(500, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
return listDbLimiters.get(config.getAccessKeyId());
|
||||||
case SEARCH_FACE:
|
case SEARCH_FACE:
|
||||||
if (searchFaceLimiters.get(config.getAccessKeyId()) == null) {
|
if (searchFaceLimiters.get(config.getAccessKeyId()) == null) {
|
||||||
searchFaceLimiters.put(config.getAccessKeyId(), new FixedRateLimiter(200, TimeUnit.MILLISECONDS));
|
searchFaceLimiters.put(config.getAccessKeyId(), new FixedRateLimiter(200, TimeUnit.MILLISECONDS));
|
||||||
@ -244,7 +251,9 @@ public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
} else {
|
} else {
|
||||||
listFaceEntitiesRequest.setLimit(200);
|
listFaceEntitiesRequest.setLimit(200);
|
||||||
}
|
}
|
||||||
listFaceEntitiesRequest.setEntityIdPrefix(prefix);
|
if (StringUtils.isNotEmpty(prefix)) {
|
||||||
|
listFaceEntitiesRequest.setEntityIdPrefix(prefix);
|
||||||
|
}
|
||||||
try (ClientWrapper clientWrapper = getClient()) {
|
try (ClientWrapper clientWrapper = getClient()) {
|
||||||
IAcsClient client = clientWrapper.getClient();
|
IAcsClient client = clientWrapper.getClient();
|
||||||
try {
|
try {
|
||||||
@ -275,6 +284,7 @@ public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
SearchFaceResponse response = client.getAcsResponse(request);
|
SearchFaceResponse response = client.getAcsResponse(request);
|
||||||
List<SearchFaceResponse.Data.MatchListItem> matchList = response.getData().getMatchList();
|
List<SearchFaceResponse.Data.MatchListItem> matchList = response.getData().getMatchList();
|
||||||
if (matchList.isEmpty()) {
|
if (matchList.isEmpty()) {
|
||||||
|
resp.setOriginalFaceScore(0f);
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
SearchFaceResponse.Data.MatchListItem matchItem = matchList.get(0);
|
SearchFaceResponse.Data.MatchListItem matchItem = matchList.get(0);
|
||||||
@ -326,6 +336,7 @@ public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
|||||||
ADD_DB,
|
ADD_DB,
|
||||||
ADD_ENTITY,
|
ADD_ENTITY,
|
||||||
ADD_FACE,
|
ADD_FACE,
|
||||||
|
LIST_DB,
|
||||||
SEARCH_FACE,
|
SEARCH_FACE,
|
||||||
DELETE_DB,
|
DELETE_DB,
|
||||||
DELETE_ENTITY,
|
DELETE_ENTITY,
|
||||||
|
@ -0,0 +1,377 @@
|
|||||||
|
package com.ycwl.basic.facebody.adapter;
|
||||||
|
|
||||||
|
import com.baidu.aip.face.AipFace;
|
||||||
|
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
||||||
|
import com.ycwl.basic.facebody.entity.AliFaceBodyConfig;
|
||||||
|
import com.ycwl.basic.facebody.entity.BceFaceBodyConfig;
|
||||||
|
import com.ycwl.basic.facebody.entity.SearchFaceResp;
|
||||||
|
import com.ycwl.basic.facebody.entity.SearchFaceResultItem;
|
||||||
|
import com.ycwl.basic.utils.ratelimiter.FixedRateLimiter;
|
||||||
|
import com.ycwl.basic.utils.ratelimiter.IRateLimiter;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class BceFaceBodyAdapter implements IFaceBodyAdapter {
|
||||||
|
protected static final Map<String, AipFace> clients = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> addEntityLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> addFaceLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> addDbLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> listDbLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> listFaceLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> searchFaceLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> deleteDbLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> deleteEntityLimiters = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, IRateLimiter> deleteFaceLimiters = new ConcurrentHashMap<>();
|
||||||
|
private BceFaceBodyConfig config;
|
||||||
|
|
||||||
|
public boolean setConfig(BceFaceBodyConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean loadConfig(Map<String, String> _config) {
|
||||||
|
BceFaceBodyConfig config = new BceFaceBodyConfig();
|
||||||
|
config.setAppId(_config.get("appId"));
|
||||||
|
config.setApiKey(_config.get("apiKey"));
|
||||||
|
config.setSecretKey(_config.get("secretKey"));
|
||||||
|
config.setAddQps(Float.parseFloat(_config.get("addQps")));
|
||||||
|
config.setSearchQps(Float.parseFloat(_config.get("searchQps")));
|
||||||
|
this.config = config;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addFaceDb(String dbName) {
|
||||||
|
IRateLimiter addDbLimiter = getLimiter(LOCK_TYPE.ADD_DB);
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
try {
|
||||||
|
addDbLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
JSONObject response = client.groupAdd(dbName, options);
|
||||||
|
if (response.getInt("error_code") == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.warn("创建人脸库失败!{}", response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建人脸库失败!", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteFaceDb(String dbName) {
|
||||||
|
IRateLimiter deleteDbLimiter = getLimiter(LOCK_TYPE.DELETE_DB);
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
try {
|
||||||
|
deleteDbLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
JSONObject response = client.groupDelete(dbName, options);
|
||||||
|
if (response.getInt("error_code") == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.warn("删除人脸库失败!{}", response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("删除人脸库失败!", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> listFaceDb() {
|
||||||
|
IRateLimiter listDbLimiter = getLimiter(LOCK_TYPE.LIST_DB);
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
options.put("start", "0");
|
||||||
|
options.put("length", "1000");
|
||||||
|
try {
|
||||||
|
listDbLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
JSONObject response = client.getGroupList(options);
|
||||||
|
if (response.getInt("error_code") == 0) {
|
||||||
|
JSONObject resultObj = response.getJSONObject("result");
|
||||||
|
if (resultObj != null) {
|
||||||
|
JSONArray data = resultObj.getJSONArray("group_id_list");
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
for (int i = 0; i < data.length(); i++) {
|
||||||
|
result.add(data.getString(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("获取人脸库列表失败!{}", response);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取人脸库列表失败!", e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AddFaceResp addFace(String dbName, String entityId, String faceUrl, String extData) {
|
||||||
|
IRateLimiter addEntityLimiter = getLimiter(LOCK_TYPE.ADD_FACE);
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
options.put("user_info", extData);
|
||||||
|
options.put("quality_control", "LOW");
|
||||||
|
options.put("action_type", "REPLACE");
|
||||||
|
try {
|
||||||
|
addEntityLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
JSONObject response = client.addUser(faceUrl, "URL", dbName, entityId, options);
|
||||||
|
if (response.getInt("error_code") == 0) {
|
||||||
|
AddFaceResp resp = new AddFaceResp();
|
||||||
|
resp.setScore(100f);
|
||||||
|
return resp;
|
||||||
|
} else {
|
||||||
|
log.warn("创建人脸失败!{}", response);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建人脸失败!", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteFace(String dbName, String entityId) {
|
||||||
|
IRateLimiter deleteFaceLimiter = getLimiter(LOCK_TYPE.DELETE_FACE);
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
List<String> tokenList = listUserFace(dbName, entityId);
|
||||||
|
AtomicInteger count = new AtomicInteger(0);
|
||||||
|
tokenList.forEach(faceToken -> {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
deleteFaceLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
JSONObject response = client.faceDelete(entityId, dbName, faceToken, options);
|
||||||
|
if (response.getInt("error_code") != 0) {
|
||||||
|
log.warn("删除人脸失败!{}", response);
|
||||||
|
} else {
|
||||||
|
count.incrementAndGet();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("删除人脸失败!", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Integer.valueOf(count.get()).equals(tokenList.size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("删除人脸失败!", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> listFace(String dbName, String prefix, Integer offset, Integer size) {
|
||||||
|
IRateLimiter listFaceLimiter = getLimiter(LOCK_TYPE.LIST_FACE);
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
options.put("start", offset == null ? "0" : offset.toString());
|
||||||
|
options.put("length", size == null ? "1000" : size.toString());
|
||||||
|
try {
|
||||||
|
listFaceLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
JSONObject response = client.getGroupUsers(dbName, options);
|
||||||
|
if (response.getInt("error_code") == 0) {
|
||||||
|
JSONObject resultObj = response.getJSONObject("result");
|
||||||
|
if (resultObj != null) {
|
||||||
|
JSONArray data = resultObj.getJSONArray("user_id_list");
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
for (int i = 0; i < data.length(); i++) {
|
||||||
|
result.add(data.getString(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("获取人脸列表失败!{}", response);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取人脸列表失败!", e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> listUserFace(String dbName, String entityId) {
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, String> options = new HashMap<>();
|
||||||
|
JSONObject response = client.faceGetlist(entityId, dbName, options);
|
||||||
|
if (response.getInt("error_code") == 0) {
|
||||||
|
JSONObject resultObj = response.getJSONObject("result");
|
||||||
|
if (resultObj != null) {
|
||||||
|
JSONArray faceList = resultObj.getJSONArray("face_list");
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
for (int i = 0; i < faceList.length(); i++) {
|
||||||
|
JSONObject jsonObject = faceList.getJSONObject(i);
|
||||||
|
result.add(jsonObject.getString("face_token"));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("获取人脸列表失败!{}", response);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取人脸列表失败!", e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchFaceResp searchFace(String dbName, String faceUrl) {
|
||||||
|
IRateLimiter searchFaceLimiter = getLimiter(LOCK_TYPE.SEARCH_FACE);
|
||||||
|
SearchFaceResp resp = new SearchFaceResp();
|
||||||
|
try {
|
||||||
|
AipFace client = getClient();
|
||||||
|
HashMap<String, Object> options = new HashMap<>();
|
||||||
|
options.put("quality_control", "LOW");
|
||||||
|
options.put("max_user_num", "50");
|
||||||
|
try {
|
||||||
|
searchFaceLimiter.acquire();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
JSONObject response = client.search(faceUrl, "URL", dbName, options);
|
||||||
|
if (response.getInt("error_code") == 0) {
|
||||||
|
resp.setOriginalFaceScore(100f);
|
||||||
|
JSONArray userList = response.getJSONArray("user_list");
|
||||||
|
List<SearchFaceResultItem> result = new ArrayList<>();
|
||||||
|
for (int i = 0; i < userList.length(); i++) {
|
||||||
|
JSONObject user = userList.getJSONObject(i);
|
||||||
|
SearchFaceResultItem item = new SearchFaceResultItem();
|
||||||
|
item.setDbName(dbName);
|
||||||
|
item.setFaceId(user.getString("user_id"));
|
||||||
|
item.setExtData(user.getString("user_info"));
|
||||||
|
item.setScore(user.getBigDecimal("score").divide(BigDecimal.valueOf(100), 6, RoundingMode.HALF_UP).floatValue());
|
||||||
|
result.add(item);
|
||||||
|
}
|
||||||
|
resp.setResult(result);
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
resp.setFirstMatchRate(result.get(0).getScore());
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
} else {
|
||||||
|
resp.setOriginalFaceScore(0f);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("搜索人脸失败!", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AipFace getClient() {
|
||||||
|
if (clients.containsKey(config.getAppId())) {
|
||||||
|
return clients.get(config.getAppId());
|
||||||
|
}
|
||||||
|
synchronized (clients) {
|
||||||
|
if (clients.containsKey(config.getAppId())) {
|
||||||
|
return clients.get(config.getAppId());
|
||||||
|
}
|
||||||
|
AipFace client = new AipFace(config.getAppId(), config.getApiKey(), config.getSecretKey());
|
||||||
|
client.setConnectionTimeoutInMillis(5000);
|
||||||
|
client.setSocketTimeoutInMillis(60000);
|
||||||
|
clients.put(config.getAppId(), client);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IRateLimiter getLimiter(LOCK_TYPE type) {
|
||||||
|
switch (type) {
|
||||||
|
case ADD_DB:
|
||||||
|
if (addDbLimiters.get(config.getAppId()) == null) {
|
||||||
|
addDbLimiters.put(config.getAppId(), new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
return addDbLimiters.get(config.getAppId());
|
||||||
|
case ADD_FACE:
|
||||||
|
if (addFaceLimiters.get(config.getAppId()) == null) {
|
||||||
|
addFaceLimiters.put(config.getAppId(), new FixedRateLimiter(config.getAddQps()));
|
||||||
|
}
|
||||||
|
return addFaceLimiters.get(config.getAppId());
|
||||||
|
case LIST_DB:
|
||||||
|
if (listDbLimiters.get(config.getAppId()) == null) {
|
||||||
|
listDbLimiters.put(config.getAppId(), new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
return listDbLimiters.get(config.getAppId());
|
||||||
|
case LIST_FACE:
|
||||||
|
if (listFaceLimiters.get(config.getAppId()) == null) {
|
||||||
|
listFaceLimiters.put(config.getAppId(), new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
return listFaceLimiters.get(config.getAppId());
|
||||||
|
case SEARCH_FACE:
|
||||||
|
if (searchFaceLimiters.get(config.getAppId()) == null) {
|
||||||
|
searchFaceLimiters.put(config.getAppId(), new FixedRateLimiter(config.getSearchQps()));
|
||||||
|
}
|
||||||
|
return searchFaceLimiters.get(config.getAppId());
|
||||||
|
case DELETE_DB:
|
||||||
|
if (deleteDbLimiters.get(config.getAppId()) == null) {
|
||||||
|
deleteDbLimiters.put(config.getAppId(), new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
return deleteDbLimiters.get(config.getAppId());
|
||||||
|
case DELETE_ENTITY:
|
||||||
|
if (deleteEntityLimiters.get(config.getAppId()) == null) {
|
||||||
|
deleteEntityLimiters.put(config.getAppId(), new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
return deleteEntityLimiters.get(config.getAppId());
|
||||||
|
case DELETE_FACE:
|
||||||
|
if (deleteFaceLimiters.get(config.getAppId()) == null) {
|
||||||
|
deleteFaceLimiters.put(config.getAppId(), new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||||
|
}
|
||||||
|
return deleteFaceLimiters.get(config.getAppId());
|
||||||
|
default:
|
||||||
|
return new FixedRateLimiter(500, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected enum LOCK_TYPE {
|
||||||
|
ADD_DB,
|
||||||
|
ADD_FACE,
|
||||||
|
LIST_DB,
|
||||||
|
LIST_FACE,
|
||||||
|
SEARCH_FACE,
|
||||||
|
DELETE_DB,
|
||||||
|
DELETE_ENTITY,
|
||||||
|
DELETE_FACE,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.ycwl.basic.facebody.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class BceFaceBodyConfig {
|
||||||
|
private String appId;
|
||||||
|
private String apiKey;
|
||||||
|
private String secretKey;
|
||||||
|
private float addQps = 2.0f;
|
||||||
|
private float searchQps = 2.0f;
|
||||||
|
}
|
@ -4,7 +4,8 @@ import lombok.Getter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public enum FaceBodyAdapterType {
|
public enum FaceBodyAdapterType {
|
||||||
ALI("ALI")
|
ALI("ALI"),
|
||||||
|
BCE("BCE"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String code;
|
private final String code;
|
||||||
|
@ -9,6 +9,16 @@ public class FixedRateLimiter implements IRateLimiter {
|
|||||||
private final Semaphore semaphore = new Semaphore(1);
|
private final Semaphore semaphore = new Semaphore(1);
|
||||||
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
||||||
|
|
||||||
|
public FixedRateLimiter(float maxRequestsPerSecond) {
|
||||||
|
int rate = Float.valueOf(1000000 / maxRequestsPerSecond).intValue();
|
||||||
|
scheduler.scheduleAtFixedRate(() -> {
|
||||||
|
if (semaphore.availablePermits() < 1) {
|
||||||
|
semaphore.release(1);
|
||||||
|
}
|
||||||
|
}, rate, rate, TimeUnit.NANOSECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public FixedRateLimiter(int rate, TimeUnit timeUnit) {
|
public FixedRateLimiter(int rate, TimeUnit timeUnit) {
|
||||||
// 启动一个线程每0.5秒释放一个许可
|
// 启动一个线程每0.5秒释放一个许可
|
||||||
scheduler.scheduleAtFixedRate(() -> {
|
scheduler.scheduleAtFixedRate(() -> {
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.ycwl.basic.facebody.adapter;
|
||||||
|
|
||||||
|
import com.ycwl.basic.facebody.entity.BceFaceBodyConfig;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class BceFaceBodyAdapterTest {
|
||||||
|
private BceFaceBodyAdapter getAdapter() {
|
||||||
|
BceFaceBodyAdapter adapter = new BceFaceBodyAdapter();
|
||||||
|
BceFaceBodyConfig config = new BceFaceBodyConfig();
|
||||||
|
config.setAppId("118363478");
|
||||||
|
config.setApiKey("3rXrDdU4cHZqLS8ICFSYZKse");
|
||||||
|
config.setSecretKey("zgGFehERZKYXEiRQpqWs9AYchLxzXzYa");
|
||||||
|
adapter.setConfig(config);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDbCreate() {
|
||||||
|
BceFaceBodyAdapter adapter = getAdapter();
|
||||||
|
boolean b = adapter.addFaceDb("test");
|
||||||
|
assertTrue(b);
|
||||||
|
boolean b0 = adapter.assureFaceDb("test");
|
||||||
|
assertTrue(b0);
|
||||||
|
boolean b1 = adapter.deleteFaceDb("test");
|
||||||
|
assertTrue(b1);
|
||||||
|
boolean b2 = adapter.assureFaceDb("test");
|
||||||
|
assertTrue(b2);
|
||||||
|
boolean b3 = adapter.deleteFaceDb("test");
|
||||||
|
assertTrue(b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddFace() {
|
||||||
|
BceFaceBodyAdapter adapter = getAdapter();
|
||||||
|
adapter.assureFaceDb("test");
|
||||||
|
adapter.addFace("test", "test", "https://frametour-assets.oss-cn-shanghai.aliyuncs.com/user-faces/user-face/c925d970-216a-4eff-b699-cd047c0f9088.jpg", "test");
|
||||||
|
List<String> strings = adapter.listUserFace("test", "test");
|
||||||
|
assertFalse(strings.isEmpty());
|
||||||
|
adapter.deleteFace("test", "test");
|
||||||
|
List<String> stringList = adapter.listUserFace("test", "test");
|
||||||
|
assertTrue(stringList.isEmpty());
|
||||||
|
List<String> listFace = adapter.listFace("test", null, 0, 10);
|
||||||
|
assertTrue(listFace.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user