!1 合并dev1.1.0分支

Merge pull request !1 from divenswu/dev-1.1.0
This commit is contained in:
divenswu 2022-03-18 06:07:40 +00:00 committed by Gitee
commit ba33c764eb
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
29 changed files with 1756 additions and 218 deletions

View File

@ -32,9 +32,15 @@
    2、[PCN](https://github.com/Rock-100/FaceKit/tree/master/PCN)
### 版本1.1.0更新
* 1、修复已知BUG
* 2、添加人脸比对11接口详见文档[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
@ -45,12 +51,12 @@
<dependency>
<groupId>com.visual.face.search</groupId>
<artifactId>face-search-client</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
</dependency>
```
* 其他语言依赖
&ensp; &ensp;使用restful接口[文档-1.0.0](https://gitee.com/open-visual/face-search/blob/master/scripts/docs/doc-1.0.0.md)
&ensp; &ensp;使用restful接口[文档-1.1.0](https://gitee.com/open-visual/face-search/blob/dev-1.1.0/scripts/docs/doc-1.1.0.md)
### 项目部署

View File

@ -7,7 +7,7 @@
<artifactId>face-search-client</artifactId>
<groupId>com.visual.face.search</groupId>
<version>1.0.0</version>
<version>1.1.0</version>
<properties>
<java.version>1.8</java.version>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>face-search</artifactId>
<groupId>com.visual.face.search</groupId>
<version>1.0.0</version>
<version>1.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>face-search-core</artifactId>

View File

@ -9,7 +9,6 @@ import org.opencv.dnn.Dnn;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import sun.misc.BASE64Decoder;
import javax.imageio.ImageIO;
import java.awt.*;
@ -20,6 +19,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Base64;
/**
* 图片加载工具
@ -66,8 +66,11 @@ public class ImageMat implements Serializable {
public static ImageMat fromBase64(String base64Str){
InputStream inputStream = null;
try {
BASE64Decoder decoder = new BASE64Decoder();
byte[] data = decoder.decodeBuffer(base64Str);
// 新版本JDK被移除替换为Base64.Decoder
// BASE64Decoder decoder = new BASE64Decoder();
// byte[] data = decoder.decodeBuffer(base64Str);
Base64.Decoder decoder = Base64.getMimeDecoder();
byte[] data = decoder.decode(base64Str);
inputStream = new ByteArrayInputStream(data);
return fromInputStream(inputStream);
}catch (Exception e){

View File

@ -1,10 +1,10 @@
package com.visual.face.search.core.utils;
import org.opencv.core.Mat;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.Objects;
public class MatUtil {
@ -42,8 +42,11 @@ public class MatUtil {
byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(matToBufferedImage(mat), "jpg", byteArrayOutputStream);
byte[] bytes = byteArrayOutputStream.toByteArray();
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encodeBuffer(Objects.requireNonNull(bytes));
// 新版本JDK被移除替换为Base64.Encoder
// BASE64Encoder encoder = new BASE64Encoder();
// return encoder.encodeBuffer(Objects.requireNonNull(bytes));
Base64.Encoder encoder = Base64.getMimeEncoder();
return encoder.encodeToString(Objects.requireNonNull(bytes));
}catch (Exception e){
throw new RuntimeException(e);
}finally {

View File

@ -29,6 +29,27 @@ public class Similarity {
}
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);
}else {
throw new RuntimeException("vector length not equal");
}
return (float) distance;
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>face-search</artifactId>
<groupId>com.visual.face.search</groupId>
<version>1.0.0</version>
<version>1.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>face-search-engine</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>face-search</artifactId>
<groupId>com.visual.face.search</groupId>
<version>1.0.0</version>
<version>1.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -38,7 +38,7 @@ public class SwaggerConfig implements WebMvcConfigurer {
return new ApiInfoBuilder()
.title("人脸搜索服务API")
.description("人脸搜索服务API")
.version("1.0.0")
.version("1.1.0")
.build();
}

View File

@ -7,7 +7,7 @@ import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@Api(tags="05、公共服务-健康检测")
@Api(tags="06、公共服务-健康检测")
@RestController("healthController")
@RequestMapping("/common/health")
public class HealthController {

View File

@ -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;
/**
* 人脸11比对
*/
public interface FaceCompareControllerApi {
/**
* 人脸比对11接口
* @param compareReq
* @return
*/
public ResponseInfo<FaceCompareRepVo> faceCompare(FaceCompareReqVo compareReq);
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
@RequestMapping("/visual/search")
public class FaceSearchController extends FaceSearchControllerImpl {
@ApiOperation(value="1、人脸搜索1:N", position = 1)
@ApiOperation(value="1、人脸搜索M:N", position = 1)
@Override
@ResponseBody
@RequestMapping(value = "/do", method = RequestMethod.POST)

View File

@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Min;
import java.util.ArrayList;
import java.util.List;
/***
@ -33,10 +34,10 @@ public class CollectVo<ExtendsVo extends CollectVo<ExtendsVo>> extends BaseVo {
private Integer shardsNum;
/**自定义的样本字段**/
@ApiModelProperty(value="自定义的样本属性字段", position = 5,required = false)
private List<FiledColumn> sampleColumns;
private List<FiledColumn> sampleColumns = new ArrayList<>();
/**自定义的人脸字段**/
@ApiModelProperty(value="自定义的人脸属性字段", position = 6,required = false)
private List<FiledColumn> faceColumns;
private List<FiledColumn> faceColumns = new ArrayList<>();
/**启用binlog同步**/
@ApiModelProperty(value="启用binlog同步。扩展字段暂不支持该功能。", position = 7,required = false)
private Boolean syncBinLog;
@ -101,7 +102,9 @@ public class CollectVo<ExtendsVo extends CollectVo<ExtendsVo>> extends BaseVo {
}
public ExtendsVo setSampleColumns(List<FiledColumn> sampleColumns) {
this.sampleColumns = sampleColumns;
if(null != sampleColumns){
this.sampleColumns = sampleColumns;
}
return (ExtendsVo) this;
}
@ -110,7 +113,9 @@ public class CollectVo<ExtendsVo extends CollectVo<ExtendsVo>> extends BaseVo {
}
public ExtendsVo setFaceColumns(List<FiledColumn> faceColumns) {
this.faceColumns = faceColumns;
if(null != faceColumns){
this.faceColumns = faceColumns;
}
return (ExtendsVo) this;
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -123,7 +123,7 @@ public class FaceSearchServiceImpl extends BaseService implements FaceSearchServ
FaceInfo.FaceBox box = faceInfos.get(i).box;
FaceSearchRepVo vo = FaceSearchRepVo.build();
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<>();
SearchResult searchResult = result.get(i);
List<SearchDocument> documents = searchResult.getDocuments();
@ -135,7 +135,7 @@ public class FaceSearchServiceImpl extends BaseService implements FaceSearchServ
String faceVectorStr = MapUtils.getString(face, Constant.ColumnNameFaceVector);
float[] faceVector = ValueUtil.convertVector(faceVectorStr);
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()){
Map<String, Object> sample = sampleMapping.get(sampleId);
SampleFaceVo faceVo = SampleFaceVo.build();
@ -143,7 +143,7 @@ public class FaceSearchServiceImpl extends BaseService implements FaceSearchServ
faceVo.setFaceId(document.getFaceId());
faceVo.setFaceScore(faceScore);
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.setSampleData(ValueUtil.getFieldKeyValues(sample, ValueUtil.getSampleColumns(collection)));
match.add(faceVo);

View File

@ -16,24 +16,27 @@ import java.util.Map;
public class ValueUtil {
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);
return collectVo.getFaceColumns();
}else{
return new ArrayList<>();
if (null != collectVo && null != collectVo.getFaceColumns()) {
return collectVo.getFaceColumns();
}
}
return new ArrayList<>();
}
public static List<FiledColumn> getSampleColumns(Collection collection){
if(null != collection.getSchemaInfo() && !collection.getSchemaInfo().isEmpty()){
CollectRepVo collectVo = JsonUtil.toEntity(collection.getSchemaInfo(), CollectRepVo.class);
return collectVo.getSampleColumns();
}else{
return new ArrayList<>();
if (null != collectVo && null != collectVo.getSampleColumns()) {
return collectVo.getSampleColumns();
}
}
return new ArrayList<>();
}
public static FieldKeyValues getFieldKeyValues(Map<String, Object> map , List<FiledColumn> columns){
columns = null != columns ? columns : new ArrayList<>();
Map<String, String> keyMap = new HashMap<>();
for(FiledColumn column : columns){
for(String dataKey : map.keySet()){

View File

@ -120,184 +120,3 @@ spring:
wall:
config:
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

View File

@ -6,7 +6,7 @@
<artifactId>face-search-test</artifactId>
<groupId>com.visual.face.search</groupId>
<version>1.0.0</version>
<version>1.1.0</version>
<properties>
<java.version>1.8</java.version>
@ -18,7 +18,7 @@
<dependency>
<groupId>com.visual.face.search</groupId>
<artifactId>face-search-client</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
</dependency>
<dependency>

View File

@ -11,7 +11,7 @@
</parent>
<groupId>com.visual.face.search</groupId>
<artifactId>face-search</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<packaging>pom</packaging>
<modules>

View File

@ -62,7 +62,7 @@ services:
visual-facesearch:
container_name: face-search-server-standalone
image: divenswu/face-search:1.0.0
image: divenswu/face-search:1.1.0
environment:
SPRING_DATASOURCE_URL: 'jdbc:mysql://visual-mysql:3306/visual_face_search?useUnicode=true&characterEncoding=utf8'
SPRING_DATASOURCE_USERNAME: root

View File

@ -30,7 +30,7 @@ services:
visual-facesearch:
container_name: face-search-server-standalone
image: divenswu/face-search:1.0.0
image: divenswu/face-search:1.1.0
environment:
SPRING_DATASOURCE_URL: 'jdbc:mysql://visual-mysql:3306/visual_face_search?useUnicode=true&characterEncoding=utf8'
SPRING_DATASOURCE_USERNAME: root

View File

@ -1,4 +1,4 @@
version='1.0.0'
version='1.1.0'
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
cd ${SHELL_FOLDER}

1340
scripts/docs/doc-1.1.0.md Normal file

File diff suppressed because it is too large Load Diff