package SpartaApi import ( "context" "encoding/json" "errors" "fmt" "github.com/tiger1103/gfast/v3/library/liberr" "io" "log" "net/url" "os" "strings" "time" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" "github.com/tiger1103/gfast-cache/cache" "github.com/tiger1103/gfast/v3/api/v1/common/coryCommon" commonService "github.com/tiger1103/gfast/v3/internal/app/common/service" ) const ( Sensitivity = 0.6 // 识别灵敏度 //AI工单(摄像头) CAMERA = "head smoke" // AI工单(摄像头) UAV_MATRIX = "pho hole shelves pile" // 方阵内容 UAV_MACHINE = "excavator Roller Truck_crane Loader Submersible_drilling_rig Sprinkler Truck_mounted_crane Truck" // 大型机械 //远界 YJCAMERA = "fire,hardhat,smoking" ) var Url = g.Cfg().MustGet(gctx.New(), "spartaApi.Url").String() var yjUrl = g.Cfg().MustGet(gctx.New(), "yjSpartaApi.Url").String() // 定义一个映射来存储不同的类型及其对应的描述 var typeDescriptions = map[string]string{ "head": "未带安全帽", "smoke": "吸烟", "belt": "未系安全带", "excavator": "挖掘机", "Roller": "压路机", "Truck_crane": "汽车吊", "Loader": "装载机", "Submersible_drilling_rig": "潜挖钻机", "Sprinkler": "沙水车", "Truck_mounted_crane": "随车吊", "Truck": "货车", //远界 "nohelmet": "未戴安全帽", "cigarette": "吸烟", "fire": "火灾", "smoggy": "烟雾", } // @Title GetDescription 2024/8/7 17:34:00 // @Description 可复用的函数,根据输入的类型返回对应的描述 // @Auth Cory func GetDescription(tp string) string { if description, exists := typeDescriptions[tp]; exists { return description } return "未知类型" } //func init() { // fmt.Println("斯巴达----------------") // token, _ := spartaApiTokenFunc() // fmt.Println("token----------------", token) //} // @Title spartaApiTokenFunc 2024/8/7 17:35:00 // @Description 登录获取身份凭证 // @Auth Cory func spartaApiTokenFunc() (token string, err error) { key := "arithmetic:token" ctx := gctx.New() prefix := g.Cfg().MustGet(ctx, "system.cache.prefix").String() gfCache := cache.New(prefix) get, err := g.Redis().Get(ctx, gfCache.CachePrefix+key) if err != nil && get.String() != "" { token = get.String() return token, err } else { clientId := g.Cfg().MustGet(gctx.New(), "spartaApi.key") clientSecret := g.Cfg().MustGet(gctx.New(), "spartaApi.secret") uri := Url + "/token?clientId=" + clientId.String() + "&clientSecret=" + clientSecret.String() response, err := g.Client().Get(gctx.New(), uri) if err != nil { return "", err } var tk *TokenEntity err = json.Unmarshal([]byte(response.ReadAllString()), &tk) if err != nil { return "", err } else { tk.Token = "Basic " + tk.Token } // 将token存储到redis中,tiken默认时间为秒,(这里少5000秒,防止token过期还存在redis中) commonService.Cache().Set(ctx, key, tk.Token, time.Duration(tk.ExpiresAt-5000)*time.Second) token = tk.Token return token, err } } //// @Title CommonAlgorithmTwoFunc 2024/8/7 17:06:00 //// @Description 提供算法得到的目标信息 //// @Auth Cory //func CommonAlgorithmTwoFunc(ctx context.Context, recognize *RecognizeReq) (result *RecognizeRes, flag bool, err error) { // result = new(RecognizeRes) // flag = false // // 1、调用算法 // body, err := ObjectIdentificationFunc(ctx, recognize) // if err != nil { // return // } // // 2、组装数据 // err = json.Unmarshal(body, &result) // if err != nil { // return // } // // 3、布尔值 // if len(result.Targets) == 0 { // 表示无违规操作 // return // } else { // 表述有违规操作 // flag = true // return // } //} // @Title CommonAlgorithmTwoUav 2024/8/7 17:06:00 // @Description 提供算法得到的目标信息【飞机专用】 // @Auth Cory func CommonAlgorithmTwoUav(ctx context.Context, recognize *RecognizeReq) (result *RecognizeRes, flag bool, err error) { result = new(RecognizeRes) flag = false //// 1、调用算法 //body, err := ObjectIdentificationFunc(ctx, recognize) //if err != nil { // return //} recognizeResult := `{ "hasTarget": 1, "originalImgSize": [1920, 1080], "targets": [ { "type": "pho", "size": [282, 274], "leftTopPoint": [3192, 2758], "score": 0.6154276132583618 }, { "type": "pho", "size": [343, 139], "leftTopPoint": [4577, 2836], "score": 0.722245454788208 }, { "type": "pho", "size": [372, 158], "leftTopPoint": [4554, 3761], "score": 0.7273581027984619 }, { "type": "pho", "size": [351, 129], "leftTopPoint": [4124, 2251], "score": 0.749356746673584 }, { "type": "pho", "size": [336, 152], "leftTopPoint": [4211, 2379], "score": 0.7633119225502014 }, { "type": "pho", "size": [343, 147], "leftTopPoint": [4321, 2515], "score": 0.7663174867630005 }, { "type": "pho", "size": [333, 152], "leftTopPoint": [4933, 2771], "score": 0.7939081192016602 }, { "type": "pho", "size": [334, 143], "leftTopPoint": [4574, 2966], "score": 0.8044442534446716 }, { "type": "pho", "size": [332, 138], "leftTopPoint": [4243, 2921], "score": 0.8075516819953918 }, { "type": "pho", "size": [315, 156], "leftTopPoint": [3628, 2535], "score": 0.8091028332710266 }, { "type": "pho", "size": [336, 129], "leftTopPoint": [3913, 3655], "score": 0.8116179704666138 }, { "type": "pho", "size": [342, 139], "leftTopPoint": [4471, 2290], "score": 0.814013659954071 }, { "type": "pho", "size": [350, 143], "leftTopPoint": [4528, 2432], "score": 0.8172851800918579 }, { "type": "pho", "size": [342, 171], "leftTopPoint": [3992, 2469], "score": 0.8185974359512329 }, { "type": "pho", "size": [338, 149], "leftTopPoint": [4433, 3345], "score": 0.8222267031669617 }, { "type": "pho", "size": [332, 134], "leftTopPoint": [4284, 2660], "score": 0.8247078657150269 }, { "type": "pho", "size": [328, 134], "leftTopPoint": [4616, 2713], "score": 0.8274019956588745 }, { "type": "pho", "size": [350, 139], "leftTopPoint": [4928, 3685], "score": 0.8295787572860718 }, { "type": "pho", "size": [339, 136], "leftTopPoint": [4908, 2905], "score": 0.8317150473594666 }, { "type": "pho", "size": [339, 135], "leftTopPoint": [4232, 3708], "score": 0.8319769501686096 }, { "type": "pho", "size": [323, 141], "leftTopPoint": [3461, 3167], "score": 0.8382804989814758 }, { "type": "pho", "size": [368, 132], "leftTopPoint": [3761, 3219], "score": 0.8471034169197083 }, { "type": "pho", "size": [338, 140], "leftTopPoint": [3894, 2986], "score": 0.8511925339698792 }, { "type": "pho", "size": [337, 144], "leftTopPoint": [3580, 2942], "score": 0.8524681329727173 }, { "type": "pho", "size": [348, 142], "leftTopPoint": [3620, 3467], "score": 0.8603440523147583 }, { "type": "pho", "size": [352, 145], "leftTopPoint": [4632, 2584], "score": 0.8645903468132019 }, { "type": "pho", "size": [365, 139], "leftTopPoint": [4585, 3633], "score": 0.8663488626480103 }, { "type": "pho", "size": [323, 138], "leftTopPoint": [3919, 2847], "score": 0.8686794638633728 }, { "type": "pho", "size": [394, 155], "leftTopPoint": [3644, 3335], "score": 0.8729261755943298 }, { "type": "pho", "size": [328, 143], "leftTopPoint": [4274, 3576], "score": 0.8783137798309326 }, { "type": "pho", "size": [300, 314], "leftTopPoint": [3247, 2571], "score": 0.879583477973938 }, { "type": "pho", "size": [660, 217], "leftTopPoint": [4903, 3817], "score": 0.8797935843467712 }, { "type": "pho", "size": [331, 170], "leftTopPoint": [3923, 2713], "score": 0.8806164264678955 }, { "type": "pho", "size": [332, 140], "leftTopPoint": [4240, 2782], "score": 0.8832747936248779 }, { "type": "pho", "size": [318, 143], "leftTopPoint": [4129, 3295], "score": 0.8922125101089478 }, { "type": "pho", "size": [349, 143], "leftTopPoint": [3867, 3116], "score": 0.8925455808639526 }, { "type": "pho", "size": [333, 138], "leftTopPoint": [4016, 3404], "score": 0.8939041495323181 }, { "type": "pho", "size": [353, 158], "leftTopPoint": [3942, 2604], "score": 0.8950177431106567 }, { "type": "pho", "size": [350, 148], "leftTopPoint": [4655, 3507], "score": 0.9090152382850647 }, { "type": "pho", "size": [322, 153], "leftTopPoint": [3587, 2792], "score": 0.9102197289466858 }, { "type": "pho", "size": [348, 159], "leftTopPoint": [4777, 3397], "score": 0.9125684499740601 } ], "pho_number": 41 }` body := []byte(recognizeResult) // 2、组装数据 err = json.Unmarshal(body, &result) if err != nil { fmt.Println("Error:", err) return } // 3、布尔值 if len(result.Targets) == 0 { // 表示无违规操作 flag = false } else { // 表述有违规操作 flag = true } //绘图 replace := strings.Replace(recognize.CapUrl, coryCommon.GlobalPath, "", 1) imgPath := coryCommon.FileToFunc(replace, 2) num := 0 mp := make(map[string]string) entity := coryCommon.TestDrawRectTextEntity{ ImPath: imgPath, } var zuobiao []*coryCommon.CoordinatesListEntity for _, data := range result.Targets { if data.Score >= Sensitivity { tp := data.Type mp[tp] = GetDescription(tp) flag = true num = num + 1 zuobiao = append(zuobiao, &coryCommon.CoordinatesListEntity{ X: data.LeftTopPoint[0], Y: data.LeftTopPoint[1], W: data.Size[0], H: data.Size[1], }) } } entity.Coordinates = zuobiao coryCommon.TestDrawRectTextFunc(&entity) return } /* hat:安全帽识别; head:不戴安全帽识别; smoke:吸烟识别; belt : 安全带识别; waste :工程垃圾识别(暂无) excavator:挖掘机; Roller:压路机; Truck_crane:汽车吊; Loader:装载机; Submersible_drilling_rig:潜挖钻机; Sprinkler:洒水车; Truck_mounted_crane:随车吊; Truck:货车 pho:光伏板 hole:洞 shelves:架子 */ func ObjectIdentificationFunc(ctx context.Context, recognize *RecognizeReq) (body []byte, err error) { // 1、获取token token, err := spartaApiTokenFunc() if err != nil { err = errors.New("获取斯巴达token错误!" + err.Error()) return } // 2、设置请求数据 uri := Url + "/api/recognize?capUrl=" + recognize.CapUrl + "&recType=" + url.QueryEscape(recognize.RecType) + "&async=" + recognize.Async + "&callBackUrl=" + recognize.CallBackUrl + "&area_high=" + recognize.AreaHigh response, err := g.Client().ContentJson().SetHeaderMap(map[string]string{ "Authorization": token, }).Get(gctx.New(), uri) defer response.Body.Close() // 3、返回数据 body, err = io.ReadAll(response.Body) fmt.Println("请求的URL ", uri) return } // @Title CommonAlgorithmFunc 2024/8/7 17:07:00 // @Description 调用算法,得到目标信息,然后圈出来 // @Auth Cory func CommonAlgorithmFunc(ctx context.Context, recognize *RecognizeReq) (mp map[string]string, flag bool, num int, err error) { flag = false num = 0 // 0、记录绝对路径,以便后续操作 //absolutePath := "C:\\Users\\MSI\\Pictures\\222.png" absolutePath := recognize.CapUrl prefix := g.Cfg().MustGet(gctx.New(), "spartaApi.prefix") recognize.CapUrl = replacePrefix(recognize.CapUrl, "/resource/public/", prefix.String()+"/file/") // 1、调用算法 body, err := ObjectIdentificationFunc(ctx, recognize) if err != nil { return } // 2、组装数据 var data []json.RawMessage err = json.Unmarshal(body, &data) if err != nil { fmt.Println("Error:", err) return } var result RecognizeRes for i, rawMsg := range data { switch i { case 0: err = json.Unmarshal(rawMsg, &result.HasTarget) case 1: err = json.Unmarshal(rawMsg, &result.OriginalImgSize) default: var target TargetsEntity err = json.Unmarshal(rawMsg, &target) if err == nil { result.Targets = append(result.Targets, target) } } if err != nil { fmt.Println("Error:", err) return } } // 3、遍历数据,然后在数据中绘画矩形框 if result.HasTarget == 0 { return } mp = make(map[string]string) for _, data := range result.Targets { if data.Score >= Sensitivity { tp := data.Type mp[tp] = GetDescription(tp) flag = true num = num + 1 coryCommon.Test_draw_rect_text(absolutePath, data.LeftTopPoint[0], data.LeftTopPoint[1], data.Size[0], data.Size[1]) } } return } // replacePrefix 将路径中指定前缀及其之前的部分替换成新的前缀 func replacePrefix(originalPath, prefixToReplace, newPrefix string) string { // 查找要替换的前缀的位置 index := strings.Index(originalPath, prefixToReplace) // 如果找到前缀 if index != -1 { // 保留前缀之后的部分 remainingPath := originalPath[index+len(prefixToReplace):] // 拼接新的路径 newPath := newPrefix + remainingPath return newPath } // 如果未找到前缀,返回原始路径 return originalPath } /* ============================================================================= 远界算法 ============================================================================= */ func CORYAInit(ctx context.Context) { req := RecognizeReq{ CapUrl: "http://xny.yj-3d.com:7363/file/temporary/2025-06-22/sxt_1750583729497_972.jpg", RecType: YJCAMERA, } now := time.Now() marshal, _ := json.Marshal(req) fmt.Println("------------", string(marshal)) fmt.Println("------------", now) result, flag, err := CommonAlgorithmTwoFunc(gctx.New(), &req) now2 := time.Now() fmt.Println("result", result, flag, err) fmt.Println("===========用时", now2.Sub(now)) fmt.Println("===========") } // @Title CommonAlgorithmTwoFunc 2024/8/7 17:06:00 // @Description 提供算法得到的目标信息(远界版本) // @Auth Cory func CommonAlgorithmTwoFunc(ctx context.Context, recognize *RecognizeReq) (result *RecognizeRes, flag bool, err error) { err = g.Try(ctx, func(ctx context.Context) { result = new(RecognizeRes) flag = false // 1、调用算法 postData := map[string]interface{}{ "type": recognize.RecType, "url": recognize.CapUrl, "extract": false, } response, err := g.Client().ContentJson().Post(ctx, yjUrl, postData) fmt.Println("1请求的URL ", err) liberr.ErrIsNil(ctx, err, "远界算法请求失败") defer response.Body.Close() body, err := io.ReadAll(response.Body) fmt.Println("2请求的URL ", err) liberr.ErrIsNil(ctx, err, "远界算法数据获取失败") fmt.Println("返回的数据为 ", string(body)) // 2、组装数据 err = json.Unmarshal(body, &result) if err != nil { return } //======================= //======================= //1、本地创建一个text来记录日志 // 定义文件路径 filePath := coryCommon.GetCWD() + "/coryLogs/logs/ai_log.txt" // 打开文件,如果文件不存在则创建 file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } defer file.Close() // 写入日志信息 marshal, _ := json.Marshal(result) marshal2, _ := json.Marshal(postData) _, err = file.WriteString(fmt.Sprintf("参数:%s,==================结果:%s\n", string(marshal), string(marshal2))) if err != nil { log.Fatal(err) } // 3、布尔值 if len(result.Targets) == 0 { // 表示无违规操作 return } else { // 表述有违规操作 flag = true return } }) return }