6个文件已删除
7个文件已添加
1 文件已重命名
5个文件已修改
| | |
| | | BUILD_TIME := $(shell date "+%F %T") |
| | | COMMIT_SHA1 := $(shell git rev-parse HEAD) |
| | | APP_NAME := sdkCompare |
| | | BUILD_VERSION := 1.0.0 |
| | | APP_NAME := faceCompare |
| | | BUILD_VERSION := 2.0.0 |
| | | PLATFORM := x86_64 |
| | | export LD_LIBRARY_PATH=/opt/vasystem/libs/FaceDetect |
| | | |
| | | ifeq ("$(PLATFORM)", "aarch64") |
| | | $(info CUR_PLATFORM:$(PLATFORM)) |
| | | export CGO_ENABLED=1 |
| | | export GOOS=linux |
| | | export GOARCH=arm64 |
| | | export CC=/opt/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc |
| | | export CXX=/opt/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc |
| | | export CGO_CFLAGS=--sysroot=/opt/l4t-gcc/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu |
| | | export CGO_CXXFLAGS=--sysroot=/opt/l4t-gcc/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu |
| | | export CGO_LDFLAGS=--sysroot=/opt/l4t-gcc/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu -lstdc++ |
| | | else |
| | | CUR_OS :=$(shell uname -m) |
| | | $(info CUR_PLATFORM:$(CUR_OS)) |
| | | endif |
| | | all: |
| | | go build -a -ldflags "-X 'basic.com/valib/version.git.BuildVersion=${BUILD_VERSION}' -X 'basic.com/valib/version.git.BuildTime=${BUILD_TIME}' -X 'basic.com/valib/version.git.CommitSha1=${COMMIT_SHA1}' -X 'basic.com/valib/version.git.AppName=${APP_NAME}'" -o ${APP_NAME} |
| | | go build -v -ldflags "-X 'basic.com/valib/version.git.BuildVersion=${BUILD_VERSION}' -X 'basic.com/valib/version.git.BuildTime=${BUILD_TIME}' -X 'basic.com/valib/version.git.CommitSha1=${COMMIT_SHA1}' -X 'basic.com/valib/version.git.AppName=${APP_NAME}'" -o ${APP_NAME} |
| | | clean: |
| | | rm -f ${APP_NAME} |
| | | .PHONY: |
New file |
| | |
| | | package cache |
| | | |
| | | import ( |
| | | "flag" |
| | | "sync" |
| | | "time" |
| | | |
| | | "sdkCompare/cache/shardmap" |
| | | "sdkCompare/db" |
| | | |
| | | "basic.com/pubsub/protomsg.git" |
| | | "basic.com/valib/logger.git" |
| | | ) |
| | | |
| | | var querynum = flag.Int("querynum", 3000, "the query number from database") |
| | | var threadnum = flag.Int("threadnum", 32, "the number of thread to deal data.") |
| | | |
| | | var ( |
| | | Unfiled = "unfiled" |
| | | PRE_DBTABLE = "dbTable_" |
| | | ) |
| | | |
| | | type CmapItem struct { |
| | | sync.Mutex |
| | | Area map[string]*shardmap.ShardMap |
| | | } |
| | | |
| | | var CacheMap *CmapItem |
| | | var doOnce sync.Once |
| | | |
| | | func ReInitDbTablePersonsCache() { |
| | | CacheMap.Lock() |
| | | defer CacheMap.Unlock() |
| | | if CacheMap == nil { |
| | | CacheMap = &CmapItem{ |
| | | Area: make(map[string]*shardmap.ShardMap), |
| | | } |
| | | } |
| | | for tableId, _ := range CacheMap.Area { |
| | | delete(CacheMap.Area, tableId) |
| | | } |
| | | |
| | | initDbTablePersonsCache() |
| | | } |
| | | |
| | | func InitDbTablePersons() { |
| | | doOnce.Do(func() { |
| | | flag.Parse() |
| | | |
| | | CacheMap = &CmapItem{ |
| | | Area: make(map[string]*shardmap.ShardMap), |
| | | } |
| | | |
| | | // 初始化未分类, 没有小区id的档案 |
| | | CacheMap.Area[Unfiled] = shardmap.New(uint8(*threadnum)) |
| | | }) |
| | | |
| | | initDbTablePersonsCache() |
| | | } |
| | | |
| | | func initDbTablePersonsCache() { |
| | | // 缓存底库中的全部人员信息 |
| | | var dbpApi db.DbPersons |
| | | total, e := dbpApi.GetPersonTotal("") |
| | | |
| | | var psApi db.PersonStatus |
| | | accessAreas, _ := psApi.GetPersonAccessedAreas() |
| | | |
| | | logger.Debugf("所有底库共有%d条记录", total) |
| | | if e == nil && total > 0 { |
| | | queryEachNum := *querynum |
| | | qn := int(total) / *threadnum |
| | | if *querynum < qn { |
| | | queryEachNum = qn |
| | | } |
| | | queryT := int(total) / queryEachNum |
| | | if int(total)%queryEachNum > 0 { |
| | | queryT++ |
| | | } |
| | | temptime := time.Now() |
| | | var wg sync.WaitGroup |
| | | |
| | | for i := 0; i < queryT; i++ { |
| | | j := i * queryEachNum |
| | | wg.Add(1) |
| | | go func(qs int) { |
| | | defer wg.Done() |
| | | dbPersons, err := dbpApi.GetPersonsCompareCacheBase(j, queryEachNum) |
| | | if err != nil { |
| | | logger.Error(err) |
| | | return |
| | | } |
| | | logger.Debugf("获取%d条人员信息", len(dbPersons)) |
| | | CacheMap.Lock() |
| | | |
| | | areaId := "" |
| | | for _, value := range dbPersons { |
| | | areaId = value.AreaId |
| | | // 没有小区id的人员 |
| | | if areaId == "" { |
| | | CacheMap.Area[Unfiled].Set(value.Id, value) |
| | | CacheMap.Area[Unfiled].Settime() |
| | | continue |
| | | } |
| | | |
| | | for _, areaId := range accessAreas[value.Id] { |
| | | if _, ok := CacheMap.Area[areaId]; !ok { |
| | | CacheMap.Area[areaId] = shardmap.New(uint8(*threadnum)) |
| | | } |
| | | |
| | | CacheMap.Area[areaId].Set(value.Id, value) |
| | | CacheMap.Area[areaId].Settime() |
| | | } |
| | | } |
| | | |
| | | CacheMap.Unlock() |
| | | |
| | | }(j) |
| | | } |
| | | wg.Wait() |
| | | logger.Debug("底库人员缓存完成用时:", time.Since(temptime)) |
| | | } |
| | | } |
| | | |
| | | // UpdateDbPersonsCacheById 更新缓存中的全部人员信息 |
| | | func UpdateDbPersonsCacheById(id string) { |
| | | var dbpApi db.DbPersons |
| | | info, err := dbpApi.GetPersonsCompareCacheById(id) |
| | | if err != nil { |
| | | logger.Error(err) |
| | | return |
| | | } |
| | | if info.Tableid != "" { |
| | | CacheMap.Lock() |
| | | defer CacheMap.Unlock() |
| | | if _, ok := CacheMap.Area[info.Tableid]; !ok { |
| | | CacheMap.Area[info.Tableid] = shardmap.New(uint8(*threadnum)) |
| | | } |
| | | CacheMap.Area[info.Tableid].Set(info.Id, info) |
| | | CacheMap.Area[info.Tableid].Settime() |
| | | } |
| | | } |
| | | |
| | | func RealTimeAddPersonInfoToCache(tableId string, id string, faceFeature string, enable int32, carNo string) { |
| | | CacheMap.Lock() |
| | | defer CacheMap.Unlock() |
| | | if _, ok := CacheMap.Area[tableId]; !ok { |
| | | CacheMap.Area[tableId] = shardmap.New(uint8(*threadnum)) |
| | | } |
| | | var ei = protomsg.Esinfo{ |
| | | Id: id, |
| | | Tableid: tableId, |
| | | FaceFeature: faceFeature, |
| | | Enable: enable, |
| | | CarNo: carNo, |
| | | } |
| | | CacheMap.Area[tableId].Set(id, &ei) |
| | | logger.Debug("id:", id, ",tableId:", ",len(faceFeature):", len(faceFeature), ",tableId:", tableId, ",enable:", enable) |
| | | } |
| | | |
| | | func RealTimeDelPersonFromCache(tableId string, id string) { |
| | | logger.Debug("DelPersonFromCache,tableId:", tableId, ",id:", id) |
| | | CacheMap.Lock() |
| | | defer CacheMap.Unlock() |
| | | if _, ok := CacheMap.Area[tableId]; ok { |
| | | CacheMap.Area[tableId].Del(id) |
| | | logger.Debug("DelPerson ok success") |
| | | } else { |
| | | logger.Error("tableId:", tableId, " not exist") |
| | | } |
| | | } |
| | | |
| | | func RealTimeDelTable(tableId string) { |
| | | logger.Debug("RealTimeDelTable tableId:", tableId) |
| | | CacheMap.Lock() |
| | | defer CacheMap.Unlock() |
| | | |
| | | if dtM, ok := CacheMap.Area[PRE_DBTABLE]; ok { |
| | | dtM.Del(tableId) |
| | | } |
| | | if _, ok := CacheMap.Area[tableId]; ok { |
| | | delete(CacheMap.Area, tableId) |
| | | } |
| | | } |
| | | |
| | | // 使底库生效,将底库中的所有生效状态的人特征添加到缓存 |
| | | func RealTimeUpdateTable(tableId string, enable int32) { |
| | | logger.Debug("RealTimeUpdateTable tableId:", tableId, ",enable:", enable) |
| | | CacheMap.Lock() |
| | | defer CacheMap.Unlock() |
| | | |
| | | if _, ok := CacheMap.Area[PRE_DBTABLE]; !ok { |
| | | CacheMap.Area[PRE_DBTABLE] = shardmap.New(uint8(*threadnum)) |
| | | } |
| | | CacheMap.Area[PRE_DBTABLE].Set(tableId, enable == 1) |
| | | } |
| | | |
| | | func UpdateCache(changeMsg *protomsg.EsPersonCacheChange) { |
| | | if changeMsg.Type == protomsg.EsCacheChanged_T_DbTable { |
| | | if changeMsg.Action == protomsg.DbAction_Insert || changeMsg.Action == protomsg.DbAction_Update { |
| | | RealTimeUpdateTable(changeMsg.TableId[0], changeMsg.Enable) |
| | | } else if changeMsg.Action == protomsg.DbAction_Delete { |
| | | RealTimeDelTable(changeMsg.TableId[0]) |
| | | } |
| | | } else if changeMsg.Type == protomsg.EsCacheChanged_T_DbTablePerson { |
| | | if changeMsg.Action == protomsg.DbAction_Insert || changeMsg.Action == protomsg.DbAction_Update { |
| | | RealTimeAddPersonInfoToCache(changeMsg.TableId[0], changeMsg.PersonId, changeMsg.Feature, changeMsg.Enable, changeMsg.CarNo) |
| | | } else if changeMsg.Action == protomsg.DbAction_Delete { |
| | | RealTimeDelPersonFromCache(changeMsg.TableId[0], changeMsg.PersonId) |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | import ( |
| | | "basic.com/pubsub/protomsg.git" |
| | | "sdkCompare/db" |
| | | "sync" |
| | | //"encoding/json" |
| | | //"fmt" |
| | |
| | | value interface{} |
| | | } |
| | | |
| | | func (s *ShardMap) Walk(wf wfOp, sourceFea []byte, baseScore float32, isWebComp bool, target string) (targets []*protomsg.SdkCompareEach) { |
| | | func (s *ShardMap) Walk(wf wfOp, sourceFea []byte, baseScore float32) (targets []*protomsg.SdkCompareEach) { |
| | | var wg sync.WaitGroup |
| | | var lock sync.Mutex |
| | | for _, si := range s.shards { |
| | |
| | | |
| | | wg.Add(1) |
| | | |
| | | go func(st *shardItem, fw wfOp, sf []byte, baseSec float32, isWeb bool) { |
| | | go func(st *shardItem, fw wfOp, sf []byte, baseSec float32) { |
| | | defer wg.Done() |
| | | for _, feature := range st.data { |
| | | if eif, ok := feature.(*protomsg.Esinfo); ok { |
| | | if !isWeb { //不会比对抓拍库,只比对有效的人 |
| | | if eif.Enable == 1 { |
| | | score := float32(0) |
| | | if target == "car" { |
| | | if eif.CarNo != "" { |
| | | score = strComp(sf, eif.CarNo) |
| | | } else { |
| | | continue |
| | | } |
| | | } else { |
| | | score = fw(sf, eif.FaceFeature) |
| | | } |
| | | if score > 0 && score >= baseScore { |
| | | lock.Lock() |
| | | targets = append(targets, &protomsg.SdkCompareEach{ |
| | | Id: eif.Id, |
| | | CompareScore: score, |
| | | Tableid: eif.Tableid, |
| | | }) |
| | | lock.Unlock() |
| | | } |
| | | } |
| | | } else { //来源是web,会比对抓拍库,不管是否有效都需要比对 |
| | | score := float32(0) |
| | | if target == "car" { |
| | | if eif.CarNo != "" { |
| | | score = strComp(sf, eif.CarNo) |
| | | } else { |
| | | continue |
| | | } |
| | | } else { |
| | | score = fw(sf, eif.FaceFeature) |
| | | } |
| | | if score > 0 && score >= baseScore { |
| | | lock.Lock() |
| | | targets = append(targets, &protomsg.SdkCompareEach{ |
| | | Id: eif.Id, |
| | | CompareScore: score, |
| | | Tableid: eif.Tableid, |
| | | }) |
| | | lock.Unlock() |
| | | } |
| | | if eif, ok := feature.(*db.FeatureCacheBase); ok { |
| | | score := float32(0) |
| | | score = fw(sf, eif.FaceFeature) |
| | | if score > 0 && score >= baseScore { |
| | | lock.Lock() |
| | | targets = append(targets, &protomsg.SdkCompareEach{ |
| | | Id: eif.Id, |
| | | CompareScore: score, |
| | | Tableid: eif.TableId, |
| | | }) |
| | | lock.Unlock() |
| | | } |
| | | } |
| | | } |
| | | |
| | | }(&tempsi, wf, sourceFea, baseScore, isWebComp) |
| | | }(&tempsi, wf, sourceFea, baseScore) |
| | | } |
| | | |
| | | wg.Wait() |
New file |
| | |
| | | package compare |
| | | |
| | | import ( |
| | | "encoding/base64" |
| | | "fmt" |
| | | "strconv" |
| | | |
| | | "sdkCompare/cache" |
| | | |
| | | "basic.com/pubsub/protomsg.git" |
| | | "basic.com/valib/logger.git" |
| | | "github.com/golang/protobuf/proto" |
| | | ) |
| | | |
| | | const thresholdLimit = float32(30) |
| | | |
| | | func GetComparePersonBaseInfo(args protomsg.CompareArgs) []byte { |
| | | if args.FaceFeature == nil { |
| | | return nil |
| | | } |
| | | |
| | | //指定最低分 |
| | | baseScore := thresholdLimit |
| | | if args.CompareThreshold > thresholdLimit { |
| | | baseScore = args.CompareThreshold |
| | | } |
| | | |
| | | if args.IsCompareAll { |
| | | baseScore = 0 |
| | | } |
| | | |
| | | var scResult protomsg.SdkCompareResult |
| | | |
| | | var walkedArea = make(map[string]struct{}, 0) |
| | | // 优先比对传入的小区id |
| | | if args.TreeNodes != nil && len(args.TreeNodes) > 0 { |
| | | for _, id := range args.TreeNodes { |
| | | if _, ok := cache.CacheMap.Area[id]; ok { |
| | | targets := cache.CacheMap.Area[id].Walk(DoSdkCompare, args.FaceFeature, baseScore) |
| | | if len(targets) > 0 { |
| | | scResult.CompareResult = append(scResult.CompareResult, targets...) |
| | | } |
| | | |
| | | walkedArea[id] = struct{}{} |
| | | } |
| | | } |
| | | |
| | | if len(scResult.CompareResult) > 0 { |
| | | goto done |
| | | } |
| | | } |
| | | |
| | | // 比对以外的小区 |
| | | if !args.IsCompareAll && len(args.TreeNodes) > 0 { |
| | | baseScore += 20 |
| | | } |
| | | |
| | | for key, val := range cache.CacheMap.Area { |
| | | if _, ok := walkedArea[key]; ok { |
| | | continue |
| | | } |
| | | |
| | | targets := val.Walk(DoSdkCompare, args.FaceFeature, baseScore) |
| | | if len(targets) > 0 { |
| | | scResult.CompareResult = append(scResult.CompareResult, targets...) |
| | | } |
| | | } |
| | | |
| | | done: |
| | | logger.Debugf("比对结果 %d条", len(scResult.CompareResult)) |
| | | buf, err := proto.Marshal(&scResult) |
| | | if err != nil { |
| | | logger.Error("scResult Marshal error!", err) |
| | | return nil |
| | | } |
| | | |
| | | return buf |
| | | } |
| | | |
| | | func DoSdkCompare(ci []byte, co string) float32 { |
| | | co_d, err := base64.StdEncoding.DecodeString(co) |
| | | if err != nil { |
| | | logger.Error("DoSdkCompare err:", err) |
| | | return -1 |
| | | } |
| | | sec := DecCompare(ci, co_d) |
| | | //logger.Debug("比对得分为:", sec) |
| | | |
| | | sec = ParseScore(sec) |
| | | return sec |
| | | } |
| | | |
| | | func ParseScore(compareScore float32) float32 { |
| | | if compareScore <= 1 { |
| | | compareScore = compareScore * 100 |
| | | } |
| | | if compareScore == 100 { |
| | | return 100 |
| | | } |
| | | f, _ := strconv.ParseFloat(fmt.Sprintf("%2.2f", compareScore), 32) |
| | | |
| | | return float32(f) |
| | | } |
File was renamed from face/faceCompare.go |
| | |
| | | package face |
| | | package compare |
| | | |
| | | import ( |
| | | "unsafe" |
New file |
| | |
| | | database: |
| | | servePort: 4010 |
| | | mysqlAddr: 192.168.20.119 |
| | | username: root |
| | | password: c++java123 |
| | | database: faceanalysis |
| | | personTable: dbtablepersons |
| | | log: |
| | | path: ./log/ |
| | | level: -1 |
| | | maxSize: 128 |
| | | maxBackups: 30 |
| | | maxAge: 15 |
| | |
| | | package config |
| | | |
| | | import ( |
| | | "fmt" |
| | | |
| | | "basic.com/valib/logger.git" |
| | | "github.com/fsnotify/fsnotify" |
| | | "github.com/spf13/viper" |
| | | "log" |
| | | ) |
| | | |
| | | type server struct { |
| | | AnalyServerId string `mapstructure:"analyServerId"` |
| | | NetworkAdapter string `mapstructure:"networkAdapter"` |
| | | } |
| | | |
| | | var Server = &server{} |
| | | |
| | | type esinfo struct { |
| | | EsIndex esindexlist `mapstructure:"index"` |
| | | } |
| | | |
| | | type esindexlist struct { |
| | | AiOcean index `mapstructure:"aiOcean"` |
| | | } |
| | | |
| | | type index struct { |
| | | IndexName string `mapstructure:"index"` |
| | | IndexType string `mapstructure:"type"` |
| | | } |
| | | |
| | | type dbpersoncompare struct { |
| | | type database struct { |
| | | MysqlAddr string `mapstructure:"mysqlAddr"` |
| | | Username string `mapstructure:"username"` |
| | | Password string `mapstructure:"password"` |
| | |
| | | ServePort int `mapstructure:"servePort"` |
| | | } |
| | | |
| | | type espersoncompare struct { |
| | | ServePort int `mapstructure:"servePort"` |
| | | ESIP string `mapstructure:"esip"` |
| | | ESPort string `mapstructure:"esPort"` |
| | | } |
| | | |
| | | var DbPersonCompInfo = &dbpersoncompare{} |
| | | |
| | | var EsCompServerInfo = &espersoncompare{} |
| | | |
| | | var EsInfo = &esinfo{} |
| | | var DbPersonCompInfo = &database{} |
| | | |
| | | type LogConfig struct { |
| | | Path string `mapstructure:"path"` //日志存储路径 |
| | |
| | | |
| | | var LogConf = &LogConfig{} |
| | | |
| | | func Init(env string) { |
| | | func Init() error { |
| | | var err error |
| | | v := viper.New() |
| | | v.SetConfigType("yaml") |
| | | v.SetConfigName(env) |
| | | v.SetConfigName("compare") |
| | | v.AddConfigPath("./") |
| | | v.AddConfigPath("./config/") |
| | | err = v.ReadInConfig() |
| | | if err != nil { |
| | | log.Fatal("error on parsing configuration file") |
| | | fmt.Printf("error on parsing configuration file, %s, config file compare.yaml\n", err.Error()) |
| | | return err |
| | | } |
| | | |
| | | read2Conf(v) |
| | | v.WatchConfig() |
| | | v.OnConfigChange(func(in fsnotify.Event) { |
| | | read2Conf(v) |
| | | }) |
| | | |
| | | return nil |
| | | } |
| | | |
| | | func read2Conf(v *viper.Viper) { |
| | | v.UnmarshalKey("es", EsInfo) |
| | | v.UnmarshalKey("server", Server) |
| | | v.UnmarshalKey("dbpersoncompare", DbPersonCompInfo) |
| | | v.UnmarshalKey("espersoncompare", EsCompServerInfo) |
| | | v.UnmarshalKey("database", DbPersonCompInfo) |
| | | v.UnmarshalKey("log", LogConf) |
| | | |
| | | logger.SetLevel(LogConf.Level) |
| | | } |
New file |
| | |
| | | package db |
| | | |
| | | type BaseEntity struct { |
| | | Id string `gorm:"primary_key;column:id" json:"id" example:""` |
| | | CreateTime string `gorm:"column:createTime" json:"createTime,omitempty" example:""` |
| | | UpdateTime string `gorm:"column:updateTime" json:"updateTime,omitempty" example:""` |
| | | CreateBy string `gorm:"column:createBy" json:"createBy,omitempty" example:""` |
| | | IsDelete int `gorm:"column:isDelete" json:"isDelete" example:"0 未删除 1已删除"` |
| | | Enable int `gorm:"column:enable" json:"enable" example:" 1生效 0未生效"` |
| | | } |
| | | |
| | | type FeatureCacheBase struct { |
| | | Id string |
| | | AreaId string |
| | | TableId string |
| | | FaceFeature string |
| | | Enable int32 |
| | | } |
New file |
| | |
| | | package db |
| | | |
| | | import ( |
| | | "fmt" |
| | | |
| | | "sdkCompare/config" |
| | | |
| | | "basic.com/valib/logger.git" |
| | | "gorm.io/driver/mysql" |
| | | "gorm.io/gorm" |
| | | ) |
| | | |
| | | var db *gorm.DB |
| | | |
| | | func ConnectDB() error { |
| | | var err error |
| | | |
| | | dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4", |
| | | config.DbPersonCompInfo.Username, |
| | | config.DbPersonCompInfo.Password, |
| | | config.DbPersonCompInfo.MysqlAddr, |
| | | config.DbPersonCompInfo.Database) |
| | | |
| | | db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{ |
| | | // 禁用外键(指定外键时不会在mysql创建真实的外键约束) |
| | | DisableForeignKeyConstraintWhenMigrating: true, |
| | | //// 指定表前缀 |
| | | //NamingStrategy: schema.NamingStrategy{ |
| | | // TablePrefix: config.Conf.Mysql.TablePrefix + "_", |
| | | //}, |
| | | }) |
| | | |
| | | if err != nil { |
| | | logger.Error("mysql database open err: %s", err.Error()) |
| | | return err |
| | | } |
| | | |
| | | return nil |
| | | } |
New file |
| | |
| | | package db |
| | | |
| | | import ( |
| | | "basic.com/pubsub/protomsg.git" |
| | | "strconv" |
| | | ) |
| | | |
| | | type DbPersons struct { |
| | | BaseEntity |
| | | TableId string `gorm:"column:tableId" json:"tableId" example:"库表id"` |
| | | FaceFeature string `gorm:"column:faceFeature" json:"faceFeature" example:"人脸特征值(车主特征)"` |
| | | PersonPicUrl string `gorm:"column:personPicUrl" json:"personPicUrl" example:"图片路径,(车主照片)"` |
| | | PersonName string `gorm:"column:personName" json:"personName" example:"人员姓名,(车主姓名)"` |
| | | Age string `gorm:"column:age" json:"age" example:"年龄"` |
| | | Sex string `gorm:"column:sex" json:"sex" example:"性别 男 女(车主性别)"` |
| | | IdCard string `gorm:"column:idCard" json:"idCard" example:"身份证(车主身份证)"` |
| | | PhoneNum string `gorm:"column:phoneNum" json:"phoneNum" example:"手机号码"` |
| | | MonitorLevel string `gorm:"column:monitorLevel" json:"monitorLevel" example:"等级"` |
| | | PicDesc string `gorm:"column:picDesc" json:"picDesc" example:"照片标识"` |
| | | Reserved string `gorm:"column:reserved" json:"reserved" example:"其他"` |
| | | FromServerId string `gorm:"column:fromServerId" json:"fromServerId,omitempty" example:"入库serverId"` |
| | | ResidentialArea string `gorm:"column:residential_area;type:varchar(255)" json:"residentialArea" example:"小区"` |
| | | Community string `gorm:"column:community;type:varchar(255)" json:"community" example:"社区"` |
| | | LastAppearanceTime int64 `gorm:"column:last_appearance_time;type:int;not null;default:0" json:"lastAppearanceTime" example:"123456789"` |
| | | SnapshotCount int `gorm:"column:snapshot_count;type:varchar(255)" json:"snapshotCount" example:"10" comment:"抓拍次数"` |
| | | DaysAppeared int `gorm:"column:days_appeared;type:int(11);not null;default:0" json:"daysAppeared" example:"5" comment:"出现天数"` |
| | | Location string `gorm:"column:location;type:varchar(255)" json:"location" example:"建档地点" comment:"建档地点"` |
| | | LastLocation string `gorm:"column:last_location;type:varchar(255)" json:"lastLocation" example:"最后出现地点" comment:"最后出现地点"` |
| | | FaceAngleYaw int `gorm:"column:face_angle_yaw;type:int(11)" json:"faceAngleYaw" example:"15" comment:"人脸角度偏航角"` |
| | | FaceAngleRoll int `gorm:"column:face_angle_roll;type:int(11)" json:"faceAngleRoll" example:"16" comment:"人脸角度滚转角"` |
| | | FaceAnglePitch int `gorm:"column:face_angle_pitch;type:int(11)" json:"faceAnglePitch" example:"15" comment:"人脸角度俯仰角"` |
| | | PersonalStatusName string `gorm:"column:personal_status;type:varchar(31);comment:AI标签" json:"-"` //AI标签 |
| | | PersonalStatus string `gorm:"-" json:"personalStatus"` //AI标签对应名称 |
| | | Labels []string `gorm:"-" json:"labels"` //手动添加的标签对应名称 |
| | | AreaID string `json:"areaID" gorm:"index;column:communityID;type:varchar(299);"` //常驻小区 domain unit ID |
| | | OrgID string `json:"orgID" gorm:"index;column:org_id;type:varchar(299);"` //常驻派出所 domain unit ID |
| | | } |
| | | |
| | | func (dbp *DbPersons) GetPersonTotal(tableId string) (total int64, err error) { |
| | | sql := "select count(1) as total from dbtablepersons where isDelete=0 and tableId in (select id from dbtables where isDelete=0)" |
| | | if tableId != "" { |
| | | sql += " and tableId='" + tableId + "'" |
| | | } |
| | | err = db.Raw(sql).Count(&total).Error |
| | | return |
| | | } |
| | | |
| | | func (dbp *DbPersons) GetPersonsCompareCacheBase(from int, size int) (arr []*FeatureCacheBase, err error) { |
| | | var persons []DbPersons |
| | | sql := "select id, tableId, faceFeature, communityID, enable from dbtablepersons where isDelete=0 and tableId in (select id from dbtables where isDelete=0)" |
| | | sql += " order by id asc limit " + strconv.Itoa(from) + "," + strconv.Itoa(size) |
| | | err = db.Raw(sql).Find(&persons).Error |
| | | if err != nil { |
| | | return nil, err |
| | | } |
| | | |
| | | for _, p := range persons { |
| | | if p.FaceFeature != "" { |
| | | arr = append(arr, &FeatureCacheBase{ |
| | | Id: p.Id, |
| | | TableId: p.TableId, |
| | | AreaId: p.AreaID, |
| | | FaceFeature: p.FaceFeature, |
| | | Enable: int32(p.Enable), |
| | | }) |
| | | } |
| | | } |
| | | return |
| | | } |
| | | |
| | | func (dbp *DbPersons) GetPersonsCompareCacheById(id string) (info *protomsg.Esinfo, err error) { |
| | | sql := "select id,faceFeature,tableId,enable from dbtablepersons where id = \"" + id + "\"" |
| | | var p DbPersons |
| | | err = db.Raw(sql).First(&p).Error |
| | | if err != nil { |
| | | return nil, err |
| | | } |
| | | if p.FaceFeature != "" { |
| | | info = &protomsg.Esinfo{ |
| | | Id: p.Id, |
| | | Tableid: p.TableId, |
| | | FaceFeature: p.FaceFeature, |
| | | Enable: int32(p.Enable), |
| | | } |
| | | } |
| | | return |
| | | } |
New file |
| | |
| | | package db |
| | | |
| | | type PersonStatus struct { |
| | | CommunityID string `gorm:"column:communityID;type:varchar(299);"` //常驻小区 |
| | | DocumentNumber string `gorm:"column:documentNumber;type:varchar(299);"` //档案编号 |
| | | Status string `gorm:"column:status"` //标签 |
| | | FrequentAddress string `gorm:"column:frequentAddress; type:varchar(299);"` //常驻地址 |
| | | } |
| | | |
| | | func (ps *PersonStatus) TableName() string { |
| | | return "person_status" |
| | | } |
| | | |
| | | func (ps *PersonStatus) GetPersonAccessedAreas() (map[string][]string, error) { |
| | | var results []PersonStatus |
| | | err := db.Table(ps.TableName()).Find(&results).Error |
| | | if err != nil { |
| | | return nil, err |
| | | } |
| | | |
| | | var communityMap = make(map[string][]string, 0) |
| | | for _, p := range results { |
| | | communityMap[p.DocumentNumber] = append(communityMap[p.DocumentNumber], p.CommunityID) |
| | | } |
| | | |
| | | return communityMap, nil |
| | | } |
| | |
| | | import ( |
| | | "context" |
| | | "flag" |
| | | "os" |
| | | "path" |
| | | "path/filepath" |
| | | "sdkCompare/proto/facecompare" |
| | | "strconv" |
| | | "time" |
| | | |
| | | "sdkCompare/cache" |
| | | "sdkCompare/compare" |
| | | "sdkCompare/config" |
| | | "sdkCompare/db" |
| | | "sdkCompare/proto/facecompare" |
| | | |
| | | "basic.com/pubsub/protomsg.git" |
| | | "basic.com/valib/logger.git" |
| | |
| | | "nanomsg.org/go-mangos/transport/tcp" |
| | | ) |
| | | |
| | | var ( |
| | | envirment string |
| | | procName string |
| | | targetType1 string |
| | | ) |
| | | const procName = "faceCompare" |
| | | |
| | | func init() { |
| | | flag.StringVar(&envirment, "e", "config", "") |
| | | |
| | | flag.StringVar(&targetType1, "targetType1", "FaceDetect", "cache feature") |
| | | |
| | | flag.Parse() |
| | | vaversion.Usage() |
| | | } |
| | | |
| | | config.Init(envirment) |
| | | func main() { |
| | | err := config.Init() |
| | | if err != nil { |
| | | return |
| | | } |
| | | |
| | | procName = filepath.Base(os.Args[0]) |
| | | var logFile = path.Join(config.LogConf.Path, procName+".log") |
| | | var logFile = path.Join(config.LogConf.Path, "faceCompare.log") |
| | | |
| | | // 日志初始化 |
| | | logger.InitLogger(logFile, config.LogConf.Level, config.LogConf.MaxSize, config.LogConf.MaxBackups, config.LogConf.MaxAge) |
| | | logger.Info("logger init success !") |
| | | } |
| | | |
| | | func main() { |
| | | //esutil.InitLog(logger.Debug) |
| | | logger.Debug("This is a new server about sdk compare, proc name ", procName) |
| | | |
| | | serveUrl := "tcp://0.0.0.0:" |
| | | if err := cache.ConnectDB(); err != nil { |
| | | if err := db.ConnectDB(); err != nil { |
| | | logger.Error(err.Error()) |
| | | return |
| | | } |
| | |
| | | cache.InitDbTablePersons() |
| | | serveUrl = serveUrl + strconv.Itoa(config.DbPersonCompInfo.ServePort) |
| | | |
| | | logger.Debugf("%s serve url:%s", procName, serveUrl) |
| | | logger.Infof("%s serve url:%s", procName, serveUrl) |
| | | |
| | | Recv(serveUrl) |
| | | } |
| | |
| | | if sock, err = rep.NewSocket(); err != nil { |
| | | logger.Error("new rep socket err:", err) |
| | | } |
| | | |
| | | sock.AddTransport(ipc.NewTransport()) |
| | | sock.AddTransport(tcp.NewTransport()) |
| | | if err = sock.Listen(url); err != nil { |
| | |
| | | for { |
| | | select { |
| | | case <-ctx.Done(): |
| | | logger.Debug("ctx done") |
| | | logger.Info("ctx done") |
| | | return |
| | | default: |
| | | msg, err = sock.Recv() |
| | | if err != nil { |
| | | if err != nil || len(msg) <= 0 { |
| | | continue |
| | | } |
| | | |
| | | if len(msg) > 0 { |
| | | var compareType facecompare.CompareRequest |
| | | err = proto.Unmarshal(msg, &compareType) |
| | | if err != nil { |
| | | logger.Error("compareType json unmarshal error") |
| | | var request facecompare.CompareRequest |
| | | err = proto.Unmarshal(msg, &request) |
| | | if err != nil { |
| | | logger.Warn("CompareRequest json unmarshal error") |
| | | continue |
| | | } |
| | | |
| | | var result []byte |
| | | if request.CompareType == facecompare.CompareType_Compare { |
| | | var compareArgInfo protomsg.CompareArgs |
| | | var cacheChangeInfo protomsg.EsPersonCacheChange |
| | | if err = proto.Unmarshal(request.Payload, &compareArgInfo); err == nil { |
| | | timeStart := time.Now() |
| | | result = compare.GetComparePersonBaseInfo(compareArgInfo) |
| | | logger.Debug("用时:", time.Since(timeStart)) |
| | | } else if err = proto.Unmarshal(request.Payload, &cacheChangeInfo); err == nil { |
| | | cache.UpdateCache(&cacheChangeInfo) |
| | | } else { |
| | | logger.Warn("CompareArgs or EsPersonCacheChange json unmarshal error") |
| | | continue |
| | | } |
| | | var result []byte |
| | | if compareType.CompareType == facecompare.CompareType_Compare { |
| | | var compareArgInfo protomsg.CompareArgs |
| | | var cacheChangeInfo protomsg.EsPersonCacheChange |
| | | if err = proto.Unmarshal(compareType.Payload, &compareArgInfo); err == nil { |
| | | timeStart := time.Now() |
| | | result = cache.GetComparePersonBaseInfo(compareArgInfo) |
| | | logger.Debug("用时:", time.Since(timeStart)) |
| | | } else if err = proto.Unmarshal(compareType.Payload, &cacheChangeInfo); err == nil { |
| | | cache.UpdateCache(&cacheChangeInfo) |
| | | } else { |
| | | logger.Error("CompareArgs or EsPersonCacheChange json unmarshal error") |
| | | continue |
| | | } else if request.CompareType == facecompare.CompareType_UpdateCache { |
| | | var compareEvent protomsg.CompareEvent |
| | | if err = proto.Unmarshal(request.Payload, &compareEvent); err == nil { |
| | | if compareEvent.EventType == protomsg.CompareEventType_ReInitCache { //加入集群后重新初始化缓存 |
| | | cache.ReInitDbTablePersonsCache() |
| | | } else if compareEvent.EventType == protomsg.CompareEventType_UpdateCache { //库中新增更新缓存 |
| | | id := string(compareEvent.Payload) |
| | | cache.UpdateDbPersonsCacheById(id) |
| | | logger.Info("--------------更新人员缓存, id: ", id) |
| | | } |
| | | } else if compareType.CompareType == facecompare.CompareType_UpdateCache { |
| | | var compareEvent protomsg.CompareEvent |
| | | if err = proto.Unmarshal(compareType.Payload, &compareEvent); err == nil { |
| | | if compareEvent.EventType == protomsg.CompareEventType_ReInitCache { //加入集群后重新初始化缓存 |
| | | cache.ReInitDbTablePersonsCache() |
| | | } else if compareEvent.EventType == protomsg.CompareEventType_UpdateCache { //库中新增更新缓存 |
| | | id := string(compareEvent.Payload) |
| | | cache.UpdateDbPersonsCacheById(id) |
| | | logger.Debug("--------------更新人员缓存, id: ", id) |
| | | } |
| | | } else { |
| | | logger.Error("CompareEvent json unmarshal error") |
| | | continue |
| | | } |
| | | } else { |
| | | logger.Warn("CompareEvent json unmarshal error") |
| | | continue |
| | | } |
| | | err = sock.Send(result) |
| | | if err != nil { |
| | | logger.Error("send reply err:", err.Error()) |
| | | } |
| | | } |
| | | |
| | | err = sock.Send(result) |
| | | if err != nil { |
| | | logger.Warn("send reply err:", err.Error()) |
| | | } |
| | | } |
| | | } |
| | |
| | | ) |
| | | |
| | | // 获取本机网卡IP |
| | | func GetLocalIP(networkName string) (ipv4 string,mask string, err error) { |
| | | func GetLocalIP(networkName string) (ipv4 string, mask string, err error) { |
| | | interfaces, err := net.Interfaces() |
| | | if err != nil { |
| | | return "","", err |
| | | return "", "", err |
| | | } |
| | | |
| | | for _, i := range interfaces { |
| | | byName, err := net.InterfaceByName(i.Name) |
| | | if err != nil { |
| | | return "","", err |
| | | return "", "", err |
| | | } |
| | | addresses, err := byName.Addrs() |
| | | for _, v := range addresses { |
| | | if ipnet, ok:=v.(*net.IPNet);ok && !ipnet.IP.IsLoopback(){ |
| | | if ipnet.IP.To4() !=nil{ |
| | | if byName.Name == networkName{ |
| | | if ipnet, ok := v.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { |
| | | if ipnet.IP.To4() != nil { |
| | | if byName.Name == networkName { |
| | | maskStr := ipnet.Mask.String() |
| | | mask64, _ := strconv.ParseUint(maskStr, 16, 32) |
| | | return ipnet.IP.String(),IpIntToString(int(mask64)),nil |
| | | return ipnet.IP.String(), IpIntToString(int(mask64)), nil |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return "","", errors.New("ipv4 not found") |
| | | return "", "", errors.New("ipv4 not found") |
| | | } |
| | | |
| | | func IpIntToString(ipInt int) string{ |
| | | func IpIntToString(ipInt int) string { |
| | | ipSegs := make([]string, 4) |
| | | var len int = len(ipSegs) |
| | | buffer := bytes.NewBufferString("") |
| | |
| | | } |
| | | return buffer.String() |
| | | } |
| | | |
| | | // 判断一个数组是否包含另一个数组的所有元素 |
| | | func ArrayContains(list []string, arr []string) bool { |
| | | c := 0 |
| | | if arr == nil || list == nil { |
| | | return false |
| | | } |
| | | for _, s := range arr { |
| | | for _, t := range list { |
| | | if s == t { |
| | | c++ |
| | | break |
| | | } |
| | | } |
| | | } |
| | | return c == len(arr) |
| | | } |