liuxiaolong
2019-08-22 f4e8f206a6760bdc31734dfcb1c65916b5b76311
controllers/fileController.go
@@ -1,16 +1,14 @@
package controllers
import (
   "basic.com/pubsub/protomsg.git"
   "basic.com/dbapi.git"
   "basic.com/fileServer/WeedFSClient.git"
   "basic.com/valib/deliver.git"
   "basic.com/pubsub/protomsg.git"
   "bytes"
   "encoding/base64"
   "encoding/json"
   "errors"
   "fmt"
   "github.com/gin-gonic/gin"
   "github.com/gogo/protobuf/proto"
   "github.com/satori/go.uuid"
   "image"
   "image/jpeg"
@@ -19,12 +17,15 @@
   "mime/multipart"
   "net/http"
   "path"
   "sort"
   "strconv"
   "strings"
   "sync"
   "time"
   "webserver/extend/code"
   "webserver/extend/config"
   "webserver/extend/esutil"
   "webserver/extend/logger"
   "webserver/extend/util"
   "webserver/models"
   "webserver/service"
@@ -120,11 +121,12 @@
      return
   }
   var weedfsUri = "http://"+config.WeedFs.Ip+":"+strconv.Itoa(config.WeedFs.UploadPort)+"/submit"
   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
@@ -138,74 +140,388 @@
            urlArr = append(urlArr, weedFilePath)
         }
      }
      util.ResponseFormat(c,code.Success,urlArr)
      //2.大图画框,标识人脸位置
      originFilePath, _ := WeedFSClient.UploadFile(weedfsUri, "FaceUrl", fileBytes)
      resultMap["uploadImage"] = originFilePath
      resultMap["smImage"] = urlArr
      util.ResponseFormat(c,code.Success, resultMap)
   } else {
      util.ResponseFormat(c,code.ComError,"未提取到人脸")
   }
}
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 {
      videopersons, _ := esApi.Videopersonsinfosbyid(captureIds, config.EsInfo.EsIndex.VideoPersons.IndexName, config.EsInfo.Masterip, config.EsInfo.Httpport)
      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
}
// @Summary 以图搜图
// @Description  以图搜图
// @Accept json
// @Produce json
// @Tags 以图搜图
// @Param url formData string true "url"
// @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 (controller FileController) SearchByPhoto(c *gin.Context) {
   photoUrl := c.Request.FormValue("url")
   if photoUrl == "" {
   var searchBody models.EsSearch
   err := c.BindJSON(&searchBody)
   if err !=nil{
      util.ResponseFormat(c, code.RequestParamError, "参数有误")
      return
   }
   if face,ok := faceExtractedMap[photoUrl];!ok{
      util.ResponseFormat(c, code.RequestParamError, "参数有误")
      return
   } else {
      arg := protomsg.CompareArgs{
         FaceFeature:face.FaceBytes,
         CompareThreshold:0.2,
      }
      b, err := proto.Marshal(&arg)
      if err !=nil{
         util.ResponseFormat(c, code.ComError, "请求marshal失败")
   var faceB []byte
   if searchBody.CaptureId != "" {//做查找此人,搜所有抓拍和底库
      searchBase64Fea, err := esApi.GetVideoPersonFaceFeatureById(searchBody.CaptureId, config.EsInfo.EsIndex.VideoPersons.IndexName, config.EsInfo.Masterip, config.EsInfo.Httpport)
      if err !=nil {
         util.ResponseFormat(c, code.ComError, "抓拍数据不存在,请检查")
         return
      }
      compServerList := config.CompServerInfo.Url
      fmt.Println("compServerList:", compServerList)
      resultList :=make([]protomsg.Dbperson,0)
      for _,str :=range compServerList{
         reqUrl := "tcp://"+str
         reqClient := deliver.NewClient(deliver.ReqRep, reqUrl)
         err = reqClient.Send(b)
         if err !=nil{
            continue
      if searchBase64Fea !=""{
         decodeF, err := base64.StdEncoding.DecodeString(searchBase64Fea)
         if err !=nil {
            util.ResponseFormat(c, code.ComError, "本条抓怕特征不是base64,请检查")
            return
         }
         resultB, err := reqClient.Recv()
         if err !=nil{
            continue
         }
         m :=make(map[string]float32,0)
         err = json.Unmarshal(resultB, &m)
         if err !=nil{
            continue
         }
         personIds := make([]string,len(m))
         for k,_ :=range m{
            personIds = append(personIds,k)
         }
         esServerIp := config.EsInfo.Masterip
         esServerPort := config.EsInfo.Httpport
         index := config.EsInfo.EsIndex.Dbtablepersons.IndexName
         dbpeople, e := esApi.Dbpersoninfosbyid(personIds, index, esServerIp, esServerPort)
         if e ==nil{
            resultList = append(resultList,dbpeople...)
         faceB = decodeF
      }
   } else {//做以图搜图
      if searchBody.PicUrl == "" || len(searchBody.DataBases) == 0 {
         util.ResponseFormat(c, code.RequestParamError, "参数有误")
         return
      }
      if face,ok := faceExtractedMap[searchBody.PicUrl];!ok{
         util.ResponseFormat(c, code.RequestParamError, "请重新上传图片")
         return
      } else {
         faceB = face.FaceBytes
      }
   }
   var sysSetApi dbapi.SysSetApi
   analyServerId := ""
   flag, sysconf := sysSetApi.GetServerInfo()
   if flag {
      analyServerId = sysconf.ServerId
   } else {
      util.ResponseFormat(c, code.ComError, "analyServerId为空,配置有误")
      return
   }
   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
         }
      }
      util.ResponseFormat(c,code.Success,resultList)
      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 = analyServerId
   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,arg *models.EsSearch) map[string]interface{} {
   //camIds := arg.TreeNodes
   //tabIds := arg.Tabs
   //taskIds := arg.Tasks
   //alarmLevels := arg.AlarmLevel
   //timeArr := arg.SearchTime
   //input := arg.InputValue
   //resultList := make([]CompareResult,0)
   //for _,each :=range *co.CompareData {
   //   if each.Id !=""{
   //      n :=0
   //      if len(camIds) == 0 || isInArr(each.CameraId,camIds) {
   //         n++
   //      }
   //      if len(tabIds) == 0 {
   //         n++
   //      }
   //      if len(taskIds) == 0 || isInArr(each.TaskId, taskIds) {
   //         n++
   //      }
   //      //判断报警等级
   //      if len(alarmLevels) == 0 {
   //
   //      }
   //      n++
   //      //判断时间
   //      if len(timeArr) == 0 {
   //
   //      }
   //      n++
   //      if input == ""{
   //
   //      }
   //      n++
   //      if n == 6 {
   //         resultList = append(resultList,cr)
   //      }
   //   } else {
   //      resultList = append(resultList,cr)
   //   }
   //}
   //logger.Debug("GetCompareDataTwice.data:",resultList)
   //service.SortByScore(resultList)
   from := (arg.Page-1)*arg.Size
   to := from + arg.Size
   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 := make(map[string]interface{},0)
   m["total"] = total
   m["compareNum"] = arg.CompareNum
   m["totalList"] = resultList
   //if from < len(resultList) {
   //   if to <= len(resultList) {
   //      m["totalList"] = resultList[from:to]
   //   } else {
   //      lte := len(resultList)
   //      m["totalList"] = resultList[from:lte]
   //   }
   //} else {
   //   m["totalList"] = []CompareResult{}
   //}
   return m
}
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]
@@ -249,7 +565,6 @@
func uploadFileReturnAddr(file multipart.File, filename string, tableId string) (string, map[string]interface{}, error) {
   defer file.Close()
   field := ""
   // weedfs 上传
   fileBytes, err := ioutil.ReadAll(file)
   if err !=nil {
@@ -264,6 +579,9 @@
   }
   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
@@ -274,55 +592,33 @@
   }
   var weedfsUri = "http://"+config.WeedFs.Ip+":"+strconv.Itoa(config.WeedFs.UploadPort)+"/submit"
   //根据人脸坐标扣出人脸小图
   t1 := time.Now()
   cutFaceImgData := util.SubImg(*pI, int(rcFace.Left), int(rcFace.Top), int(rcFace.Right), int(rcFace.Bottom))
   fileInfo, e := esutil.PostFormData(weedfsUri, filename, "file", cutFaceImgData)
   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 {
      fmt.Println(e.Error())
      return "", nil, e
   } else {
      field = fileInfo[picUrlField].(string) // 文件路径
   }
   if strings.Contains(field,"/"){
      idx := strings.Index(field, "/")
      field = field[idx+1:]
   }
   fmt.Println("field:",field)
   ext := path.Ext(filename)
   fileNameOnly := strings.TrimSuffix(filename, ext)
   dbperson := new(models.Dbtablepersons)
   dbperson.PersonPicUrl = field //  图片路经
   dbperson.PersonPicUrl = weedFilePath //  图片路经
   dbperson.TableId = tableId           //
   dbperson.PersonName = fileNameOnly       // 图片名
   // 演示base64编码
   dbperson.Enable = 1 //默认有效
   dbperson.FaceFeature = faceBase64 // 特征值base64 码
   result := addDbPerson(dbperson)
   logger.Debug("addDbPerson用时:", time.Since(t1))
   return fileNameOnly, result, nil
}
//func getFaceFeaFromSdk(fileBytes []byte) ([]*protomsg.ResultFaceExtCom,error,*protomsg.Image){
//   s := service.NewFaceSdkService(fileBytes)
//   i, err := s.ReadFromUploadImg()
//   if err !=nil{
//      fmt.Println("readFromUploadImg err:",err)
//      return nil,err,i
//   }
//   bc, err := service.ImgCompress(i)
//   if err !=nil {
//      fmt.Println("ImgCompress err:",err)
//      return nil,err,i
//   }
//   s.PushImgMsg(bc)
//   s.GetFaceFea()
//   if s.Result == nil{
//      return nil,errors.New("no fea"),i
//   } else {
//      return s.Result,nil,i
//   }
//}
/**上传方法**/
@@ -350,33 +646,44 @@
   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 {
      //文件的名称
      filename := head.Filename
      file, err := head.Open()
      fmt.Println(file, err, filename)
      if err != nil {
         log.Fatal(err)
      }
      field, _, err1 := uploadFileReturnAddr(file, filename, tableId)
      //extNames = append(extNames, field)
      if err1 != nil || field == "" {
         failList = append(failList, filename)
      } else {
         successList = append(successList, filename)
      }
      wg.Add(1)
      go func(head *multipart.FileHeader,tableId string) {
         defer wg.Done()
         tIStart := time.Now()
         filename := head.Filename
         file, err := head.Open()
         fmt.Println(file, err, filename)
         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
   //addResult["detail"] = details
   //fields := fdfsclient.UploadFileByBuffer100(bytess, extNames)     //  fastdfs 上传
   if len(successList)>0 {
      util.ResponseFormat(c, code.Success, addResult)
      util.ResponseFormat(c, code.DbPersonUploadSuccess, addResult)
   } else {
      util.ResponseFormat(c, code.ServiceInsideError, err.Error())
      util.ResponseFormat(c, code.DbPersonUploadFail, addResult)
   }
}