mirror of
https://gitee.com/open-visual/face-search.git
synced 2025-07-25 19:41:42 +08:00
commit
ba33c764eb
12
README.md
12
README.md
@ -32,9 +32,15 @@
|
|||||||
|
|
||||||
    2、[PCN](https://github.com/Rock-100/FaceKit/tree/master/PCN)
|
    2、[PCN](https://github.com/Rock-100/FaceKit/tree/master/PCN)
|
||||||
|
|
||||||
|
### 版本1.1.0更新
|
||||||
|
|
||||||
|
* 1、修复已知BUG
|
||||||
|
* 2、添加人脸比对1:1接口,详见文档:[05、人脸比对服务](https://gitee.com/open-visual/face-search/blob/dev-1.1.0/scripts/docs/doc-1.1.0.md#05%E4%BA%BA%E8%84%B8%E6%AF%94%E5%AF%B9%E6%9C%8D%E5%8A%A1)
|
||||||
|
|
||||||
|
|
||||||
### 项目文档
|
### 项目文档
|
||||||
|
|
||||||
* 在线文档:[文档-1.0.0](https://gitee.com/open-visual/face-search/blob/master/scripts/docs/doc-1.0.0.md)
|
* 在线文档:[文档-1.1.0](https://gitee.com/open-visual/face-search/blob/dev-1.1.0/scripts/docs/doc-1.1.0.md)
|
||||||
|
|
||||||
* swagger文档:启动项目且开启swagger,访问:host:port/doc.html, 如 http://127.0.0.1:8080/doc.html
|
* swagger文档:启动项目且开启swagger,访问:host:port/doc.html, 如 http://127.0.0.1:8080/doc.html
|
||||||
|
|
||||||
@ -45,12 +51,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<artifactId>face-search-client</artifactId>
|
<artifactId>face-search-client</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
* 其他语言依赖
|
* 其他语言依赖
|
||||||
|
|
||||||
   使用restful接口:[文档-1.0.0](https://gitee.com/open-visual/face-search/blob/master/scripts/docs/doc-1.0.0.md)
|
   使用restful接口:[文档-1.1.0](https://gitee.com/open-visual/face-search/blob/dev-1.1.0/scripts/docs/doc-1.1.0.md)
|
||||||
|
|
||||||
|
|
||||||
### 项目部署
|
### 项目部署
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<artifactId>face-search-client</artifactId>
|
<artifactId>face-search-client</artifactId>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>face-search</artifactId>
|
<artifactId>face-search</artifactId>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>face-search-core</artifactId>
|
<artifactId>face-search-core</artifactId>
|
||||||
|
@ -9,7 +9,6 @@ import org.opencv.dnn.Dnn;
|
|||||||
import org.opencv.highgui.HighGui;
|
import org.opencv.highgui.HighGui;
|
||||||
import org.opencv.imgcodecs.Imgcodecs;
|
import org.opencv.imgcodecs.Imgcodecs;
|
||||||
import org.opencv.imgproc.Imgproc;
|
import org.opencv.imgproc.Imgproc;
|
||||||
import sun.misc.BASE64Decoder;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@ -20,6 +19,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片加载工具
|
* 图片加载工具
|
||||||
@ -66,8 +66,11 @@ public class ImageMat implements Serializable {
|
|||||||
public static ImageMat fromBase64(String base64Str){
|
public static ImageMat fromBase64(String base64Str){
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
try {
|
try {
|
||||||
BASE64Decoder decoder = new BASE64Decoder();
|
// 新版本JDK被移除,替换为Base64.Decoder
|
||||||
byte[] data = decoder.decodeBuffer(base64Str);
|
// BASE64Decoder decoder = new BASE64Decoder();
|
||||||
|
// byte[] data = decoder.decodeBuffer(base64Str);
|
||||||
|
Base64.Decoder decoder = Base64.getMimeDecoder();
|
||||||
|
byte[] data = decoder.decode(base64Str);
|
||||||
inputStream = new ByteArrayInputStream(data);
|
inputStream = new ByteArrayInputStream(data);
|
||||||
return fromInputStream(inputStream);
|
return fromInputStream(inputStream);
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.visual.face.search.core.utils;
|
package com.visual.face.search.core.utils;
|
||||||
|
|
||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import sun.misc.BASE64Encoder;
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class MatUtil {
|
public class MatUtil {
|
||||||
@ -42,8 +42,11 @@ public class MatUtil {
|
|||||||
byteArrayOutputStream = new ByteArrayOutputStream();
|
byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
ImageIO.write(matToBufferedImage(mat), "jpg", byteArrayOutputStream);
|
ImageIO.write(matToBufferedImage(mat), "jpg", byteArrayOutputStream);
|
||||||
byte[] bytes = byteArrayOutputStream.toByteArray();
|
byte[] bytes = byteArrayOutputStream.toByteArray();
|
||||||
BASE64Encoder encoder = new BASE64Encoder();
|
// 新版本JDK被移除,替换为Base64.Encoder
|
||||||
return encoder.encodeBuffer(Objects.requireNonNull(bytes));
|
// BASE64Encoder encoder = new BASE64Encoder();
|
||||||
|
// return encoder.encodeBuffer(Objects.requireNonNull(bytes));
|
||||||
|
Base64.Encoder encoder = Base64.getMimeEncoder();
|
||||||
|
return encoder.encodeToString(Objects.requireNonNull(bytes));
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}finally {
|
}finally {
|
||||||
|
@ -31,4 +31,25 @@ public class Similarity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 两个向量可以为任意维度,但必须保持维度相同,表示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);
|
||||||
|
}else {
|
||||||
|
throw new RuntimeException("vector length not equal");
|
||||||
|
}
|
||||||
|
return (float) distance;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>face-search</artifactId>
|
<artifactId>face-search</artifactId>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>face-search-engine</artifactId>
|
<artifactId>face-search-engine</artifactId>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>face-search</artifactId>
|
<artifactId>face-search</artifactId>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public class SwaggerConfig implements WebMvcConfigurer {
|
|||||||
return new ApiInfoBuilder()
|
return new ApiInfoBuilder()
|
||||||
.title("人脸搜索服务API")
|
.title("人脸搜索服务API")
|
||||||
.description("人脸搜索服务API")
|
.description("人脸搜索服务API")
|
||||||
.version("1.0.0")
|
.version("1.1.0")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import io.swagger.annotations.ApiOperation;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
|
||||||
@Api(tags="05、公共服务-健康检测")
|
@Api(tags="06、公共服务-健康检测")
|
||||||
@RestController("healthController")
|
@RestController("healthController")
|
||||||
@RequestMapping("/common/health")
|
@RequestMapping("/common/health")
|
||||||
public class HealthController {
|
public class HealthController {
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.visual.face.search.server.controller.server.api;
|
||||||
|
|
||||||
|
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.response.FaceCompareRepVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人脸1:1比对
|
||||||
|
*/
|
||||||
|
public interface FaceCompareControllerApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人脸比对1:1接口
|
||||||
|
* @param compareReq
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ResponseInfo<FaceCompareRepVo> faceCompare(FaceCompareReqVo compareReq);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
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.domain.common.ResponseInfo;
|
||||||
|
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 com.visual.face.search.server.utils.ResponseBuilder;
|
||||||
|
|
||||||
|
|
||||||
|
public class FaceCompareControllerImpl extends BaseController implements FaceCompareControllerApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FaceCompareService faceCompareService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseInfo<FaceCompareRepVo> faceCompare(FaceCompareReqVo compareReq) {
|
||||||
|
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,27 @@
|
|||||||
|
package com.visual.face.search.server.controller.server.restful;
|
||||||
|
|
||||||
|
import com.visual.face.search.server.controller.server.impl.FaceCompareControllerImpl;
|
||||||
|
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.response.FaceCompareRepVo;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@Api(tags="05、人脸比对服务")
|
||||||
|
@RestController("visualFaceCompareController")
|
||||||
|
@RequestMapping("/visual/compare")
|
||||||
|
public class FaceCompareController extends FaceCompareControllerImpl {
|
||||||
|
|
||||||
|
|
||||||
|
@ApiOperation(value="1、人脸比对1:1", position = 1)
|
||||||
|
@Override
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping(value = "/do", method = RequestMethod.POST)
|
||||||
|
public ResponseInfo<FaceCompareRepVo> faceCompare(FaceCompareReqVo compareReq) {
|
||||||
|
return super.faceCompare(compareReq);
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
@RequestMapping("/visual/search")
|
@RequestMapping("/visual/search")
|
||||||
public class FaceSearchController extends FaceSearchControllerImpl {
|
public class FaceSearchController extends FaceSearchControllerImpl {
|
||||||
|
|
||||||
@ApiOperation(value="1、人脸搜索1:N", position = 1)
|
@ApiOperation(value="1、人脸搜索M:N", position = 1)
|
||||||
@Override
|
@Override
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequestMapping(value = "/do", method = RequestMethod.POST)
|
@RequestMapping(value = "/do", method = RequestMethod.POST)
|
||||||
|
@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
|
|||||||
import org.hibernate.validator.constraints.Length;
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -33,10 +34,10 @@ public class CollectVo<ExtendsVo extends CollectVo<ExtendsVo>> extends BaseVo {
|
|||||||
private Integer shardsNum;
|
private Integer shardsNum;
|
||||||
/**自定义的样本字段**/
|
/**自定义的样本字段**/
|
||||||
@ApiModelProperty(value="自定义的样本属性字段", position = 5,required = false)
|
@ApiModelProperty(value="自定义的样本属性字段", position = 5,required = false)
|
||||||
private List<FiledColumn> sampleColumns;
|
private List<FiledColumn> sampleColumns = new ArrayList<>();
|
||||||
/**自定义的人脸字段**/
|
/**自定义的人脸字段**/
|
||||||
@ApiModelProperty(value="自定义的人脸属性字段", position = 6,required = false)
|
@ApiModelProperty(value="自定义的人脸属性字段", position = 6,required = false)
|
||||||
private List<FiledColumn> faceColumns;
|
private List<FiledColumn> faceColumns = new ArrayList<>();
|
||||||
/**启用binlog同步**/
|
/**启用binlog同步**/
|
||||||
@ApiModelProperty(value="启用binlog同步。扩展字段,暂不支持该功能。", position = 7,required = false)
|
@ApiModelProperty(value="启用binlog同步。扩展字段,暂不支持该功能。", position = 7,required = false)
|
||||||
private Boolean syncBinLog;
|
private Boolean syncBinLog;
|
||||||
@ -101,7 +102,9 @@ public class CollectVo<ExtendsVo extends CollectVo<ExtendsVo>> extends BaseVo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ExtendsVo setSampleColumns(List<FiledColumn> sampleColumns) {
|
public ExtendsVo setSampleColumns(List<FiledColumn> sampleColumns) {
|
||||||
|
if(null != sampleColumns){
|
||||||
this.sampleColumns = sampleColumns;
|
this.sampleColumns = sampleColumns;
|
||||||
|
}
|
||||||
return (ExtendsVo) this;
|
return (ExtendsVo) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +113,9 @@ public class CollectVo<ExtendsVo extends CollectVo<ExtendsVo>> extends BaseVo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ExtendsVo setFaceColumns(List<FiledColumn> faceColumns) {
|
public ExtendsVo setFaceColumns(List<FiledColumn> faceColumns) {
|
||||||
|
if(null != faceColumns){
|
||||||
this.faceColumns = faceColumns;
|
this.faceColumns = faceColumns;
|
||||||
|
}
|
||||||
return (ExtendsVo) this;
|
return (ExtendsVo) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.visual.face.search.server.domain.extend;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
public class CompareFace {
|
||||||
|
|
||||||
|
/**人脸质量分数**/
|
||||||
|
@ApiModelProperty(value="A图片人脸分数:[0,100]", position = 1, required = true)
|
||||||
|
private Float faceScoreA;
|
||||||
|
/**人脸质量分数**/
|
||||||
|
@ApiModelProperty(value="B图片人脸分数:[0,100]", position = 1, required = true)
|
||||||
|
private Float faceScoreB;
|
||||||
|
|
||||||
|
/**人脸位置信息**/
|
||||||
|
@ApiModelProperty(value="A图片人脸位置信息", position = 3, required = true)
|
||||||
|
private FaceLocation locationA;
|
||||||
|
/**人脸位置信息**/
|
||||||
|
@ApiModelProperty(value="B图片人脸位置信息", position = 4, required = true)
|
||||||
|
private FaceLocation locationB;
|
||||||
|
|
||||||
|
|
||||||
|
public Float getFaceScoreA() {
|
||||||
|
return faceScoreA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaceScoreA(Float faceScoreA) {
|
||||||
|
this.faceScoreA = faceScoreA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FaceLocation getLocationA() {
|
||||||
|
return locationA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocationA(FaceLocation locationA) {
|
||||||
|
this.locationA = locationA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Float getFaceScoreB() {
|
||||||
|
return faceScoreB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaceScoreB(Float faceScoreB) {
|
||||||
|
this.faceScoreB = faceScoreB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FaceLocation getLocationB() {
|
||||||
|
return locationB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocationB(FaceLocation locationB) {
|
||||||
|
this.locationB = locationB;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.visual.face.search.server.domain.request;
|
||||||
|
|
||||||
|
import com.visual.face.search.server.domain.base.BaseVo;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
public class FaceCompareReqVo extends BaseVo {
|
||||||
|
|
||||||
|
/**图像Base64编码值**/
|
||||||
|
@NotNull(message = "imageBase64A cannot be empty")
|
||||||
|
@ApiModelProperty(value="图像A的Base64编码值", position = 1,required = true)
|
||||||
|
private String imageBase64A;
|
||||||
|
|
||||||
|
/**图像Base64编码值**/
|
||||||
|
@NotNull(message = "imageBase64B cannot be empty")
|
||||||
|
@ApiModelProperty(value="图像B的Base64编码值", position = 2,required = true)
|
||||||
|
private String imageBase64B;
|
||||||
|
|
||||||
|
/**人脸质量分数阈值**/
|
||||||
|
@Size(min = 0, max = 100, message = "faceScoreThreshold is not in the range")
|
||||||
|
@ApiModelProperty(value="人脸质量分数阈值,范围:[0,100]:默认0。当设置为0时,会默认使用当前模型的默认值,该方法为推荐使用方式", position = 3,required = false)
|
||||||
|
private Float faceScoreThreshold = 0f;
|
||||||
|
|
||||||
|
/**是否需要人脸信息**/
|
||||||
|
@ApiModelProperty(value="是否需要人脸信息,默认为:true", position = 4,required = false)
|
||||||
|
private Boolean needFaceInfo = true;
|
||||||
|
|
||||||
|
|
||||||
|
public String getImageBase64A() {
|
||||||
|
return imageBase64A;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImageBase64A(String imageBase64A) {
|
||||||
|
this.imageBase64A = imageBase64A;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImageBase64B() {
|
||||||
|
return imageBase64B;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImageBase64B(String imageBase64B) {
|
||||||
|
this.imageBase64B = imageBase64B;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Float getFaceScoreThreshold() {
|
||||||
|
return faceScoreThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaceScoreThreshold(Float faceScoreThreshold) {
|
||||||
|
if(null != faceScoreThreshold && faceScoreThreshold >= 0 && faceScoreThreshold <= 100){
|
||||||
|
this.faceScoreThreshold = faceScoreThreshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getNeedFaceInfo() {
|
||||||
|
return needFaceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNeedFaceInfo(Boolean needFaceInfo) {
|
||||||
|
if(null != needFaceInfo){
|
||||||
|
this.needFaceInfo = needFaceInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.visual.face.search.server.domain.response;
|
||||||
|
|
||||||
|
import com.visual.face.search.server.domain.base.BaseVo;
|
||||||
|
import com.visual.face.search.server.domain.extend.CompareFace;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
public class FaceCompareRepVo extends BaseVo {
|
||||||
|
/**向量的距离**/
|
||||||
|
@ApiModelProperty(value="向量欧式距离:>=0", position = 1, required = true)
|
||||||
|
private Float distance;
|
||||||
|
/**转换后的置信度**/
|
||||||
|
@ApiModelProperty(value="余弦距离转换后的置信度:[-100,100],值越大,相似度越高。", position = 2, required = true)
|
||||||
|
private Float confidence;
|
||||||
|
/**人脸信息**/
|
||||||
|
@ApiModelProperty(value="人脸信息,参数needFaceInfo=false时,值为null", position = 3, required = false)
|
||||||
|
private CompareFace faceInfo;
|
||||||
|
|
||||||
|
public Float getDistance() {
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDistance(Float distance) {
|
||||||
|
this.distance = distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Float getConfidence() {
|
||||||
|
return confidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfidence(Float confidence) {
|
||||||
|
this.confidence = confidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompareFace getFaceInfo() {
|
||||||
|
return faceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFaceInfo(CompareFace faceInfo) {
|
||||||
|
this.faceInfo = faceInfo;
|
||||||
|
}
|
||||||
|
}
|
@ -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,94 @@
|
|||||||
|
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, faceInfoB.embedding.embeds);
|
||||||
|
float confidence = (float) Math.floor(simVal * 1000000)/10000;
|
||||||
|
//欧式距离
|
||||||
|
float euclideanDistance = Similarity.euclideanDistance(faceInfoA.embedding.embeds, faceInfoB.embedding.embeds);
|
||||||
|
float distance = (float) Math.floor(euclideanDistance * 10000)/10000;
|
||||||
|
//构建返回值
|
||||||
|
FaceCompareRepVo faceCompareRep = new FaceCompareRepVo();
|
||||||
|
faceCompareRep.setDistance(distance);
|
||||||
|
faceCompareRep.setConfidence(confidence);
|
||||||
|
if(compareReq.getNeedFaceInfo()){
|
||||||
|
CompareFace compareFace = new CompareFace();
|
||||||
|
compareFace.setFaceScoreA((float) Math.floor(faceInfoA.score * 1000000)/10000);
|
||||||
|
compareFace.setFaceScoreB((float) Math.floor(faceInfoA.score * 1000000)/10000);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -123,7 +123,7 @@ public class FaceSearchServiceImpl extends BaseService implements FaceSearchServ
|
|||||||
FaceInfo.FaceBox box = faceInfos.get(i).box;
|
FaceInfo.FaceBox box = faceInfos.get(i).box;
|
||||||
FaceSearchRepVo vo = FaceSearchRepVo.build();
|
FaceSearchRepVo vo = FaceSearchRepVo.build();
|
||||||
vo.setLocation(FaceLocation.build(box.leftTop.x, box.leftTop.y, box.width(), box.height()));
|
vo.setLocation(FaceLocation.build(box.leftTop.x, box.leftTop.y, box.width(), box.height()));
|
||||||
vo.setFaceScore((float)Math.floor(faceInfos.get(i).score * 10000)/100);
|
vo.setFaceScore((float)Math.floor(faceInfos.get(i).score * 1000000)/10000);
|
||||||
List<SampleFaceVo> match = new ArrayList<>();
|
List<SampleFaceVo> match = new ArrayList<>();
|
||||||
SearchResult searchResult = result.get(i);
|
SearchResult searchResult = result.get(i);
|
||||||
List<SearchDocument> documents = searchResult.getDocuments();
|
List<SearchDocument> documents = searchResult.getDocuments();
|
||||||
@ -135,7 +135,7 @@ public class FaceSearchServiceImpl extends BaseService implements FaceSearchServ
|
|||||||
String faceVectorStr = MapUtils.getString(face, Constant.ColumnNameFaceVector);
|
String faceVectorStr = MapUtils.getString(face, Constant.ColumnNameFaceVector);
|
||||||
float[] faceVector = ValueUtil.convertVector(faceVectorStr);
|
float[] faceVector = ValueUtil.convertVector(faceVectorStr);
|
||||||
float simVal = Similarity.cosineSimilarity(faceInfos.get(i).embedding.embeds, faceVector);
|
float simVal = Similarity.cosineSimilarity(faceInfos.get(i).embedding.embeds, faceVector);
|
||||||
float confidence = (float) Math.floor(simVal * 10000)/100;
|
float confidence = (float) Math.floor(simVal * 1000000)/10000;
|
||||||
if(null != sampleId && sampleMapping.containsKey(sampleId) && confidence >= search.getConfidenceThreshold()){
|
if(null != sampleId && sampleMapping.containsKey(sampleId) && confidence >= search.getConfidenceThreshold()){
|
||||||
Map<String, Object> sample = sampleMapping.get(sampleId);
|
Map<String, Object> sample = sampleMapping.get(sampleId);
|
||||||
SampleFaceVo faceVo = SampleFaceVo.build();
|
SampleFaceVo faceVo = SampleFaceVo.build();
|
||||||
@ -143,7 +143,7 @@ public class FaceSearchServiceImpl extends BaseService implements FaceSearchServ
|
|||||||
faceVo.setFaceId(document.getFaceId());
|
faceVo.setFaceId(document.getFaceId());
|
||||||
faceVo.setFaceScore(faceScore);
|
faceVo.setFaceScore(faceScore);
|
||||||
faceVo.setConfidence(confidence);
|
faceVo.setConfidence(confidence);
|
||||||
faceVo.setDistance((float) Math.floor(document.getScore() * 100) / 100);
|
faceVo.setDistance((float) Math.floor(document.getScore() * 10000) / 10000);
|
||||||
faceVo.setFaceData(ValueUtil.getFieldKeyValues(face, ValueUtil.getFaceColumns(collection)));
|
faceVo.setFaceData(ValueUtil.getFieldKeyValues(face, ValueUtil.getFaceColumns(collection)));
|
||||||
faceVo.setSampleData(ValueUtil.getFieldKeyValues(sample, ValueUtil.getSampleColumns(collection)));
|
faceVo.setSampleData(ValueUtil.getFieldKeyValues(sample, ValueUtil.getSampleColumns(collection)));
|
||||||
match.add(faceVo);
|
match.add(faceVo);
|
||||||
|
@ -16,24 +16,27 @@ import java.util.Map;
|
|||||||
public class ValueUtil {
|
public class ValueUtil {
|
||||||
|
|
||||||
public static List<FiledColumn> getFaceColumns(Collection collection){
|
public static List<FiledColumn> getFaceColumns(Collection collection){
|
||||||
if(null != collection.getSchemaInfo() && !collection.getSchemaInfo().isEmpty()){
|
if(null != collection.getSchemaInfo() && !collection.getSchemaInfo().isEmpty()) {
|
||||||
CollectRepVo collectVo = JsonUtil.toEntity(collection.getSchemaInfo(), CollectRepVo.class);
|
CollectRepVo collectVo = JsonUtil.toEntity(collection.getSchemaInfo(), CollectRepVo.class);
|
||||||
|
if (null != collectVo && null != collectVo.getFaceColumns()) {
|
||||||
return collectVo.getFaceColumns();
|
return collectVo.getFaceColumns();
|
||||||
}else{
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
public static List<FiledColumn> getSampleColumns(Collection collection){
|
public static List<FiledColumn> getSampleColumns(Collection collection){
|
||||||
if(null != collection.getSchemaInfo() && !collection.getSchemaInfo().isEmpty()){
|
if(null != collection.getSchemaInfo() && !collection.getSchemaInfo().isEmpty()){
|
||||||
CollectRepVo collectVo = JsonUtil.toEntity(collection.getSchemaInfo(), CollectRepVo.class);
|
CollectRepVo collectVo = JsonUtil.toEntity(collection.getSchemaInfo(), CollectRepVo.class);
|
||||||
|
if (null != collectVo && null != collectVo.getSampleColumns()) {
|
||||||
return collectVo.getSampleColumns();
|
return collectVo.getSampleColumns();
|
||||||
}else{
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
public static FieldKeyValues getFieldKeyValues(Map<String, Object> map , List<FiledColumn> columns){
|
public static FieldKeyValues getFieldKeyValues(Map<String, Object> map , List<FiledColumn> columns){
|
||||||
|
columns = null != columns ? columns : new ArrayList<>();
|
||||||
Map<String, String> keyMap = new HashMap<>();
|
Map<String, String> keyMap = new HashMap<>();
|
||||||
for(FiledColumn column : columns){
|
for(FiledColumn column : columns){
|
||||||
for(String dataKey : map.keySet()){
|
for(String dataKey : map.keySet()){
|
||||||
|
@ -120,184 +120,3 @@ spring:
|
|||||||
wall:
|
wall:
|
||||||
config:
|
config:
|
||||||
multi-statement-allow: true
|
multi-statement-allow: true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 用户配置
|
|
||||||
#user:
|
|
||||||
# password:
|
|
||||||
# # 密码错误{maxRetryCount}次锁定10分钟
|
|
||||||
# maxRetryCount: 5
|
|
||||||
#
|
|
||||||
## Spring配置
|
|
||||||
#spring:
|
|
||||||
# # 模板引擎
|
|
||||||
# thymeleaf:
|
|
||||||
# mode: HTML
|
|
||||||
# encoding: utf-8
|
|
||||||
# # 禁用缓存
|
|
||||||
# cache: false
|
|
||||||
# # 资源信息
|
|
||||||
# messages:
|
|
||||||
# # 国际化资源文件路径
|
|
||||||
# basename: static/i18n/messages
|
|
||||||
# jackson:
|
|
||||||
# time-zone: GMT+8
|
|
||||||
# date-format: yyyy-MM-dd HH:mm:ss
|
|
||||||
# # 文件上传
|
|
||||||
# servlet:
|
|
||||||
# multipart:
|
|
||||||
# # 单个文件大小
|
|
||||||
# max-file-size: 10MB
|
|
||||||
# # 设置总上传的文件大小
|
|
||||||
# max-request-size: 20MB
|
|
||||||
# #数据源
|
|
||||||
# datasource:
|
|
||||||
# type: com.alibaba.druid.pool.DruidDataSource
|
|
||||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
|
||||||
# druid:
|
|
||||||
# # 主库数据源
|
|
||||||
# master:
|
|
||||||
# url: jdbc:mysql://127.0.0.1:3306/open_lab?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
|
||||||
# username: root
|
|
||||||
# password: root
|
|
||||||
# # 从库数据源
|
|
||||||
# slave:
|
|
||||||
# # 从数据源开关/默认关闭
|
|
||||||
# enabled: false
|
|
||||||
# url:
|
|
||||||
# username:
|
|
||||||
# password:
|
|
||||||
# # 初始连接数
|
|
||||||
# initialSize: 5
|
|
||||||
# # 最小连接池数量
|
|
||||||
# minIdle: 10
|
|
||||||
# # 最大连接池数量
|
|
||||||
# maxActive: 20
|
|
||||||
# # 配置获取连接等待超时的时间
|
|
||||||
# maxWait: 60000
|
|
||||||
# # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
|
||||||
# timeBetweenEvictionRunsMillis: 60000
|
|
||||||
# # 配置一个连接在池中最小生存的时间,单位是毫秒
|
|
||||||
# minEvictableIdleTimeMillis: 300000
|
|
||||||
# # 配置一个连接在池中最大生存的时间,单位是毫秒
|
|
||||||
# maxEvictableIdleTimeMillis: 900000
|
|
||||||
# # 配置检测连接是否有效
|
|
||||||
# validationQuery: SELECT 1 FROM DUAL
|
|
||||||
# testWhileIdle: true
|
|
||||||
# testOnBorrow: false
|
|
||||||
# testOnReturn: false
|
|
||||||
# webStatFilter:
|
|
||||||
# enabled: true
|
|
||||||
# statViewServlet:
|
|
||||||
# enabled: true
|
|
||||||
# # 设置白名单,不填则允许所有访问
|
|
||||||
# allow:
|
|
||||||
# url-pattern: /druid/*
|
|
||||||
# # 控制台管理用户名和密码
|
|
||||||
# login-username:
|
|
||||||
# login-password:
|
|
||||||
# filter:
|
|
||||||
# stat:
|
|
||||||
# enabled: true
|
|
||||||
# # 慢SQL记录
|
|
||||||
# log-slow-sql: true
|
|
||||||
# slow-sql-millis: 1000
|
|
||||||
# merge-sql: true
|
|
||||||
# wall:
|
|
||||||
# config:
|
|
||||||
# multi-statement-allow: true
|
|
||||||
# session:
|
|
||||||
# store-type: redis
|
|
||||||
# redis:
|
|
||||||
# database: 2
|
|
||||||
# host: 127.0.0.1
|
|
||||||
# port: 6379
|
|
||||||
# password: # 密码(默认为空)
|
|
||||||
# timeout: 6000 # 连接超时时长(毫秒)
|
|
||||||
# jedis:
|
|
||||||
# pool:
|
|
||||||
# max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
|
|
||||||
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
|
||||||
# max-idle: 10 # 连接池中的最大空闲连接
|
|
||||||
# min-idle: 5 # 连接池中的最小空闲连接
|
|
||||||
#
|
|
||||||
## MyBatis
|
|
||||||
#mybatis:
|
|
||||||
# # 搜索指定包别名
|
|
||||||
# typeAliasesPackage: com.open.lab.manager.**.domain
|
|
||||||
# # 配置mapper的扫描,找到所有的mapper.xml映射文件
|
|
||||||
# mapperLocations: classpath*:mapper/**/*Mapper.xml
|
|
||||||
# # 加载全局的配置文件
|
|
||||||
# configLocation: classpath:mybatis/mybatis-config.xml
|
|
||||||
#
|
|
||||||
## PageHelper分页插件
|
|
||||||
#pagehelper:
|
|
||||||
# helperDialect: mysql
|
|
||||||
# reasonable: true
|
|
||||||
# supportMethodsArguments: true
|
|
||||||
# params: count=countSql
|
|
||||||
#
|
|
||||||
## Shiro
|
|
||||||
#shiro:
|
|
||||||
# cache:
|
|
||||||
# storeEngine: redis
|
|
||||||
# user:
|
|
||||||
# # 登录地址
|
|
||||||
# loginUrl: /login
|
|
||||||
# # 权限认证失败地址
|
|
||||||
# unauthorizedUrl: /unauth
|
|
||||||
# # 首页地址
|
|
||||||
# indexUrl: /index
|
|
||||||
# # 验证码开关
|
|
||||||
# captchaEnabled: true
|
|
||||||
# # 验证码类型 math 数组计算 char 字符
|
|
||||||
# captchaType: math
|
|
||||||
# cookie:
|
|
||||||
# # 设置Cookie的域名 默认空,即当前访问的域名
|
|
||||||
# domain:
|
|
||||||
# # 设置cookie的有效访问路径
|
|
||||||
# path: /
|
|
||||||
# # 设置HttpOnly属性
|
|
||||||
# httpOnly: true
|
|
||||||
# # 设置Cookie的过期时间,天为单位
|
|
||||||
# maxAge: 30
|
|
||||||
# # 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)KeyGenerator keygen = KeyGenerator.getInstance("AES"); SecretKey deskey = keygen.generateKey(); System.out.println(Base64.encodeToString(deskey.getEncoded()));
|
|
||||||
# cipherKey: zSyK5Kp6PZAAjlT+eeNMlg==
|
|
||||||
# session:
|
|
||||||
# # Session超时时间,-1代表永不过期(默认30分钟)
|
|
||||||
# expireTime: 30
|
|
||||||
# # 同步session到数据库的周期(默认1分钟)
|
|
||||||
# dbSyncPeriod: 1
|
|
||||||
# # 相隔多久检查一次session的有效性,默认就是10分钟
|
|
||||||
# validationInterval: 10
|
|
||||||
# # 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制)
|
|
||||||
# maxSession: -1
|
|
||||||
# # 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
|
|
||||||
# kickoutAfter: false
|
|
||||||
#
|
|
||||||
## 防止XSS攻击
|
|
||||||
#xss:
|
|
||||||
# # 过滤开关
|
|
||||||
# enabled: true
|
|
||||||
# # 排除链接(多个用逗号分隔)
|
|
||||||
# excludes: /system/notice/*
|
|
||||||
# # 匹配链接
|
|
||||||
# urlPatterns: /system/*,/monitor/*,/tool/*
|
|
||||||
#
|
|
||||||
## Swagger配置
|
|
||||||
#swagger:
|
|
||||||
# # 是否开启swagger
|
|
||||||
# enabled: true
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<artifactId>face-search-test</artifactId>
|
<artifactId>face-search-test</artifactId>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<artifactId>face-search-client</artifactId>
|
<artifactId>face-search-client</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
2
pom.xml
2
pom.xml
@ -11,7 +11,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
<groupId>com.visual.face.search</groupId>
|
<groupId>com.visual.face.search</groupId>
|
||||||
<artifactId>face-search</artifactId>
|
<artifactId>face-search</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.1.0</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@ -62,7 +62,7 @@ services:
|
|||||||
|
|
||||||
visual-facesearch:
|
visual-facesearch:
|
||||||
container_name: face-search-server-standalone
|
container_name: face-search-server-standalone
|
||||||
image: divenswu/face-search:1.0.0
|
image: divenswu/face-search:1.1.0
|
||||||
environment:
|
environment:
|
||||||
SPRING_DATASOURCE_URL: 'jdbc:mysql://visual-mysql:3306/visual_face_search?useUnicode=true&characterEncoding=utf8'
|
SPRING_DATASOURCE_URL: 'jdbc:mysql://visual-mysql:3306/visual_face_search?useUnicode=true&characterEncoding=utf8'
|
||||||
SPRING_DATASOURCE_USERNAME: root
|
SPRING_DATASOURCE_USERNAME: root
|
||||||
|
@ -30,7 +30,7 @@ services:
|
|||||||
|
|
||||||
visual-facesearch:
|
visual-facesearch:
|
||||||
container_name: face-search-server-standalone
|
container_name: face-search-server-standalone
|
||||||
image: divenswu/face-search:1.0.0
|
image: divenswu/face-search:1.1.0
|
||||||
environment:
|
environment:
|
||||||
SPRING_DATASOURCE_URL: 'jdbc:mysql://visual-mysql:3306/visual_face_search?useUnicode=true&characterEncoding=utf8'
|
SPRING_DATASOURCE_URL: 'jdbc:mysql://visual-mysql:3306/visual_face_search?useUnicode=true&characterEncoding=utf8'
|
||||||
SPRING_DATASOURCE_USERNAME: root
|
SPRING_DATASOURCE_USERNAME: root
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version='1.0.0'
|
version='1.1.0'
|
||||||
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
|
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
|
||||||
cd ${SHELL_FOLDER}
|
cd ${SHELL_FOLDER}
|
||||||
|
|
||||||
|
1340
scripts/docs/doc-1.1.0.md
Normal file
1340
scripts/docs/doc-1.1.0.md
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user