package controllers
|
|
import (
|
"basic.com/dbapi.git"
|
"basic.com/fileServer/WeedFSClient.git"
|
"basic.com/pubsub/protomsg.git"
|
"bytes"
|
"encoding/base64"
|
"errors"
|
"fmt"
|
"github.com/gin-gonic/gin"
|
"github.com/satori/go.uuid"
|
"gocv.io/x/gocv"
|
"image"
|
"image/color"
|
"image/jpeg"
|
"io/ioutil"
|
"log"
|
"mime/multipart"
|
"net/http"
|
"path"
|
"sort"
|
"strconv"
|
"strings"
|
"sync"
|
"time"
|
"webserver/cache"
|
"webserver/extend/code"
|
"webserver/extend/config"
|
"webserver/extend/esutil"
|
"basic.com/valib/logger.git"
|
"webserver/extend/util"
|
"webserver/models"
|
"webserver/service"
|
esApi "basic.com/pubsub/esutil.git"
|
)
|
|
type FileController struct {
|
}
|
|
// weedfs 访问路径
|
//var picIp = "http://192.168.1.182:6080/"
|
var picIp = "http://"
|
|
var picUrlField = "fileUrl"
|
|
//var picUrlField = "fid"
|
/**上传方法**/
|
|
//var weedfsUri = "http://192.168.1.182:9500/submit"
|
|
// @Summary 依据图片添加底库人员
|
// @Description 依据图片添加底库返回数据人员
|
// @Accept mpfd
|
// @Produce json
|
// @Tags dbperson 底库人员
|
// @Param file formData file true "底库人员图片"
|
// @Param tableId formData string false "底库id,有id 则加入底库,无则只上传图片"
|
// @Success 200 {string} json "{"code":200, msg:"目录结构数据", success:true}"
|
// @Failure 500 {string} json "{"code":500, msg:"返回错误信息", success:false}"
|
// @Router /data/api-v/dbperson/fileupload [POST]
|
func (fc FileController) Fileupload(c *gin.Context) {
|
//得到上传的文件
|
file, header, err := c.Request.FormFile("file") //image这个是uplaodify参数定义中的 'fileObjName':'image'
|
tableId := c.Request.FormValue("tableId")
|
if err != nil {
|
c.String(http.StatusBadRequest, "Bad request")
|
return
|
}
|
//文件的名称
|
filename := header.Filename
|
fmt.Println(file, err, filename)
|
if err != nil {
|
log.Fatal(err)
|
filename = uuid.NewV4().String()
|
}
|
// fastdfs
|
{
|
//fileSuffix := path.Ext(filename)[1:] //获取文件后缀
|
//fmt.Println("文件后缀 =", fileSuffix)
|
//data, _ := ioutil.ReadAll(file)
|
// fastdfs 上传 暂废弃
|
//field := fdfsclient.UploadFileByBuffer(data, fileSuffix)
|
}
|
fileNameOnly, result, err := uploadFileReturnAddr(file, filename, tableId)
|
if err != nil {
|
if err.Error() == "NotFeatureFindError" {
|
util.ResponseFormat(c, code.NotFeatureFindError, filename)
|
} else {
|
util.ResponseFormat(c, code.ServiceInsideError, err.Error())
|
}
|
return
|
}
|
if tableId != "" { // 上传
|
if result["success"].(bool) {
|
util.ResponseFormat(c, code.Success, result["data"])
|
} else {
|
util.ResponseFormat(c, code.ServiceInsideError, result["data"])
|
}
|
} else {
|
util.ResponseFormat(c, code.Success, fileNameOnly)
|
}
|
}
|
|
|
type FaceExtract struct {
|
Url string `json:"url"`
|
FaceBytes []byte `json:"faceBytes"`
|
}
|
var faceExtractedMap = make(map[string]FaceExtract,0)
|
|
// @Summary 人脸提取
|
// @Description 人脸提取
|
// @Produce json
|
// @Tags 以图搜图
|
// @Param file formData file true "人员图片"
|
// @Success 200 {string} json "{"code":200, msg:"", data:"", success:true}"
|
// @Failure 500 {string} json "{"code":500, msg:"", data:"", success:false}"
|
// @Router /data/api-v/dbperson/faceExtract [POST]
|
func (controller FileController) FaceExtract(c *gin.Context) {
|
file, _, err := c.Request.FormFile("file") //image这个是uplaodify参数定义中的 'fileObjName':'image'
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "参数有误")
|
return
|
}
|
localConf, err2 := cache.GetServerInfo()
|
if err2 !=nil || localConf.WebPicIp == "" {
|
logger.Debug("localConfig is wrong!!!")
|
return
|
}
|
var weedfsUri = "http://"+localConf.WebPicIp+":"+strconv.Itoa(int(localConf.WebPicPort))+"/submit"
|
logger.Debug("weedfsUri:",weedfsUri)
|
resultMap :=make(map[string]interface{},0)
|
//将上传的图片交人脸检测和人脸提取,获得特征
|
fileBytes, _ := ioutil.ReadAll(file)
|
faceArr, err, pI := service.GetFaceFeaFromSdk(fileBytes, time.Second*60)
|
if err ==nil && len(faceArr) >0 {
|
//1.提取每一张人脸小图
|
urlArr := make([]string,0)
|
for _,r := range faceArr {
|
rcFace := r.Pos.RcFace
|
cutFaceImgData := util.SubImg(*pI, int(rcFace.Left), int(rcFace.Top), int(rcFace.Right), int(rcFace.Bottom))
|
weedFilePath, e := WeedFSClient.UploadFile(weedfsUri, "FaceUrl", cutFaceImgData)
|
if e == nil{
|
faceExtractedMap[weedFilePath] = FaceExtract{
|
Url:weedFilePath,
|
FaceBytes:r.Feats,
|
}
|
urlArr = append(urlArr, weedFilePath)
|
}
|
}
|
//2.大图画框,标识人脸位置
|
drawedB, _ := drawPolygonOnImg(pI, &faceArr)
|
|
originFilePath, _ := WeedFSClient.UploadFile(weedfsUri, "FaceUrl", *drawedB)
|
resultMap["uploadImage"] = originFilePath
|
resultMap["smImage"] = urlArr
|
util.ResponseFormat(c,code.Success, resultMap)
|
} else {
|
util.ResponseFormat(c,code.ComError,"未提取到人脸")
|
}
|
}
|
|
func drawPolygonOnImg(i *protomsg.Image,faceArr *[]*protomsg.ResultFaceDetect) (*[]byte,error) {
|
rook, _ := gocv.NewMatFromBytes(int(i.Height), int(i.Width), gocv.MatTypeCV8UC3, i.Data)
|
defer rook.Close()
|
//yellow := color.RGBA{255, 255, 0, 0}
|
red := color.RGBA{255, 0, 0, 0}
|
for _,faceResult := range *faceArr {
|
left := int(faceResult.Pos.RcFace.Left)
|
top := int(faceResult.Pos.RcFace.Top)
|
right := int(faceResult.Pos.RcFace.Right)
|
bottom := int(faceResult.Pos.RcFace.Bottom)
|
gocv.Rectangle(&rook, image.Rect(left,top,right,bottom), red, 1)
|
}
|
fData,err := gocv.IMEncode(".jpg", rook)
|
return &fData,err
|
}
|
|
type CompareResult struct {
|
Id string `json:"id"`
|
CompareScore float32 `json:"compareScore"`
|
CameraId string `json:"cameraId"`
|
CameraAddr string `json:"cameraAddr"`
|
PicDate string `json:"picDate"`
|
Content string `json:"content"`
|
IsAlarm int `json:"isAlarm"`
|
PicMaxUrl string `json:"picMaxUrl"`
|
PicSmUrl []string `json:"picSmUrl"`
|
Sex string `json:"sex"`
|
AgeDescription string `json:"ageDescription"`
|
Race string `json:"race"`
|
TaskId string `json:"taskId"`
|
TaskName string `json:"taskName"`
|
BaseInfo []DbPersonVo `json:"baseInfo"`
|
VideoUrl string `json:"videoUrl"`
|
SdkName string `json:"sdkName"`
|
}
|
type DbPersonVo struct {
|
BwType string `json:"bwType"`
|
CompareScore float32 `json:"compareScore"`
|
IdCard string `json:"idCard"`
|
MonitorLevel string `json:"monitorLevel"`
|
PersonId string `json:"personId"`
|
PersonName string `json:"personName"`
|
PersonPicUrl string `json:"personPicUrl"`
|
PhoneNum string `json:"phoneNum"`
|
Sex string `json:"sex"`
|
TableId string `json:"tableId"`
|
TableName string `json:"tableName"`
|
Enable int32 `json:"enable"`
|
}
|
|
type ScoreIndex struct {
|
CompareScore float32
|
Index int
|
}
|
|
//填充向前端返回的数据
|
func FillDataToCompareResult(compResult *protomsg.SdkCompareResult) []CompareResult {
|
|
var resultList = make([]CompareResult, len(compResult.CompareResult))
|
dbPersonM := make(map[string]ScoreIndex, 0)
|
captureM := make(map[string]ScoreIndex, 0)
|
personIds := make([]string,0)
|
captureIds := make([]string,0)
|
for idx,v :=range compResult.CompareResult{
|
if v.Tableid == service.CaptureTable {
|
captureM[v.Id] = ScoreIndex{
|
Index: idx,
|
CompareScore: v.CompareScore,
|
}
|
captureIds = append(captureIds,v.Id)
|
} else {
|
dbPersonM[v.Id] = ScoreIndex{
|
Index: idx,
|
CompareScore: v.CompareScore,
|
}
|
personIds = append(personIds,v.Id)
|
}
|
}
|
logger.Debug("comp len(personIds):", len(personIds))
|
logger.Debug("comp len(captureIds):", len(captureIds))
|
|
var dbpersons []protomsg.Dbperson
|
if len(personIds) >0 {
|
var dbpApi dbapi.DbPersonApi
|
dbpersons, _ = dbpApi.Dbpersoninfosbyid(personIds)
|
}
|
|
if len(dbpersons) >0 {
|
var dtApi dbapi.DbTableApi
|
for _,p :=range dbpersons {
|
var dbP = DbPersonVo {
|
PersonId: p.Id,
|
IdCard: p.IdCard,
|
CompareScore: util.ParseScore(dbPersonM[p.Id].CompareScore),
|
MonitorLevel: p.MonitorLevel,
|
PersonName: p.PersonName,
|
PersonPicUrl: p.PersonPicUrl,
|
PhoneNum: p.PhoneNum,
|
Sex: p.Sex,
|
TableId: p.TableId,
|
Enable: p.Enable,
|
}
|
dbTableInfos, _ := dtApi.DbtablesById([]string{ p.TableId })
|
if dbTableInfos !=nil{
|
dbP.BwType = dbTableInfos[0].BwType
|
dbP.TableName = dbTableInfos[0].TableName
|
}
|
|
resultList[dbPersonM[p.Id].Index] = CompareResult{
|
BaseInfo:[]DbPersonVo{ dbP },
|
}
|
}
|
}
|
if len(captureIds) >0 {
|
localConf, err2 := cache.GetServerInfo()
|
if err2 !=nil || localConf.AlarmIp == "" || localConf.ServerId == "" {
|
logger.Debug("localConfig is wrong!!!")
|
return nil
|
}
|
logger.Debug("captureIds:",strings.Join(captureIds,","))
|
videopersons, _ := esApi.Videopersonsinfosbyid(captureIds, config.EsInfo.EsIndex.VideoPersons.IndexName, localConf.AlarmIp, strconv.Itoa(int(localConf.AlarmPort)))
|
logger.Debug("comp videoPersons.len:",len(videopersons))
|
for _,vp :=range videopersons {
|
isAlarmInt, _ := strconv.Atoi(vp.IsAlarm)
|
bi := make([]DbPersonVo,0)
|
for _,p :=range vp.BaseInfo {
|
bi = append(bi, DbPersonVo{
|
PersonId: p.PersonId,
|
IdCard: p.IdCard,
|
CompareScore: util.ParseScore(p.CompareScore),
|
MonitorLevel: parseMonitorLevel(p.MonitorLevel),
|
PersonName: p.PersonName,
|
PersonPicUrl: p.PersonPicUrl,
|
PhoneNum: p.PhoneNum,
|
Sex: p.Sex,
|
TableId: p.TableId,
|
BwType: strconv.Itoa(int(p.BwType)),
|
TableName: p.TableName,
|
})
|
}
|
vpE := CompareResult{
|
Id: vp.Id,
|
CompareScore: util.ParseScore(captureM[vp.Id].CompareScore),
|
CameraId: vp.CameraId,
|
CameraAddr: vp.CameraAddr,
|
PicDate: vp.PicDate,
|
PicMaxUrl: vp.PicMaxUrl,
|
PicSmUrl: vp.PicSmUrl,
|
IsAlarm: isAlarmInt,
|
Sex: vp.Sex,
|
AgeDescription: vp.AgeDescription,
|
Race: vp.Race,
|
TaskName: vp.TaskName,
|
TaskId: vp.TaskId,
|
VideoUrl: vp.VideoUrl,
|
BaseInfo: bi,
|
SdkName: "人脸",
|
}
|
resultList[captureM[vp.Id].Index] = vpE
|
}
|
}
|
return resultList
|
}
|
|
func parseMonitorLevel(level string) string {
|
if level == "1" {
|
return "一级"
|
}
|
if level == "2" {
|
return "二级"
|
}
|
if level == "3" {
|
return "三级"
|
}
|
return level
|
}
|
|
func GetFeaFromOneFaceImg(fileBytes []byte) (faceB []byte,oriImg string,smImgs []string, err error){
|
localConf, err2 := cache.GetServerInfo()
|
if err2 !=nil || localConf.WebPicIp == "" {
|
logger.Debug("localConfig is wrong!!!")
|
return nil,"",nil,errors.New("localConf err")
|
}
|
var weedfsUri = "http://"+localConf.WebPicIp+":"+strconv.Itoa(int(localConf.WebPicPort))+"/submit"
|
logger.Debug("weedfsUri:",weedfsUri)
|
faceArr, err, pI := service.GetFaceFeaFromSdk(fileBytes, time.Second*60)
|
if err ==nil && len(faceArr) ==1 {
|
rcFace := faceArr[0].Pos.RcFace
|
cutFaceImgData := util.SubImg(*pI, int(rcFace.Left), int(rcFace.Top), int(rcFace.Right), int(rcFace.Bottom))
|
weedFilePath, e := WeedFSClient.UploadFile(weedfsUri, "FaceUrl", cutFaceImgData)
|
if e == nil{
|
faceExtractedMap[weedFilePath] = FaceExtract{
|
Url:weedFilePath,
|
FaceBytes:faceArr[0].Feats,
|
}
|
smImgs = append(smImgs, weedFilePath)
|
}
|
//2.大图画框,标识人脸位置
|
drawedB, _ := drawPolygonOnImg(pI, &faceArr)
|
|
originFilePath, _ := WeedFSClient.UploadFile(weedfsUri, "FaceUrl", *drawedB)
|
return faceArr[0].Feats,originFilePath,smImgs,nil
|
} else {
|
return nil,"",nil,errors.New("no face")
|
}
|
}
|
|
// @Summary 以图搜图
|
// @Description 以图搜图
|
// @Accept json
|
// @Produce json
|
// @Tags 以图搜图
|
// @Param condition body models.EsSearch true "搜索参数"
|
// @Success 200 {string} json "{"code":200, msg:"", data:"", success:true}"
|
// @Failure 500 {string} json "{"code":500, msg:"", data:"", success:false}"
|
// @Router /data/api-v/dbperson/searchByPhoto [POST]
|
func (fc FileController) SearchByPhoto(c *gin.Context) {
|
var searchBody models.EsSearch
|
err := c.BindJSON(&searchBody)
|
if err !=nil{
|
util.ResponseFormat(c, code.RequestParamError, "参数有误")
|
return
|
}
|
localConf, err2 := cache.GetServerInfo()
|
if err2 !=nil || localConf.AlarmIp == "" || localConf.ServerId == "" {
|
logger.Debug("localConfig is wrong!!!")
|
util.ResponseFormat(c,code.ComError,"localConf wrong")
|
return
|
}
|
var faceB []byte
|
logger.Debug("compTargetId:",searchBody.CompTargetId,",compTargetType:",searchBody.CompTargetType)
|
if searchBody.CompTargetId != "" {//做查找此人,按抓拍的人脸或者底库的人脸以图搜图
|
if searchBody.CompTargetType == 0 {//本张人脸是底库人脸
|
var dbpApi dbapi.DbPersonApi
|
dbPersons, e := dbpApi.Dbpersoninfosbyid([]string{searchBody.CompTargetId})
|
if e ==nil && dbPersons !=nil && len(dbPersons) ==1 {
|
searchBase64Fea := dbPersons[0].FaceFeature
|
if searchBase64Fea != "" {
|
decodeF, err := base64.StdEncoding.DecodeString(dbPersons[0].FaceFeature)
|
if err !=nil {
|
util.ResponseFormat(c, code.ComError, "本条底库人员特征不是base64,请检查")
|
return
|
}
|
faceB = decodeF
|
} else {
|
util.ResponseFormat(c, code.ComError, "本条底库人员特征为空,请检查")
|
return
|
}
|
} else {
|
util.ResponseFormat(c, code.ComError, "底库人员查询失败,请检查")
|
return
|
}
|
} else {
|
searchBase64Fea, err := esApi.GetVideoPersonFaceFeatureById(searchBody.CompTargetId, config.EsInfo.EsIndex.VideoPersons.IndexName, localConf.AlarmIp, strconv.Itoa(int(localConf.AlarmPort)))
|
if err !=nil {
|
util.ResponseFormat(c, code.ComError, "抓拍数据不存在,请检查")
|
return
|
}
|
|
if searchBase64Fea !=""{
|
decodeF, err := base64.StdEncoding.DecodeString(searchBase64Fea)
|
if err !=nil {
|
util.ResponseFormat(c, code.ComError, "本条抓怕特征不是base64,请检查")
|
return
|
}
|
faceB = decodeF
|
}
|
}
|
|
} else {//做以图搜图
|
if searchBody.PicUrl == "" || len(searchBody.DataBases) == 0 {
|
util.ResponseFormat(c, code.RequestParamError, "以图搜图PicUrl不能为空")
|
return
|
}
|
if face,ok := faceExtractedMap[searchBody.PicUrl];!ok{
|
util.ResponseFormat(c, code.RequestParamError, "人脸特征未检测,请重新上传图片")
|
return
|
} else {
|
faceB = face.FaceBytes
|
}
|
}
|
|
if faceB == nil {
|
util.ResponseFormat(c, code.RequestParamError, "请重新上传图片")
|
return
|
}
|
arg := protomsg.CompareArgs{
|
FaceFeature: faceB,
|
CompareThreshold: searchBody.Threshold,
|
}
|
|
var hasCompEsPerson = false
|
if searchBody.DataBases !=nil {
|
for idx,tableId :=range searchBody.DataBases {
|
if tableId == "esData" {
|
searchBody.DataBases = append(searchBody.DataBases[:idx], searchBody.DataBases[idx+1:]...)
|
hasCompEsPerson = true
|
break
|
}
|
}
|
arg.TableIds = searchBody.DataBases
|
} else {
|
arg.TableIds = []string{}
|
}
|
arg.Source = true // 标识来源是web
|
arg.AlarmLevel = searchBody.AlarmLevel
|
arg.Tasks = searchBody.Tasks
|
arg.TreeNodes = searchBody.TreeNodes
|
arg.Tabs = searchBody.Tabs
|
arg.SearchTime = searchBody.SearchTime
|
arg.InputValue = searchBody.InputValue
|
arg.Collection = searchBody.Collection
|
arg.AnalyServerId = localConf.ServerId
|
|
logger.Debug("arg.TableIds:", arg.TableIds, ",alarmLevel:",arg.AlarmLevel,",treeNodes:",arg.TreeNodes,",searchTime:",arg.SearchTime,
|
",inputValue:",arg.InputValue,",tasks:",arg.Tasks,",compThreshold:",arg.CompareThreshold)
|
timeStart := time.Now()
|
|
compareService := service.NewFaceCompareService(arg)
|
var totalData service.CompareList
|
if len(arg.TableIds) >0 {//有比对底库
|
dbPersonTargets := compareService.CompareDbPersons()
|
if dbPersonTargets !=nil {
|
totalData = append(totalData,*dbPersonTargets...)
|
}
|
}
|
if hasCompEsPerson {//有比对Es抓拍
|
esPersons := compareService.CompareVideoPersons()
|
if esPersons !=nil {
|
totalData = append(totalData, *esPersons...)
|
}
|
}
|
|
logger.Debug("comp 比对结束,用时:",time.Since(timeStart))
|
service.SetCompResultByNum(&service.CompareOnce{
|
CompareNum: compareService.CompareNum,
|
CompareData: &totalData,
|
})
|
|
m := make(map[string]interface{},3)
|
if totalData != nil && totalData.Len() > 0{
|
sort.Sort(totalData)
|
total := totalData.Len()
|
|
m["compareNum"] = compareService.CompareNum
|
m["total"] = total
|
var sCompResult protomsg.SdkCompareResult
|
if total <= searchBody.Size {
|
sCompResult.CompareResult = totalData
|
} else {
|
sCompResult.CompareResult = totalData[0:searchBody.Size]
|
}
|
resultList := FillDataToCompareResult(&sCompResult)
|
m["totalList"] = resultList
|
logger.Debug("comp 比对加排序返回用时:", time.Since(timeStart))
|
|
} else {
|
m["total"] = 0
|
m["compareNum"] = compareService.CompareNum
|
m["totalList"] = []CompareResult{}
|
}
|
util.ResponseFormat(c,code.Success,m)
|
}
|
|
func GetCompareDataTwice(co *service.CompareOnce,searchBody *models.EsSearch) map[string]interface{} {
|
m := make(map[string]interface{},0)
|
|
from := (searchBody.Page-1)*searchBody.Size
|
to := from + searchBody.Size
|
|
var hasCompEsPerson = false
|
if searchBody.DataBases !=nil {
|
for _,tableId :=range searchBody.DataBases {
|
if tableId == "esData" {
|
hasCompEsPerson = true
|
break
|
}
|
}
|
}
|
if hasCompEsPerson {//二次检索ES比对结果
|
arg := protomsg.CompareArgs{
|
CompareThreshold: searchBody.Threshold,
|
}
|
localConf, err := cache.GetServerInfo()
|
if err ==nil && localConf.AlarmIp != "" && localConf.ServerId != "" {
|
arg.Source = true // 标识来源是web
|
arg.AlarmLevel = searchBody.AlarmLevel
|
arg.Tasks = searchBody.Tasks
|
arg.TreeNodes = searchBody.TreeNodes
|
arg.Tabs = searchBody.Tabs
|
arg.SearchTime = searchBody.SearchTime
|
arg.InputValue = searchBody.InputValue
|
arg.Collection = searchBody.Collection
|
arg.AnalyServerId = localConf.ServerId
|
captureIds := esApi.GetAllLocalVideopersonsId(arg, config.EsInfo.EsIndex.VideoPersons.IndexName, localConf.AlarmIp, strconv.Itoa(int(localConf.AlarmPort)))
|
if captureIds !=nil {
|
var aResult protomsg.SdkCompareResult
|
aList := getTwiceSearchResult(co, &captureIds)
|
aTotal := aList.Len()
|
if aTotal <= to {
|
aResult.CompareResult = (*aList)[from:aTotal]
|
} else {
|
aResult.CompareResult = (*aList)[from:to]
|
}
|
out := FillDataToCompareResult(&aResult)
|
m["total"] = aTotal
|
m["compareNum"] = searchBody.CompareNum
|
m["totalList"] = out
|
return m
|
} else {
|
m["total"] = 0
|
m["compareNum"] = searchBody.CompareNum
|
m["totalList"] = []interface{}{}
|
return m
|
}
|
}
|
}
|
|
|
var sCompResult protomsg.SdkCompareResult
|
total := len(*co.CompareData)
|
if total <= to {
|
sCompResult.CompareResult = (*co.CompareData)[from:total]
|
} else {
|
sCompResult.CompareResult = (*co.CompareData)[from:to]
|
}
|
resultList := FillDataToCompareResult(&sCompResult)
|
|
|
m["total"] = total
|
m["compareNum"] = searchBody.CompareNum
|
m["totalList"] = resultList
|
|
return m
|
}
|
|
func getTwiceSearchResult(co *service.CompareOnce, captureIds *[]string) *service.CompareList{
|
m := make(map[string]string)
|
for _,capId :=range *captureIds {
|
m[capId] = capId
|
}
|
var totalData service.CompareList
|
for _,each :=range *co.CompareData {
|
if _,ok :=m[each.Id];ok{
|
totalData = append(totalData, each)
|
}
|
}
|
|
if totalData != nil && totalData.Len() > 0{
|
sort.Sort(totalData)
|
}
|
|
return &totalData
|
}
|
|
func isInArr(id string,arr []string) bool {
|
for _,v :=range arr {
|
if v == id {
|
return true
|
}
|
}
|
return false
|
}
|
|
|
// @Description 人员照片上传并获取特征值
|
// @Router /data/api-v/dbperson/fileUploadTest [POST]
|
func (controller FileController) UploadPersonTest(c *gin.Context) {
|
file, _, err := c.Request.FormFile("file") //image这个是uplaodify参数定义中的 'fileObjName':'image'
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, "参数有误")
|
return
|
}
|
localConf, err2 := cache.GetServerInfo()
|
if err2 !=nil || localConf.WebPicIp == "" {
|
logger.Debug("localConfig is wrong!!!")
|
return
|
}
|
var weedfsUri = "http://"+localConf.WebPicIp+":"+strconv.Itoa(int(localConf.WebPicPort))+"/submit"
|
|
//将上传的图片交人脸检测和人脸提取,获得特征
|
fileBytes, _ := ioutil.ReadAll(file)
|
faceArr, err, pI := service.GetFaceFeaFromSdk(fileBytes, time.Second*5)
|
if err ==nil && len(faceArr) >0 {
|
var faceBase64= ""
|
var rcFace *protomsg.Rect
|
for _,r := range faceArr {
|
rcFace = r.Pos.RcFace
|
faceBase64 = base64.StdEncoding.EncodeToString(r.Feats)//获取提取到的第一张人脸特征
|
break
|
}
|
//根据人脸坐标扣出人脸小图
|
cutFaceImgData := util.SubImg(*pI, int(rcFace.Left), int(rcFace.Top), int(rcFace.Right), int(rcFace.Bottom))
|
weedFilePath, e := WeedFSClient.UploadFile(weedfsUri, "testCutFace", cutFaceImgData)
|
if e !=nil{
|
util.ResponseFormat(c,code.ComError,"文件上传失败")
|
} else {
|
util.ResponseFormat(c,code.Success,weedFilePath + ";" + faceBase64)
|
}
|
} else {
|
util.ResponseFormat(c,code.ComError,"未提取到人脸")
|
}
|
}
|
|
/*// 对上面的编码结果进行base64解码
|
decodeBytes, err := base64.StdEncoding.DecodeString(encodeString)
|
if err != nil {
|
log.Fatalln(err)
|
}*/
|
|
func uploadFileReturnAddr(file multipart.File, filename string, tableId string) (string, map[string]interface{}, error) {
|
defer file.Close()
|
// weedfs 上传
|
fileBytes, err := ioutil.ReadAll(file)
|
if err !=nil {
|
return "",nil,err
|
}
|
|
//将上传的图片交人脸检测和人脸提取,获得特征
|
var faceBase64=""
|
faceArr, err, pI := service.GetFaceFeaFromSdk(fileBytes, time.Second*5)
|
if faceArr ==nil {
|
return "",nil,errors.New("NotFeatureFindError")
|
}
|
var rcFace *protomsg.Rect
|
if err ==nil && len(faceArr) >0 {
|
if len(faceArr) >1 {
|
return "",nil, errors.New("TooManyFaces")
|
}
|
for _,r := range faceArr {
|
//拿到人脸的坐标
|
rcFace = r.Pos.RcFace
|
|
faceBase64 = base64.StdEncoding.EncodeToString(r.Feats)//获取提取到的第一张人脸特征
|
break
|
}
|
}
|
localConf, err2 := cache.GetServerInfo()
|
if err2 !=nil || localConf.WebPicIp == "" {
|
logger.Debug("localConfig is wrong!!!")
|
return "",nil,err2
|
}
|
var weedfsUri = "http://"+localConf.WebPicIp+":"+strconv.Itoa(int(localConf.WebPicPort))+"/submit"
|
//根据人脸坐标扣出人脸小图
|
t1 := time.Now()
|
cutFaceImgData := util.SubImg(*pI, int(rcFace.Left), int(rcFace.Top), int(rcFace.Right), int(rcFace.Bottom))
|
logger.Debug("SubImg用时:", time.Since(t1))
|
t1 = time.Now()
|
weedFilePath, e := WeedFSClient.UploadFile(weedfsUri, filename, cutFaceImgData)
|
logger.Debug("上传到weedfs用时:", time.Since(t1))
|
t1 = time.Now()
|
if e != nil {
|
logger.Debug("WeedFSClient.UploadFile err:", e)
|
return "", nil, e
|
}
|
|
ext := path.Ext(filename)
|
fileNameOnly := strings.TrimSuffix(filename, ext)
|
|
dbperson := new(models.Dbtablepersons)
|
dbperson.PersonPicUrl = weedFilePath // 图片路经
|
dbperson.TableId = tableId //
|
dbperson.PersonName = fileNameOnly // 图片名
|
dbperson.Enable = 1 //默认有效
|
dbperson.FaceFeature = faceBase64 // 特征值base64 码
|
|
result := addDbPerson(dbperson)
|
logger.Debug("addDbPerson用时:", time.Since(t1))
|
return fileNameOnly, result, nil
|
|
}
|
|
/**上传方法**/
|
|
// @Summary 批量添加底库人员
|
// @Description 依据图片批量添加底库人员
|
// @Accept mpfd
|
// @Produce json
|
// @Tags dbperson 底库人员
|
// @Param files formData file[] true "多个底库人员图片"
|
// @Param tableId formData string false "底库id,有id 则加入底库,无则只上传图片"
|
// @Success 200 {string} json "{"code":200, msg:"目录结构数据", success:true,data:{}}"
|
// @Failure 500 {string} json "{"code":500, msg:"返回错误信息", success:false,data:null}"
|
// @Router /data/api-v/dbperson/moreFileUpload [POST]
|
func (fc FileController) MoreFileUpload(c *gin.Context) {
|
//得到上传的文件
|
//image这个是uplaodify参数定义中的 'fileObjName':'image'
|
form, err := c.MultipartForm()
|
tableId := c.Request.FormValue("tableId")
|
fileHeaders := form.File["files"]
|
if err != nil {
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
extNames := make([]string, 0)
|
addResult := make(map[string]interface{}, 0)
|
successList := make([]string, 0)
|
failList := make([]string,0)
|
tAllStart := time.Now()
|
var wg sync.WaitGroup
|
var lock sync.Mutex
|
for _, head := range fileHeaders {
|
wg.Add(1)
|
go func(head *multipart.FileHeader,tableId string) {
|
defer wg.Done()
|
tIStart := time.Now()
|
filename := head.Filename
|
fileExt := path.Ext(filename)
|
fileExt = strings.ToLower(fileExt)
|
if fileExt !=".jpg" && fileExt != ".jpeg" && fileExt != ".png" {
|
lock.Lock()
|
failList = append(failList, filename)
|
lock.Unlock()
|
return
|
}
|
file, err := head.Open()
|
if err != nil {
|
lock.Lock()
|
failList = append(failList, filename)
|
lock.Unlock()
|
return
|
}
|
field, _, err1 := uploadFileReturnAddr(file, filename, tableId)
|
lock.Lock()
|
if err1 != nil || field == "" {
|
failList = append(failList, filename)
|
} else {
|
successList = append(successList, filename)
|
}
|
lock.Unlock()
|
logger.Debug(filename,"切图用时:",time.Since(tIStart))
|
}(head, tableId)
|
wg.Wait()
|
}
|
logger.Debug("切",len(fileHeaders),"张人脸用时:", time.Since(tAllStart))
|
addResult["successList"] = successList
|
addResult["failList"] = failList
|
addResult["fields"] = extNames
|
|
//if len(successList)>0 {
|
util.ResponseFormat(c, code.DbPersonUploadSuccess, addResult)
|
//} else {
|
// util.ResponseFormat(c, code.DbPersonUploadFail, addResult)
|
//}
|
}
|
|
type EsPersonSave struct {
|
FaceFeature string `json:"faceFeature"`
|
TableId string `json:"tableId"`
|
Id string `json:"id"`
|
PersonPicUrl string `json:"personPicUrl"`
|
IdCard string `json:"idCard"`
|
}
|
|
// @Summary 上传图片 并切图
|
// @Description 上传图片 并切图
|
// @Accept mpfd
|
// @Produce json
|
// @Tags dbperson 底库人员
|
// @Param file formData file true "底库人员图片"
|
// @Param tableId formData string false "底库id,有id 则加入底库,无则只上传图片"
|
// @Success 200 {string} json "{"code":200, msg:"目录结构数据", success:true, data:""}"
|
// @Failure 500 {string} json "{"code":500, msg:"返回错误信息", success:false, data:""}"
|
// @Router /data/api-v/es/ImageUploadReturnPics [POST]
|
func (fc FileController) ImageUploadReturnPics(c *gin.Context) {
|
//得到上传的文件
|
file, header, err := c.Request.FormFile("file") //image这个是uplaodify参数定义中的 'fileObjName':'image'
|
if err != nil {
|
log.Fatal(err)
|
util.ResponseFormat(c, code.RequestParamError, err.Error())
|
return
|
}
|
//文件的名称
|
filename := header.Filename
|
defer file.Close()
|
field := ""
|
|
// weedfs 上传
|
uploadData := make([]byte, header.Size)
|
i, err2 := file.ReadAt(uploadData, 0)
|
if err2 != nil {
|
fmt.Println("上传返回i:", i)
|
util.ResponseFormat(c, code.UploadFileError, err2.Error())
|
return
|
}
|
localConf, err2 := cache.GetServerInfo()
|
if err2 !=nil || localConf.WebPicIp == "" {
|
logger.Debug("localConfig is wrong!!!")
|
return
|
}
|
var weedfsUri = "http://"+localConf.WebPicIp+":"+strconv.Itoa(int(localConf.WebPicPort))+"/submit"
|
{
|
uri := weedfsUri
|
fileInfo, e := esutil.PostFormBufferData(uri, filename, "file", uploadData)
|
if e != nil {
|
fmt.Println(e.Error())
|
util.ResponseFormat(c, code.UploadFileError, e.Error())
|
return // 上传失败
|
} else {
|
field = fileInfo[picUrlField].(string) // 文件路径
|
}
|
}
|
// fileInfo["point"] = v.RcFace // 返回特征值
|
// fileInfo["feature"] = feat
|
//features := gorun.GetSimpleFaceDetect(picIp + "/" + field) // 特征值 只在linux 下
|
|
result := make(map[string]interface{}, 0)
|
result["uploadImage"] = picIp + field
|
smUrl := make([]string, 0)
|
//for _, feature := range features { // linux
|
// 获取图片
|
//point := feature["point"].(gosdk.CRECT) // linux
|
buffer := bytes.NewBuffer(uploadData)
|
m, _, _ := image.Decode(buffer) // 图片文件解码
|
rgbImg := m.(*image.YCbCr)
|
//subImg := rgbImg.SubImage(image.Rect(int(point.Left),int(point.Bottom),int(point.Right),int(point.Top))).(*image.YCbCr) //图片裁剪x0 y0 x1 y1 linux
|
subImg := rgbImg.SubImage(image.Rect(30, 130, 170, 20)).(*image.YCbCr) //图片裁剪x0 y0 x1 y1 windows
|
emptyBuff := bytes.NewBuffer(nil) //开辟一个新的空buff
|
jpeg.Encode(emptyBuff, subImg, nil) //img写入到buff
|
bytes := emptyBuff.Bytes()
|
fileInfo, e := esutil.PostFormBufferData(weedfsUri, filename, "file", bytes)
|
if e != nil {
|
fmt.Println(e.Error())
|
util.ResponseFormat(c, code.UploadFileError, e.Error())
|
return // 上传失败
|
smUrl = append(smUrl, "一组获取失败")
|
} else {
|
field = fileInfo[picUrlField].(string) // 文件路径
|
smUrl = append(smUrl, picIp+field)
|
}
|
//} // linux
|
result["smImage"] = smUrl
|
util.ResponseFormat(c, code.Success, result)
|
}
|
|
/**下载方法**/
|
func Filedown(c *gin.Context) {
|
//暂时没有提供方法
|
|
}
|