Commit 6a0f781c by xmh

人体比对结果改为每个特征池10个,人体特征存储和比对前进行权重计算

1 parent ca25ceb7
......@@ -28,6 +28,12 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>android-json</artifactId>
<groupId>com.vaadin.external.google</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.viontech.keliu</groupId>
......@@ -57,7 +63,7 @@
<dependency>
<groupId>com.viontech.keliu</groupId>
<artifactId>AlgApiClient</artifactId>
<version>6.0.4-SNAPSHOT</version>
<version>6.0.5-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>javax</groupId>
......
......@@ -5,10 +5,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = {"com.viontech"})public class XmhTestApplication {
@ComponentScan(basePackages = {"com.viontech"})public class MatchApp {
public static void main(String[] args) {
SpringApplication.run(XmhTestApplication.class, args);
SpringApplication.run(MatchApp.class, args);
}
}
\ No newline at end of file
......@@ -12,7 +12,8 @@ public class Constant {
/** 人脸特征维数 */
public final static int FACE_FEATURE_DIMS = 512;
/** 人体特征维数 */
public final static int BODY_FEATURE_DIMS = 2048;
public final static int BODY_FEATURE_DIMS_2048 = 2048;
public final static int BODY_FEATURE_DIMS_2110 = 2110;
/** poolId不存在时es返回的message所包含的字段 */
public final static String STR_POOL_ID_ALREADY_EXISTS = "already_exists";
......@@ -21,5 +22,7 @@ public class Constant {
public final static String CLASS_CAST_EXCEPTION = "class_cast_exception";
/** 人脸匹配结果的数量 */
public final static int MATCH_RESULT_SIZE = 5;
public final static int FACE_MATCH_RESULT_SIZE = 5;
/** 人体匹配结果的数量 */
public final static int BODY_MATCH_RESULT_SIZE = 10;
}
......@@ -8,6 +8,7 @@ import com.viontech.keliu.model.Pool;
import com.viontech.match.config.Constant;
import com.viontech.match.entity.vo.RequestVo;
import com.viontech.match.entity.vo.ResponseVo;
import com.viontech.match.util.Utils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.bulk.BulkRequest;
......@@ -79,7 +80,7 @@ public class PersonService {
pool.setPersonPoolId(id);
if (poolService.existPool(id)) {
pool.setStatus(0);
List<Person> face = matchPerson(id, requestVo.getPerson(),0);
List<Person> face = matchPerson(id, requestVo.getPerson(), 0);
matchFaces.addAll(face);
List<Person> body = matchPerson(id, requestVo.getPerson(), 1);
matchBodies.addAll(body);
......@@ -167,11 +168,14 @@ public class PersonService {
if (bodyFeatures != null && bodyFeatures.size() > 0) {
for (BodyFeature bodyFeature : bodyFeatures) {
Double[] feature = bodyFeature.getFeature();
if (feature == null || feature.length < Constant.BODY_FEATURE_DIMS) {
if (feature == null || feature.length < Constant.BODY_FEATURE_DIMS_2048) {
continue;
} else if (feature.length == Constant.BODY_FEATURE_DIMS_2110) {
feature = Utils.transferBodyFeature(feature);
}
if (feature.length > Constant.BODY_FEATURE_DIMS) {
feature = Arrays.copyOfRange(feature, 3, Constant.BODY_FEATURE_DIMS + 3);
if (feature.length > Constant.BODY_FEATURE_DIMS_2048) {
feature = Arrays.copyOfRange(feature, 3, Constant.BODY_FEATURE_DIMS_2048 + 3);
}
String fid = bodyFeature.getBid();
......@@ -201,20 +205,22 @@ public class PersonService {
}
public List<Person> matchPerson(String poolId, Person person , int type) throws Exception {
public List<Person> matchPerson(String poolId, Person person, int type) throws Exception {
List<Person> matchResult = new ArrayList<>();
int matchResultSize = 0;
if (type == 0) {
List<FaceFeature> faceFeatures = person.getFaceFeatures();
matchFace(faceFeatures, poolId, matchResult);
}else {
matchResultSize = Constant.FACE_MATCH_RESULT_SIZE;
} else {
List<BodyFeature> bodyFeatures = person.getBodyFeatures();
matchBody(bodyFeatures, poolId, matchResult);
matchResultSize = Constant.BODY_MATCH_RESULT_SIZE;
}
Stream<Person> stream = matchResult.stream().sorted(Comparator.comparingInt(Person::getScore).reversed());
if (matchResult.size() > Constant.MATCH_RESULT_SIZE) {
stream = stream.limit(5);
if (matchResult.size() > matchResultSize) {
stream = stream.limit(matchResultSize);
}
matchResult = stream.collect(Collectors.toList());
return matchResult;
......@@ -247,12 +253,15 @@ public class PersonService {
if (bodyFeatures != null && bodyFeatures.size() > 0) {
for (BodyFeature faceFeature : bodyFeatures) {
Double[] feature = faceFeature.getFeature();
if (feature == null || feature.length < Constant.BODY_FEATURE_DIMS) {
if (feature == null || feature.length < Constant.BODY_FEATURE_DIMS_2048) {
log.info("人体特征维数小于2048,跳过比对");
continue;
} else if (feature.length == Constant.BODY_FEATURE_DIMS_2110) {
feature = Utils.transferBodyFeature(feature);
}
if (feature.length > Constant.BODY_FEATURE_DIMS) {
feature = Arrays.copyOfRange(feature, 3, Constant.BODY_FEATURE_DIMS + 3);
if (feature.length > Constant.BODY_FEATURE_DIMS_2048) {
feature = Arrays.copyOfRange(feature, 3, Constant.BODY_FEATURE_DIMS_2048 + 3);
}
Script script = new Script(
......@@ -260,16 +269,20 @@ public class PersonService {
"(cosineSimilarity(params.body, 'body') + 1) / 2 * 100", Collections.singletonMap("body", feature));
ScriptScoreQueryBuilder queryBuilder = QueryBuilders.scriptScoreQuery(QueryBuilders.existsQuery("body"), script);
matchResult.addAll(match0(poolId, queryBuilder));
matchResult.addAll(match0(poolId, queryBuilder, Constant.BODY_MATCH_RESULT_SIZE));
}
}
}
private List<Person> match0(String poolId, ScriptScoreQueryBuilder scriptScoreQueryBuilder) throws IOException {
return match0(poolId, scriptScoreQueryBuilder, Constant.FACE_MATCH_RESULT_SIZE);
}
private List<Person> match0(String poolId, ScriptScoreQueryBuilder scriptScoreQueryBuilder, Integer matchResultSize) throws IOException {
List<Person> persons = new ArrayList<>();
SearchSourceBuilder builder = new SearchSourceBuilder()
.size(Constant.MATCH_RESULT_SIZE)
.size(matchResultSize)
.query(scriptScoreQueryBuilder)
.fetchSource(new String[]{"personId", "age", "gender", "fid"}, null);
SearchRequest searchRequest = new SearchRequest(poolId)
......
......@@ -196,7 +196,7 @@ public class PoolService {
builder.startObject("body");
{
builder.field("type", "dense_vector");
builder.field("dims", Constant.BODY_FEATURE_DIMS);
builder.field("dims", Constant.BODY_FEATURE_DIMS_2048);
}
builder.endObject();
// 人员id
......
package com.viontech.match.util;
import java.awt.*;
import java.awt.image.BufferedImage;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
/**
* .
......@@ -9,24 +10,68 @@ import java.awt.image.BufferedImage;
* @author 谢明辉
* @date 2020/11/23
*/
@Slf4j
@SuppressWarnings("ALL")
public class Utils {
public static BufferedImage convertImg2Jpg(BufferedImage image) {
BufferedImage newBufferedImage;
//防止图片变色
int width = image.getWidth();
int height = image.getHeight();
if (width > 600 || height > 600) {
newBufferedImage = new BufferedImage(600, 600, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = newBufferedImage.createGraphics();
graphics.drawImage(image, 0, 0, 600, 600, Color.WHITE, null);
/**
* 将 2110 维的人体特征加权计算得到 2048 维特征数据
*
* @param f1 2110 维的人体特征数据
*
* @return 加权计算后的结果
*/
public static Double[] transferBodyFeature(Double[] f1) {
try {
int featureLen = f1[0].intValue();
int npiece = f1[1].intValue();
Double[] vec1 = Arrays.copyOfRange(f1, 3, 2048 + 3);
Double[] temp = Arrays.copyOfRange(f1, 3 + featureLen + npiece, f1.length);
Double[] wt1 = getWeights(temp);
Double normCoeF1 = 0D;
for (int i = 0; i < 8; i++) {
normCoeF1 += wt1[i] * wt1[i] * f1[3 + 2048 + i];
}
normCoeF1 = 1 / Math.sqrt(normCoeF1);
for (int i = 0; i < 2048; i++) {
vec1[i] = vec1[i] * wt1[i / 256] * normCoeF1;
}
return vec1;
} catch (Throwable e) {
log.error("转换出错", e);
}
return f1;
}
private static Double[] getWeights(Double[] landmarks) {
Double[] wt = new Double[8];
Arrays.fill(wt, 1D);
if (landmarks[15 * 3 + 2] > 0.8 && landmarks[16 * 3 + 2] > 0.8) {
} else if (landmarks[15 * 3 + 2] > 0.8 || landmarks[16 * 3 + 2] > 0.8) {
wt[7] = 0.7;
} else if (landmarks[13 * 3 + 2] > 0.8 && landmarks[14 * 3 + 2] > 0.8) {
wt[7] = 0.2;
wt[3] = 0.7;
} else if (landmarks[13 * 3 + 2] > 0.8 || landmarks[14 * 3 + 2] > 0.8) {
wt[7] = 0.1;
wt[3] = 0.4;
} else if (landmarks[11 * 3 + 2] > 0.7 && landmarks[12 * 3 + 2] > 0.7) {
wt[7] = 0D;
wt[3] = 0.2;
wt[6] = 0.8;
wt[2] = 1.1;
wt[5] = 1.1;
} else {
newBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = newBufferedImage.createGraphics();
graphics.drawImage(image, 0, 0, Color.WHITE, null);
wt[7] = 0D;
wt[3] = 0D;
wt[6] = 0.3;
wt[2] = 1.2;
wt[5] = 1.4;
}
return newBufferedImage;
return wt;
}
}
package com.viontech.match.util;
import com.viontech.keliu.utils.JsonUtil;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
/**
* .
*
* @author 谢明辉
* @date 2021/4/6
*/
class UtilsTest {
@Test
void transferBodyFeature() throws Exception {
List<String> strings = Files.readAllLines(Paths.get("C:\\Users\\vion\\Desktop\\body.feature"));
String s = strings.get(0);
JSONObject jsonObject = JsonUtil.toObject(s);
JSONArray datas = jsonObject.getJSONArray("datas");
JSONObject obj = datas.getJSONObject(0);
JSONArray data = obj.getJSONArray("data");
List<Object> objects = data.toList();
Double[] feature = objects.toArray(new Double[]{});
Double[] doubles = Utils.transferBodyFeature(feature);
System.out.println(Arrays.toString(doubles));
}
}
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!