using DocumentFormat.OpenXml.Bibliography; using DocumentFormat.OpenXml.EMMA; using Infrastructure; using Infrastructure.CloudSdk; using Infrastructure.CloudSdk.minio; using Infrastructure.Extensions; using Infrastructure.Helpers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Log4Net.AspNetCore.Entities; using Minio; using Newtonsoft.Json; using NPOI.SS.Formula.Functions; using OpenAuth.App.BaseApp.Base; using OpenAuth.App.Interface; using OpenAuth.App.ServiceApp.Algo.Request; using OpenAuth.App.ServiceApp.Algo.Response; using OpenAuth.Repository; using OpenAuth.Repository.Domain; using OpenAuth.WebApi; using SqlSugar; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Text.Json.Nodes; using System.Threading.Tasks; namespace OpenAuth.App.ServiceApp.Algo { public class DaHuaAiApp : SqlSugarBaseApp { // 8192坐标系 private const float STANDARD_WIDTH = 8192f; private const float STANDARD_HEIGHT = 8192f; public MinioService _minioService; private readonly ILogger _logger; private readonly MqttClientManager _mqttClientManager; public DaHuaAiApp(ISugarUnitOfWork unitWork, MinioService minioService, ILogger logger, MqttClientManager mqttClientManager, ISimpleClient repository, IAuth auth) : base(unitWork, repository, auth) { _minioService = minioService; _logger = logger; _mqttClientManager = mqttClientManager; } #region 大华算法 //分析两次航线图片 public async Task>> BehaviorAlarm(string firstId, string secondId, string cdid) { using (var db = UnitWork.CreateContext()) { var imageList1 = await db.LasaMediaFile.AsQueryable().Where(r => r.TaskId == firstId && r.AbsoluteAltitude != 0 && r.AbsoluteAltitude != null).OrderBy(r => r.CreateTime).ToListAsync(); var imageList2 = await db.LasaMediaFile.AsQueryable().Where(r => r.TaskId == secondId && r.AbsoluteAltitude != 0 && r.AbsoluteAltitude != null).OrderBy(r => r.CreateTime).ToListAsync(); //var imageList1 = await db.LasaMediaFile.AsQueryable().Where(r => r.Id == firstId && r.AbsoluteAltitude != 0 && r.AbsoluteAltitude != null).ToListAsync(); //var imageList2 = await db.LasaMediaFile.AsQueryable().Where(r => r.Id == secondId && r.AbsoluteAltitude != 0 && r.AbsoluteAltitude != null).ToListAsync(); List dataList = new List(); if (imageList1.Count() != imageList2.Count()) { //删除检测记录 await db.Lasa_ChangeDetection.DeleteByIdAsync(cdid); db.Commit(); throw new Exception("任务照片数量不对应,请重新选择任务"); } for (int i = 0; i < imageList1.Count; i++) { dataList.Add(new { @event = "event.capturePic", uid = "1", channelCode = "sdhc04", recordId = "kQUXlb1Y8oDgCpZSo7l2yG175617335006157587", sourceId = "kQUXlb1Y8oDgCpZSo7l2yG175617335006157587", taskSource = 1, taskId = "8ab0e1e213234a848e20d0d335559786", capTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), taskTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), cdid = cdid, imageInfo = new { imgSize = 1667235, imgWidth = 4032, imgHeight = 3024 }, imageInfoList = new[] { new { imgUrl = "http://175.27.168.120:6013/test/"+imageList1[i].ObjectKey, imgSize = imageList1[i].Size, imgWidth = imageList1[i].Width, imgHeight = imageList1[i].Height, imgType = 0, longitude = imageList1[i].Lng, absAltitude = imageList1[i].AbsoluteAltitude, latitude = imageList1[i].Lat, zoom = imageList1[i].DigitalZoomRatio, yaw = imageList1[i].GimbalYawDegree, pitch = imageList1[i].GimbalPitchDegree, roll = imageList1[i].GimbalRollDegree, focalLength = imageList1[i].FocalLength }, new { imgUrl = "http://175.27.168.120:6013/test/"+imageList2[i].ObjectKey, imgSize = imageList2[i].Size, imgWidth = imageList2[i].Width, imgHeight = imageList2[i].Height, imgType = 1, longitude =imageList2[i].Lng, absAltitude = imageList2[i].AbsoluteAltitude,//拍摄绝对高度 latitude = imageList2[i].Lat, zoom = imageList2[i].DigitalZoomRatio,//放大倍率 yaw =imageList2[i].GimbalYawDegree,//偏航角? pitch = imageList2[i].GimbalPitchDegree,//滚角? roll = imageList2[i].GimbalRollDegree, focalLength = imageList2[i].FocalLength//焦距 } } }); } return new Response> { Result = dataList, Message = "获取数据成功" }; } } public async Task> AddDaHuaImg(string info) { Console.WriteLine(info); _logger.LogError("耕地破坏报警数据;" + info); using (var db = UnitWork.CreateContext()) { var data = JsonConvert.DeserializeObject(info); string cdid = data.cdid.ToString(); var oldinfo = await db.LasaAiAchievement.GetFirstAsync(r => r.TaskId == cdid); var imageList = data.imageInfoList; string detectRegionJson = JsonConvert.SerializeObject(data.info.detectRegion); //string detectRegionJson = "[[0, 0],[8063, 647],[8017, 7774],[552, 8033]]"; //string url = "http://123.132.248.154:6015/DroneEnforcement/2025/20250514/lQLPJyIVimQWGKnNA4PNA6Gw1D3q5gbxUvQIiumcIx4vAA_929_899.png"; var regionArray = JsonConvert.DeserializeObject(detectRegionJson); var imaList = data.imgList; if (oldinfo != null) { string compareGroupId = Guid.NewGuid().ToString(); int index = 0; foreach (var item in imageList) { //插入详情 LasaAiAchievementDetail lasaAiAchievementDetail = new LasaAiAchievementDetail() { Id = Guid.NewGuid().ToString(), Image = item.imgUrl, AiAchievementId = oldinfo.Id, Lng = (double?)item.longitude ?? 0.0, Lat = (double?)item.latitude ?? 0.0, CompareIndex = index, GroupId = compareGroupId, CompareCount = regionArray.Length }; // 如果是第二张图片 -> 画区域 + 上传 if (index == 1) { Console.WriteLine(item.imgUrl); Console.WriteLine(regionArray); var imgurlend = await DrawingImgAndUpload1(item.imgUrl.ToString().Replace("\\", ""), imaList, cdid); lasaAiAchievementDetail.Image = imgurlend; } await db.LasaAiAchievementDetail.InsertAsync(lasaAiAchievementDetail); index++; } } else { string compareGroupId = Guid.NewGuid().ToString(); int index = 0; LasaAiAchievement lasaAiAchievement = new LasaAiAchievement { Id = Guid.NewGuid().ToString(), Title = "本地耕地破坏区域报警", CreateTime = DateTime.Now, AiModel = "DaHuaAi", TaskId = cdid }; foreach (var item in imageList) { //插入详情 LasaAiAchievementDetail lasaAiAchievementDetail = new LasaAiAchievementDetail() { Id = Guid.NewGuid().ToString(), Image = item.imgUrl, AiAchievementId = lasaAiAchievement.Id, Lng = (double?)item.longitude ?? 0.0, Lat = (double?)item.latitude ?? 0.0, CompareIndex = index, GroupId = compareGroupId, CompareCount = regionArray.Length }; // 如果是第二张图片 -> 画区域 + 上传 if (index == 1) { Console.WriteLine(item.imgUrl); Console.WriteLine(regionArray); //var imgurlend = await DrawingImgAndUpload(item.imgUrl, regionArray); var imgurlend = await DrawingImgAndUpload1(item.imgUrl.ToString().Replace("\\", ""), imaList, cdid); lasaAiAchievementDetail.Image = imgurlend; } lasaAiAchievement.Lat = item.latitude; lasaAiAchievement.Lng = item.longitude; lasaAiAchievement.Cover = item.imgUrl; await db.LasaAiAchievementDetail.InsertAsync(lasaAiAchievementDetail); index++; } await db.LasaAiAchievement.InsertAsync(lasaAiAchievement); //查询监测记录,然后更新监测记录的成果id await db.Lasa_ChangeDetection.UpdateAsync(u => new Lasa_ChangeDetection { AiAchievementId = lasaAiAchievement.Id }, u => u.Id == cdid); } if (db.Commit()) return new Response { Result = true, Message = "添加成功" }; else return new Response { Result = false, Message = "添加失败" }; } } //public async Task DrawingImgAndUpload(string url, int[][] regionArray) public async Task DrawingImgAndUpload(string url, int[][] regionArray, string cdid) { //string url = "http://123.132.248.154:6015/DroneEnforcement/2025/20250514/lQLPJyIVimQWGKnNA4PNA6Gw1D3q5gbxUvQIiumcIx4vAA_929_899.png"; // detectRegion JSON(可以直接替换成你的接口返回数据) //string detectRegionJson = "[[0, 0],[8063, 647],[8017, 7774],[552, 8033]]"; //var regionArray = JsonConvert.DeserializeObject(detectRegionJson); //Console.WriteLine($"regionArray 是否为空"); //if (regionArray == null || regionArray.Length == 0) // throw new ArgumentException("detectRegion 参数无效"); Point[] polygon = new Point[regionArray.Length]; for (int i = 0; i < regionArray.Length; i++) { polygon[i] = new Point(regionArray[i][0], regionArray[i][1]); } using (HttpClient client = new HttpClient()) { var bytes = await client.GetByteArrayAsync(url); using (var ms = new MemoryStream(bytes)) using (var image = Image.FromStream(ms)) using (var bmp = new Bitmap(image)) using (var g = Graphics.FromImage(bmp)) { g.SmoothingMode = SmoothingMode.AntiAlias; using (var pen = new Pen(Color.Red, 5)) { g.DrawPolygon(pen, polygon); } using (var outputStream = new MemoryStream()) { bmp.Save(outputStream, ImageFormat.Png); outputStream.Position = 0; string fileName = Path.GetFileName(new Uri(url).AbsolutePath); // 上传到 MinIO(直接传 MemoryStream) string uploadedUrl = await _minioService.UploadStreamFile(outputStream, fileName, "test", cdid); Console.WriteLine("返回imgurl:" + uploadedUrl); return uploadedUrl; } } } } public async Task DrawingImgAndUpload1(string url, dynamic rects, string cdid) { try { Console.WriteLine(url); // 下载图片 //url = "http://123.132.248.154:6015/DroneEnforcement/2025/20250514/localStorage.jpg"; using var stream = await httpClient.GetStreamAsync(url); using var image = Image.FromStream(stream); using var g = Graphics.FromImage(image); using var pen = new Pen(Color.Red, 5); // 红色粗线 float scaleX = image.Width / STANDARD_WIDTH; float scaleY = image.Height / STANDARD_HEIGHT; foreach (var item in rects) { // 画框 foreach (var rect in item.objectRect) { Console.WriteLine(JsonConvert.SerializeObject(rect)); int x = (int)(rect.objLeft * scaleX); int y = (int)(rect.objTop * scaleY); int width = (int)((rect.objRight - rect.objLeft) * scaleX); int height = (int)((rect.objBottom - rect.objTop) * scaleY); if (x < image.Width && y < image.Height && width > 0 && height > 0) { g.DrawRectangle(pen, x, y, width, height); } } } // 保存到内存流再上传 using var outputStream = new MemoryStream(); image.Save(outputStream, ImageFormat.Png); outputStream.Position = 0; string fileName = Path.GetFileName(new Uri(url).AbsolutePath); // 上传到 MinIO string uploadedUrl = await _minioService.UploadStreamFile(outputStream, fileName, "test", cdid); Console.WriteLine("返回 imgurl:" + uploadedUrl); return uploadedUrl; } catch (Exception ex) { Console.WriteLine($"处理图片失败: {url}, 错误: {ex.Message}"); return string.Empty; } } public async void DrawingImgAsync() { string url = "http://123.132.248.154:6015/DroneEnforcement/2025/20250514/lQLPJyIVimQWGKnNA4PNA6Gw1D3q5gbxUvQIiumcIx4vAA_929_899.png"; string savePath = "output.png"; // detectRegion JSON(可以直接替换成你的接口返回数据) string detectRegionJson = "[[0, 0],[8063, 647],[8017, 7774],[552, 8033]]"; // 解析 JSON var regionArray = JsonConvert.DeserializeObject(detectRegionJson); if (regionArray == null) { Console.WriteLine("解析 detectRegion 失败"); return; } Point[] polygon = new Point[regionArray.Length]; for (int i = 0; i < regionArray.Length; i++) { polygon[i] = new Point(regionArray[i][0], regionArray[i][1]); } using (HttpClient client = new HttpClient()) { var bytes = await client.GetByteArrayAsync(url); using (var ms = new System.IO.MemoryStream(bytes)) using (var image = Image.FromStream(ms)) using (var bmp = new Bitmap(image)) using (var g = Graphics.FromImage(bmp)) { g.SmoothingMode = SmoothingMode.AntiAlias; using (var pen = new Pen(Color.Red, 5)) // 红色边框 using (var brush = new SolidBrush(Color.FromArgb(80, Color.Blue))) // 半透明填充 { g.FillPolygon(brush, polygon); g.DrawPolygon(pen, polygon); } bmp.Save(savePath, ImageFormat.Png); } } Console.WriteLine("已保存图片: " + savePath); } public async Task> UpdateState(string id) { using (var db = UnitWork.CreateContext()) { await db.Lasa_ChangeDetection.UpdateAsync(u => new Lasa_ChangeDetection { IsFinish = true }, u => u.Id == id); if (db.Commit()) return new Response { Result = true, Message = "检测完成" }; else return new Response { Result = false, Message = "检测完成" }; } } #endregion #region 烟雾报警 private static readonly HttpClient httpClient = new HttpClient(); public async Task> AddDaHuaSmokeDetectionImg(string info) { Console.WriteLine(info); _logger.LogError("烟雾报警数据;" + info); var config = ConfigHelper.GetConfigRoot(); var ImgUrlIp = config["DaHua:ImgUrl"]; using (var db = UnitWork.CreateContext()) { var data = JsonConvert.DeserializeObject(info); var imageList = data.imageList; foreach (var img in imageList) { //var uploadedUrl = await DrawRectanglesOnImageAsync(img.imgUrl.ToString().Replace("\\", ""), img.objectRect); var uploadedUrl = await DrawRectanglesOnImageAsync(ImgUrlIp + img.imgUrl.ToString().Replace("\\", ""), img.objectRect); Console.WriteLine($"已处理图片 {uploadedUrl}"); LasaAiAchievement lasaAiAchievement = new LasaAiAchievement(); lasaAiAchievement.Id = Guid.NewGuid().ToString(); lasaAiAchievement.CreateTime = DateTime.Now; lasaAiAchievement.TaskId = "10"; lasaAiAchievement.AiModel = "DaHuaSmokeDetection"; lasaAiAchievement.Tag = ""; lasaAiAchievement.AlgoId = ""; lasaAiAchievement.Title = "烟雾报警"; //var confidence = tag.Select(r => r.confidence).Max(); //var confidence = item.confidence; //if (confidence < 0.3) //{ // break; //} //lasaAiAchievement.ConfidenceLevel = (float)Math.Round(confidence, 2) * 100; //插入详情 LasaAiAchievementDetail lasaAiAchievementDetail = new LasaAiAchievementDetail() { Id = Guid.NewGuid().ToString(), Image = uploadedUrl, AiAchievementId = lasaAiAchievement.Id, //Lat = lat, //Lng = lng }; lasaAiAchievement.Cover = uploadedUrl; //lasaAiAchievement.Lat = (float)lat; //lasaAiAchievement.Lng = (float)lng; await db.LasaAiAchievement.InsertAsync(lasaAiAchievement); await db.LasaAiAchievementDetail.InsertAsync(lasaAiAchievementDetail); } if (db.Commit()) return new Response { Result = true, Message = "添加成功" }; else return new Response { Result = false, Message = "添加失败" }; } } /// /// 从 URL 下载图片并画框 /// public async Task DrawRectanglesOnImageAsync(string url, dynamic rects) { try { // 下载图片 //url = "http://123.132.248.154:6015/DroneEnforcement/2025/20250514/localStorage.jpg"; using var stream = await httpClient.GetStreamAsync(url); using var image = Image.FromStream(stream); using var g = Graphics.FromImage(image); using var pen = new Pen(Color.Red, 5); // 红色粗线 float scaleX = image.Width / STANDARD_WIDTH; float scaleY = image.Height / STANDARD_HEIGHT; // 画框 foreach (var rect in rects) { int x = (int)(rect.objLeft * scaleX); int y = (int)(rect.objTop * scaleY); int width = (int)((rect.objRight - rect.objLeft) * scaleX); int height = (int)((rect.objBottom - rect.objTop) * scaleY); if (x < image.Width && y < image.Height && width > 0 && height > 0) { g.DrawRectangle(pen, x, y, width, height); } } // 保存到内存流再上传 using var outputStream = new MemoryStream(); image.Save(outputStream, ImageFormat.Png); outputStream.Position = 0; string fileName = Path.GetFileName(new Uri(url).AbsolutePath); // 上传到 MinIO string uploadedUrl = await _minioService.UploadStreamFile(outputStream, fileName, "test", "yanwubaojing"); Console.WriteLine("返回 imgurl:" + uploadedUrl); return uploadedUrl; } catch (Exception ex) { Console.WriteLine($"处理图片失败: {url}, 错误: {ex.Message}"); return string.Empty; } } // 定义矩形对象 public class ObjectRect { public int objBottom { get; set; } public int objLeft { get; set; } public int objRight { get; set; } public int objTop { get; set; } } // 定义 imageList 里的结构 public class ImageInfo { public int imgHeight { get; set; } public int imgWidth { get; set; } public string imgUrl { get; set; } public List objectRect { get; set; } } public class Root { public List imageList { get; set; } } #endregion #region 本地模型 /// /// /// /// 任务id /// 图片地址 /// 算法id /// 无人机信息 /// 标签信息 /// public async Task> AddImg(string taskid, string path, string aiid, dynamic drone_info, List tag) { using (var db = UnitWork.CreateContext()) { _logger.LogError("标签信息:" + JsonConvert.SerializeObject(tag)); _logger.LogError("aiid:" + aiid); var config = ConfigHelper.GetConfigRoot(); var Ip = "http://" + config["Minio:Endpoint"] + "/" + config["Minio:BucketName"] + "/"; foreach (var item in tag) { var info = await db.LasaAiAchievement.GetFirstAsync(r => r.TaskId == taskid && r.Tag == item.class_id.ToString()); var modelinfo = await db.LasaModelLabel.AsQueryable().Where(r => r.PId == aiid).ToListAsync(); double lat = 0.0, lng = 0.0; if (drone_info != null) { //var root = JsonNode.Parse(drone_info)?.AsObject(); //lat = root?["data"]?["latitude"]?.GetValue() ?? 0.0; //lng = root?["data"]?["longitude"]?.GetValue() ?? 0.0; lat = (double?)drone_info.data?.latitude ?? 0.0; lng = (double?)drone_info.data?.longitude ?? 0.0; } if (info == null) { LasaAiAchievement lasaAiAchievement = new LasaAiAchievement(); lasaAiAchievement.Id = Guid.NewGuid().ToString(); lasaAiAchievement.CreateTime = DateTime.Now; lasaAiAchievement.TaskId = taskid; lasaAiAchievement.AiModel = "yolo12x"; lasaAiAchievement.Tag = item.class_id.ToString(); lasaAiAchievement.AlgoId = aiid; var modelid = modelinfo.Where(r => r.EnumValue == item.class_id).FirstOrDefault(); if (modelid != null) { lasaAiAchievement.Title = modelid.Name; } else { lasaAiAchievement.Title = ""; } //var confidence = tag.Select(r => r.confidence).Max(); var confidence = item.confidence; if (confidence < 0.3) { break; } lasaAiAchievement.ConfidenceLevel = (float)Math.Round(confidence, 2) * 100; //插入详情 LasaAiAchievementDetail lasaAiAchievementDetail = new LasaAiAchievementDetail() { Id = Guid.NewGuid().ToString(), //Image = "http://175.27.168.120:6013/test/" + path, Image = Ip + path, AiAchievementId = lasaAiAchievement.Id, Lat = lat, Lng = lng }; //lasaAiAchievement.Cover = "http://175.27.168.120:6013/test/" + path; lasaAiAchievement.Cover = Ip + path; lasaAiAchievement.Lat = (float)lat; lasaAiAchievement.Lng = (float)lng; await db.LasaAiAchievement.InsertAsync(lasaAiAchievement); await db.LasaAiAchievementDetail.InsertAsync(lasaAiAchievementDetail); } else { //插入详情 LasaAiAchievementDetail lasaAiAchievementDetail = new LasaAiAchievementDetail() { Id = Guid.NewGuid().ToString(), Image = Ip + path, AiAchievementId = info.Id, Lat = lat, Lng = lng }; await db.LasaAiAchievementDetail.InsertAsync(lasaAiAchievementDetail); } } #region 推送到防火平台 //await _mqttClientManager.PublishAsync("fireclueinfo", JsonConvert.SerializeObject( // new // { // ReportPerson = "", // Describe = "", // Lng = "", // La = "", // Address = "", // AreaName = "", // Image = path, // DegreeType = 3 // })); #endregion if (db.Commit()) return new Response { Result = true, Message = "添加成功" }; else return new Response { Result = false, Message = "添加失败" }; } } public async void PublishMsg(List topic, string payload) { foreach (var topicItem in topic) { await _mqttClientManager.PublishAsync(topicItem, payload); } } #endregion } }