private void Refresh() { //in case of disabled cameras: if (comboBox_filter_camera.Text != "All Cameras" && comboBox_filter_camera.Text.Trim().ToLower().Trim() != this.cam.name.Trim().ToLower()) { this.cam = AITOOL.GetCamera(comboBox_filter_camera.Text); } List <ObjectPosition> hist = new List <ObjectPosition>(); List <ObjectPosition> masked = new List <ObjectPosition>(); if (comboBox_filter_camera.Text == "All Cameras") { foreach (Camera curcam in AppSettings.Settings.CameraList) { hist.AddRange(curcam.maskManager.last_positions_history); masked.AddRange(curcam.maskManager.masked_positions); } } else { hist = cam.maskManager.last_positions_history; masked = cam.maskManager.masked_positions; } Global_GUI.UpdateFOLV(ref FOLV_MaskHistory, hist, true); Global_GUI.UpdateFOLV(ref FOLV_Masks, masked, true); this.CurObjPosLst.Clear(); ShowMaskImage(); ShowImageMask(null); }
public List <ClsRelevantObject> GetDefaultObjectList(bool Clear) { List <ClsRelevantObject> ret = this._DefaultObjectsList; //get the default camera list try { if (this.defaultcam.IsNull()) { this.defaultcam = AITOOL.GetCamera("Default", true); } if (!this.defaultcam.IsNull()) //probably here to soon { if (this.defaultcam.DefaultTriggeringObjects.ObjectList.Count > 0 && !this.Camera.EqualsIgnoreCase(this.defaultcam.Name)) { this._DefaultObjectsList = this.defaultcam.DefaultTriggeringObjects.CloneObjectList(); } else { this._DefaultObjectsList = this.FromString(AppSettings.Settings.ObjectPriority, Clear, false); } ret = this._DefaultObjectsList; } } catch (Exception ex) { AITOOL.Log($"Error: ({this.TypeName}) {ex.Msg()}"); } return(ret); }
private void Refresh() { //in case of disabled cameras: if (!string.Equals(this.comboBox_filter_camera.Text, "All Cameras", StringComparison.OrdinalIgnoreCase) && this.comboBox_filter_camera.Text.ToLower().Trim() != this.cam.Name.ToLower().Trim()) { this.cam = AITOOL.GetCamera(this.comboBox_filter_camera.Text); } List <ObjectPosition> hist = new List <ObjectPosition>(); List <ObjectPosition> masked = new List <ObjectPosition>(); if (this.comboBox_filter_camera.Text == "All Cameras") { foreach (Camera curcam in AppSettings.Settings.CameraList) { hist.AddRange(curcam.maskManager.LastPositionsHistory); masked.AddRange(curcam.maskManager.MaskedPositions); } } else { hist = this.cam.maskManager.LastPositionsHistory; masked = this.cam.maskManager.MaskedPositions; } Global_GUI.UpdateFOLV(this.FOLV_MaskHistory, hist, FullRefresh: true); Global_GUI.UpdateFOLV(this.FOLV_Masks, masked, FullRefresh: true); this.CurObjPosLst.Clear(); this.ShowMaskImage(); this.ShowImageMask(null); }
public void ShowCamera() { if (cmb_cameras.Text.Trim().EqualsIgnoreCase("all cameras")) { this.CurrentCam = AITOOL.GetCamera("default", true); } else { this.CurrentCam = AITOOL.GetCamera(cmb_cameras.Text.Trim()); } cb_paused.Checked = this.CurrentCam.Paused; if (this.CurrentCam.Paused) { cb_paused.Text = "UN-pause"; } else { cb_paused.Text = "Pause"; } tb_minutes.Text = this.CurrentCam.PauseMinutes.ToString(); cb_FileMonitoring.Checked = this.CurrentCam.PauseFileMon; cb_MQTT.Checked = this.CurrentCam.PauseMQTT; cb_Pushover.Checked = this.CurrentCam.PausePushover; cb_Telegram.Checked = this.CurrentCam.PauseTelegram; cb_URL.Checked = this.CurrentCam.PauseURL; UpdateButton(); }
private void FOLV_MaskHistory_CellRightClick(object sender, BrightIdeasSoftware.CellRightClickEventArgs e) { if (e.Model != null) { this.contextMenuPosObj = (ObjectPosition)e.Model; this.cam = AITOOL.GetCamera(this.contextMenuPosObj.CameraName); } }
public void Init(Camera cam = null) { if (!cam.IsNull()) { this.cam = cam; } if (this.cam.IsNull() && this.CameraName.IsNotEmpty()) { this.cam = AITOOL.GetCamera(this.CameraName); } if (!this.cam.IsNull()) { this.CameraName = this.cam.Name; } //dont initialize until we have a list of cameras available if (!this.Initialized || !this.ObjectDict.IsNull() && !AppSettings.Settings.CameraList.IsNull() && AppSettings.Settings.CameraList.Count > 0) { lock (ROLockObject) { //migrate from the dictionary to the list - dictionary no longer used if (!this.ObjectDict.IsNull()) { if (this.ObjectDict.Count > 0) { ObjectList.Clear(); foreach (Object item in ObjectDict.Values) { if (item is DictionaryEntry) { ClsRelevantObject ro = (ClsRelevantObject)((DictionaryEntry)item).Value; ObjectList.Add(ro.CloneJson()); } else if (item is ClsRelevantObject) { ClsRelevantObject ro = (ClsRelevantObject)item; ObjectList.Add(ro.CloneJson()); } else { AITOOL.Log($"Warn: Old object is {item.GetType().FullName}??"); } } } this.ObjectDict = null; } //Add default settings this.Initialized = true; Update(); } } }
private void comboBox_filter_camera_SelectionChangeCommitted(object sender, EventArgs e) { //I think this event only triggers when user picks something NOT when items are initially added to combobox if (!(this.comboBox_filter_camera.Text == "All Cameras")) { this.BtnDynamicMaskingSettings.Enabled = true; this.cam = AITOOL.GetCamera(this.comboBox_filter_camera.Text); } else { this.BtnDynamicMaskingSettings.Enabled = false; } this.Refresh(); }
private void FOLV_MaskHistory_SelectionChanged(object sender, EventArgs e) { this.CurObjPosLst.Clear(); if (this.FOLV_MaskHistory.SelectedObjects != null && this.FOLV_MaskHistory.SelectedObjects.Count > 0) { this.contextMenuPosObj = (ObjectPosition)this.FOLV_MaskHistory.SelectedObjects[0]; this.cam = AITOOL.GetCamera(this.contextMenuPosObj.CameraName); this.ShowMaskImage(); foreach (object obj in this.FOLV_MaskHistory.SelectedObjects) { this.CurObjPosLst.Add((ObjectPosition)obj); } } this.pictureBox1.Refresh(); }
private void FOLV_Masks_SelectionChanged(object sender, EventArgs e) { this.CurObjPosLst.Clear(); if (FOLV_Masks.SelectedObjects != null && FOLV_Masks.SelectedObjects.Count > 0) { contextMenuPosObj = (ObjectPosition)FOLV_Masks.SelectedObject; this.cam = AITOOL.GetCamera(contextMenuPosObj.cameraName); ShowMaskImage(); foreach (object obj in FOLV_Masks.SelectedObjects) { CurObjPosLst.Add((ObjectPosition)obj); } } pictureBox1.Refresh(); }
public override string ToString() { //LabelDisplayFormat = "[Detection] [[Detail]] ({0:0}%)" if (this._cam == null) { this._cam = AITOOL.GetCamera(this.Camera); } //Dont call this or we get a stack overflow! //string ret = AITOOL.ReplaceParams(this._cam, null, this._curimg, this._cam.DetectionDisplayFormat, this); string ret = this._cam.DetectionDisplayFormat; ret = Global.ReplaceCaseInsensitive(ret, "[label]", this.Label); //only gives first detection ret = Global.ReplaceCaseInsensitive(ret, "[detail]", this.Detail); ret = Global.ReplaceCaseInsensitive(ret, "[result]", this.Result.ToString()); ret = Global.ReplaceCaseInsensitive(ret, "[position]", this.PositionString()); ret = Global.ReplaceCaseInsensitive(ret, "[confidence]", this.ConfidenceString()); //if there was no detail string, clean up: ret = ret.Replace("[]", "").Replace("()", "").Replace(" ", " ").Replace(" ", " "); return(ret); }
public ResultType IsRelevant(List <ClsPrediction> preds, bool IsNew, out bool IgnoreMask, string DbgDetail = "") { using var Trace = new Trace(); //This c# 8.0 using feature will auto dispose when the function is done. ResultType ret = ResultType.UnwantedObject; IgnoreMask = false; this.Init(); if (!this.Initialized) { return(ret); } //if nothing is 'enabled' assume everything should be let through to be on the safe side (As if they passed an empty list) if (this.ObjectList.Count == 0 || this.EnabledCount == 0) //assume if no list is provided to always return relevant { return(ResultType.Relevant); } //if fred is found, the whole prediction will be ignored //triggering_objects = person, car, -FRED //found objects = person, fred if (preds != null && preds.Count > 0) { //find at least one thing in the triggered objects list in order to send string notrelevant = ""; string relevant = ""; string ignored = ""; string notenabled = ""; string nottime = ""; string nothreshold = ""; bool ignore = false; foreach (ClsPrediction pred in preds) { string label = pred.Label; if (pred.Result == ResultType.Relevant || IsNew) { ClsRelevantObject ro = this.Get(label, AllowEverything: true, out int FoundIDX); if (!ro.IsNull()) { if (ro.Enabled) { if (Global.IsTimeBetween(DateTime.Now, ro.ActiveTimeRange)) { //assume if confidence is 0 it has not been set yet (dynamic masking routine, etc) if (pred.Confidence == 0 || pred.Confidence.Round() >= ro.Threshold_lower && pred.Confidence.Round() <= ro.Threshold_upper) { ro.LastHitTime = DateTime.Now; ro.Hits++; if (!ro.Trigger) { ignore = true; if (!ignored.Contains(label)) { ignored += label + ","; } } else { ret = ResultType.Relevant; IgnoreMask = ro.IgnoreMask; if (!relevant.Contains(label)) { relevant += label + ","; } } } else { if (!nothreshold.Contains(label)) { nothreshold += label + $" ({pred.Confidence.Round()}%),"; } } } else { if (!nottime.Contains(label)) { nottime += label + ","; } } } else { if (!notenabled.Contains(label)) { notenabled += label + ","; } } } else { if (!notrelevant.Contains(label)) { notrelevant += label + ","; } } } else { if (!notrelevant.Contains(label)) { notrelevant += label + ","; } } } //Add to the main list if (this.cam == null) { this.cam = AITOOL.GetCamera(this.Camera); } if (this.defaultcam == null) { this.defaultcam = AITOOL.GetCamera("Default", true); } //always try to add the current prediction to the list (disabled) to give them the option of enabling later foreach (ClsPrediction pred in preds) { this.TryAdd(pred.Label, false, out int AddedIDX); //add it to the Current camera list (disabled) this.cam.DefaultTriggeringObjects.TryAdd(pred.Label, false, out int AddedIDX2); //add it to the default camera list (disabled) if (!this.defaultcam.IsNull()) { this.defaultcam.DefaultTriggeringObjects.TryAdd(pred.Label, false, out int AddedIDX3); } } if (ignore) { ret = ResultType.IgnoredObject; } if (!DbgDetail.IsEmpty()) { DbgDetail = $" ({DbgDetail})"; } if (relevant.IsEmpty()) { relevant = "(NONE)"; } if (notrelevant.IsEmpty()) { notrelevant = "(NONE)"; } if (ignored.IsEmpty()) { ignored = "(NONE)"; } if (notenabled.IsEmpty()) { notenabled = "(NONE)"; } if (nottime.IsEmpty()) { nottime = "(NONE)"; } if (nothreshold.IsEmpty()) { nothreshold = "(NONE)"; } string maskignore = ""; if (IgnoreMask) { maskignore = " (Mask will be ignored)"; } if (ret != ResultType.Relevant) { AITOOL.Log($"Trace: RelevantObjectManager: Skipping '{this.TypeName}{DbgDetail}' because objects were not defined to trigger, or were set to ignore: Relevant='{relevant.Trim(", ".ToCharArray())}', Irrelevant='{notrelevant.Trim(", ".ToCharArray())}', Caused ignore='{ignored.Trim(", ".ToCharArray())}', Not Enabled={notenabled.Trim(" ,".ToCharArray())}, Not Time={nottime.Trim(" ,".ToCharArray())}, No Threshold Match={nothreshold.Trim(" ,".ToCharArray())} All Triggering Objects='{this.ToString()}', {preds.Count} predictions(s), Enabled={this.EnabledCount} of {this.ObjectList.Count}"); } else { AITOOL.Log($"Trace: RelevantObjectManager: Object is valid for '{this.TypeName}{DbgDetail}' because object(s) '{relevant.Trim(", ".ToCharArray())}' were in trigger objects list '{this.ToString()}',{maskignore} Enabled={this.EnabledCount} of {this.ObjectList.Count}"); } } return(ret); }
private async void btTest_Click(object sender, EventArgs e) { this.UpdateURL(); AITOOL.UpdateAIURLs(); string pth = Global.GetRegSetting("TestImage", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestImage.jpg")); OpenFileDialog ofd = new OpenFileDialog { InitialDirectory = Path.GetDirectoryName(pth), FileName = Path.GetFileName(pth), Title = "Select test image", CheckFileExists = true, CheckPathExists = true, DefaultExt = "jpg", Filter = "jpg files (*.jpg)|*.jpg", FilterIndex = 2, RestoreDirectory = true, ShowReadOnly = true }; if (ofd.ShowDialog() == DialogResult.OK) { pth = ofd.FileName; Global.SaveRegSetting("TestImage", pth); if (File.Exists(pth)) { //must create a temp unique file every time because database key is the filename Camera cam = AITOOL.GetCamera("default", true); if (cam == null) { cam = new Camera("TEST_CAM"); } string ext = Path.GetExtension(pth); string tpth = Path.Combine(Path.GetTempPath(), $"{cam.Name}.URLTEST.{DateTime.Now:yyyy-MM-dd_HH-mm-ss-fff}{ext}"); File.Copy(pth, tpth, true); btTest.Enabled = false; bt_Save.Enabled = false; btTest.Text = "Working..."; this.UpdateURL(); ClsImageQueueItem CurImg = new ClsImageQueueItem(tpth, 0); List <ClsURLItem> linked = new List <ClsURLItem> { this.CurURL }; if (this.CurURL.LinkServerResults && !string.IsNullOrEmpty(this.CurURL.LinkedResultsServerList)) { linked.AddRange(await AITOOL.WaitForNextURL(cam, false, null, this.CurURL.LinkedResultsServerList)); } if (linked.Count > 1) { AITOOL.Log($"Debug: ---- Found '{linked.Count}' linked AI URL's."); } AITOOL.DetectObjectsResult result = await AITOOL.DetectObjects(CurImg, linked, cam); //make sure not stuck in use for the test: foreach (var url in result.OutURLs) { url.InUse.WriteFullFence(false); } btTest.Enabled = true; bt_Save.Enabled = true; btTest.Text = "Test"; if (result.Success) { Frm_ObjectDetail frm = new Frm_ObjectDetail(); frm.PredictionObjectDetails = result.OutPredictions; frm.ImageFileName = tpth; frm.Show(); MessageBox.Show($"Success! {this.CurURL.LastResultMessage}", "Success"); } else { MessageBox.Show($"Error! {this.CurURL.LastResultMessage}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } this.CurURL.ErrCount.WriteUnfenced(0); this.CurURL.CurErrCount.WriteUnfenced(0); } else { MessageBox.Show($"Test file does not exist:\r\n{pth}"); } } }
public ClsLogItm Log(string Detail, string AIServer = "", string Camera = "", string Image = "", string Source = "", int Depth = 0, LogLevel Level = null, Nullable <DateTime> Time = default(DateTime?), [CallerMemberName()] string memberName = null) { if (!this.Enabled) { return(null); } lock (this._LockObj) { this._LastIDX.AtomicIncrementAndGet(); this.LastLogItm = new ClsLogItm(); this.LastLogItm.Detail = Detail.Replace("|", ";"); this.LastLogItm.Filename = Path.GetFileName(this._Filename); this.LastLogItm.ThreadID = Thread.CurrentThread.ManagedThreadId; if (Source == null || string.IsNullOrWhiteSpace(Source)) { this.LastLogItm.Source = this._LastSource; } else { this.LastLogItm.Source = Source; } if (Camera == null || string.IsNullOrWhiteSpace(Camera)) { this.LastLogItm.Camera = this._LastCamera; } else { this.LastLogItm.Camera = Camera; if (!Camera.StartsWith("Trace-")) { this._LastCamera = Camera; } } if (AIServer == null || string.IsNullOrWhiteSpace(AIServer)) { this.LastLogItm.AIServer = this._LastAIServer; } else { this.LastLogItm.AIServer = AIServer; if (!AIServer.StartsWith("Trace-")) { this._LastAIServer = AIServer; } } if (Image == null || string.IsNullOrWhiteSpace(Image)) { this.LastLogItm.Image = this._LastImage; } else { this.LastLogItm.Image = Path.GetFileName(Image); } if (Time.HasValue) { this.LastLogItm.Date = Time.Value; } else { this.LastLogItm.Date = DateTime.Now; } if (memberName == ".ctor") { memberName = "Constructor"; } this.LastLogItm.Func = memberName.Replace("AITool.", ""); //deepstack messages spam us... bool DeepstackDebug = !string.Equals(this.LastLogItm.Func, "handleredisprocmsg", StringComparison.OrdinalIgnoreCase) || string.Equals(this.LastLogItm.Func, "handleredisprocmsg", StringComparison.OrdinalIgnoreCase) && AppSettings.Settings.deepstack_debug; if (!DeepstackDebug) { return(this.LastLogItm); } if (Level == null) { if (this.LastLogItm.Detail.IndexOf("fatal:", StringComparison.OrdinalIgnoreCase) >= 0) { Level = LogLevel.Fatal; } else if (this.LastLogItm.Detail.IndexOf("error:", StringComparison.OrdinalIgnoreCase) >= 0) { Level = LogLevel.Error; } else if (this.LastLogItm.Detail.IndexOf("warning:", StringComparison.OrdinalIgnoreCase) >= 0 || this.LastLogItm.Detail.IndexOf("warn:", StringComparison.OrdinalIgnoreCase) >= 0) { Level = LogLevel.Warn; } else if (this.LastLogItm.Detail.IndexOf("info:", StringComparison.OrdinalIgnoreCase) >= 0) { Level = LogLevel.Info; } else if (this.LastLogItm.Detail.IndexOf("debug:", StringComparison.OrdinalIgnoreCase) >= 0) { Level = LogLevel.Debug; } else if (this.LastLogItm.Detail.IndexOf("trace:", StringComparison.OrdinalIgnoreCase) >= 0) { Level = LogLevel.Trace; } else { Level = LogLevel.Info; } } bool HasError = false; //remove tags if (Level == LogLevel.Error) { this.ErrorCount.AtomicIncrementAndGet(); HasError = true; this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "error:", ""); } else if (Level == LogLevel.Fatal) { this.ErrorCount.AtomicIncrementAndGet(); HasError = true; this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "fatal:", ""); } else if (Level == LogLevel.Warn) { this.ErrorCount.AtomicIncrementAndGet(); HasError = true; this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "warn:", ""); this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "warning:", ""); } else if (Level == LogLevel.Info) { this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "info:", ""); } else if (Level == LogLevel.Trace) { this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "trace:", ""); } else if (Level == LogLevel.Debug) { this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "debug:", ""); } if (this.LastLogItm.Detail.TrimStart().StartsWith("{")) { this.LastLogItm.Color = this.LastLogItm.Detail.GetWord("{", "}"); //strip out the color definition this.LastLogItm.Detail = Global.ReplaceCaseInsensitive(this.LastLogItm.Detail, "{" + this.LastLogItm.Color + "}", ""); } //clean out any whitespace //this.LastLogItm.Detail = this.LastLogItm.Detail.TrimStart(); if (this._CurDepth.ReadFullFence() + Depth > 0) { this.LastLogItm.Detail = new string(' ', (this._CurDepth.ReadFullFence() + Depth * 2)) + this.LastLogItm.Detail; } this.LastLogItm.Depth = this._CurDepth.ReadFullFence() + Depth; this.LastLogItm.Level = Level; this.LastLogItm.Idx = this._LastIDX.ReadFullFence(); if (this._Store) { if (Level >= this.MinLevel) { this.Values.Add(this.LastLogItm); this.RecentlyAdded.Enqueue(this.LastLogItm); //keep the log list size down if (this.Values.Count > this.MaxGUILogItems) { this.RecentlyDeleted.Enqueue(this.Values[0]); this.Values.RemoveAt(0); } } } this.NLogFileWriter.Log(Level, this.LastLogItm.ToString()); if (Debugger.IsAttached) { Console.WriteLine(this.LastLogItm.ToDetailString()); } string itm = this.LastLogItm.ToString(); //Send telegram error message if (AppSettings.Settings.send_telegram_errors && (HasError) && AppSettings.Settings.telegram_chatids.Count > 0 && AITOOL.TriggerActionQueue != null && !(itm.IndexOf("telegram", StringComparison.OrdinalIgnoreCase) >= 0) && !(itm.IndexOf("addtriggeraction", StringComparison.OrdinalIgnoreCase) >= 0)) { //await TelegramText($"[{time}]: {text}"); //upload text to Telegram Camera cam = AITOOL.GetCamera(this._LastCamera); AITOOL.TriggerActionQueue.AddTriggerActionAsync(TriggerType.TelegramText, cam, null, null, true, false, null, this.LastLogItm.ToDetailString()); } //Send pushover error message if (AppSettings.Settings.send_pushover_errors && (HasError) && !string.IsNullOrEmpty(AppSettings.Settings.pushover_APIKey) && !string.IsNullOrEmpty(AppSettings.Settings.pushover_UserKey) && AITOOL.TriggerActionQueue != null && !(itm.IndexOf("pushover", StringComparison.OrdinalIgnoreCase) >= 0) && !(itm.IndexOf("addtriggeraction", StringComparison.OrdinalIgnoreCase) >= 0)) { Camera cam = AITOOL.GetCamera(this._LastCamera); AITOOL.TriggerActionQueue.AddTriggerActionAsync(TriggerType.Pushover, cam, null, null, true, false, null, this.LastLogItm.ToDetailString()); } if (HasError) { NLog.LogManager.Flush(); } } return(this.LastLogItm); }
public ResultType IsRelevant(List <ClsPrediction> preds, bool IsNew, out bool IgnoreImageMask, out bool IgnoreDynamicMask, string DbgDetail = "") { using var Trace = new Trace(); //This c# 8.0 using feature will auto dispose when the function is done. ResultType ret = ResultType.UnwantedObject; IgnoreImageMask = false; IgnoreDynamicMask = false; this.Init(); if (!this.Initialized) { return(ret); } //if nothing is 'enabled' assume everything should be let through to be on the safe side (As if they passed an empty list) if (this.ObjectList.Count == 0 || this.EnabledCount == 0) //assume if no list is provided to always return relevant { AITOOL.Log($"Debug: RelevantObjectManager: Allowing '{this.TypeName}{DbgDetail}' because no relevant objects were enabled. {preds.Count} predictions(s), Enabled={this.EnabledCount} of {this.ObjectList.Count}"); return(ResultType.Relevant); } //if fred is found, the whole prediction will be ignored //triggering_objects = person, car, -FRED //found objects = person, fred if (preds != null && preds.Count > 0) { //find at least one thing in the triggered objects list in order to send string notrelevant = ""; string relevant = ""; string ignored = ""; string unknownobject = ""; string notenabled = ""; string nottime = ""; string nothreshold = ""; string percentsizewrong = ""; bool ignore = false; foreach (ClsPrediction pred in preds) { string label = pred.Label; if (pred.Result == ResultType.Relevant || IsNew) { ClsRelevantObject ro = this.Get(label, AllowEverything: true, out int FoundIDX); if (!ro.IsNull()) { //Add the PercentOfImage size stats in any case: if (pred.Confidence == 0 || pred.Confidence.Round() >= ro.Threshold_lower) { ro.PercentSizeStats.AddToCalc(pred.PercentOfImage); ro.HeightStats.AddToCalc(pred.RectHeight); ro.WidthStats.AddToCalc(pred.RectWidth); } if (ro.Enabled) { if (Global.IsTimeBetween(DateTime.Now, ro.ActiveTimeRange)) { //assume if confidence is 0 it has not been set yet (dynamic masking routine, etc) if (pred.Confidence == 0 || pred.Confidence.Round() >= ro.Threshold_lower && pred.Confidence.Round() <= ro.Threshold_upper) { if (pred.PercentOfImage.Round() >= ro.PredSizeMinPercentOfImage && pred.PercentOfImage.Round() <= ro.PredSizeMaxPercentOfImage) { ro.LastHitTime = DateTime.Now; ro.Hits++; if (!ro.Trigger) { ignore = true; if (!ignored.Contains(label)) { ignored += label + ","; } } else { ret = ResultType.Relevant; pred.ObjectResult = ResultType.Relevant; IgnoreImageMask = ro.IgnoreImageMask; if (ro.IgnoreDynamicMask.HasValue) { IgnoreDynamicMask = ro.IgnoreDynamicMask.Value; } if (!relevant.Contains(label)) { relevant += label + ","; } } } else { if (pred.Confidence.Round() < ro.Threshold_lower) { pred.ObjectResult = ResultType.TooSmallPercent; } else if (pred.Confidence.Round() > ro.Threshold_upper) { pred.ObjectResult = ResultType.TooLargePercent; } if (!percentsizewrong.Contains(label)) { percentsizewrong += label + $" ({pred.PercentOfImage.Round()}%),"; } } } else { pred.ObjectResult = ResultType.NoConfidence; if (!nothreshold.Contains(label)) { nothreshold += label + $" ({pred.Confidence.Round()}%),"; } } } else { pred.ObjectResult = ResultType.NotInTimeRange; if (!nottime.Contains(label)) { nottime += label + ","; } } } else { pred.ObjectResult = ResultType.NotEnabled; if (!notenabled.Contains(label)) { notenabled += label + ","; } } } else { pred.ObjectResult = ResultType.UnknownObject; if (!unknownobject.Contains(label)) { unknownobject += label + ","; } } } else { pred.ObjectResult = pred.Result; if (!notrelevant.Contains(label)) { notrelevant += label + ","; } } } //Add to the main list if (this.cam == null) { this.cam = AITOOL.GetCamera(this.CameraName); } if (this.defaultcam == null) { this.defaultcam = AITOOL.GetCamera("Default", true); } //always try to add the current prediction to the list (disabled) to give them the option of enabling later foreach (ClsPrediction pred in preds) { this.TryAdd(pred.Label, false, out int AddedIDX); //add it to the Current camera list (disabled) this.cam.DefaultTriggeringObjects.TryAdd(pred.Label, false, out int AddedIDX2); //add it to the default camera list (disabled) if (!this.defaultcam.IsNull()) { this.defaultcam.DefaultTriggeringObjects.TryAdd(pred.Label, false, out int AddedIDX3); } } if (ignore) { ret = ResultType.IgnoredObject; } if (!DbgDetail.IsEmpty()) { DbgDetail = $" ({DbgDetail})"; } if (!relevant.IsEmpty()) { relevant = $"Relevant='{relevant.Trim(", ".ToCharArray())}',"; } if (!notrelevant.IsEmpty()) { notrelevant = $"Irrelevant='{notrelevant.Trim(", ".ToCharArray())}',"; } if (!ignored.IsEmpty()) { ignored = $"Caused ignore='{ignored.Trim(", ".ToCharArray())}',"; } if (!notenabled.IsEmpty()) { notenabled = $"Not Enabled={notenabled.Trim(" ,".ToCharArray())},"; } if (!nottime.IsEmpty()) { nottime = $"Not Time={nottime.Trim(" ,".ToCharArray())},"; } if (!nothreshold.IsEmpty()) { nothreshold = $"No Threshold Match='{nothreshold.Trim(" ,".ToCharArray())}',"; } if (!percentsizewrong.IsEmpty()) { percentsizewrong = $"Percent Size wrong='{percentsizewrong.Trim(" ,".ToCharArray())}',"; } if (!unknownobject.IsEmpty()) { unknownobject = $"Unknown Object='{unknownobject.Trim(" ,".ToCharArray())}',"; } ; string maskignore = ""; if (IgnoreImageMask) { maskignore = " (Mask will be ignored)"; } if (ret != ResultType.Relevant) { AITOOL.Log($"Debug: RelevantObjectManager: Skipping '{this.TypeName}{DbgDetail}' because: {notrelevant}{ignored}{notenabled}{nottime}{nothreshold}{percentsizewrong}{unknownobject}{relevant}. {maskignore}, {preds.Count} predictions(s), Enabled={this.EnabledCount} of {this.ObjectList.Count}, IsNew={IsNew}"); } else { AITOOL.Log($"Debug: RelevantObjectManager: Object is valid for '{this.TypeName}{DbgDetail}' because: {relevant}{notrelevant}{ignored}{notenabled}{nottime}{nothreshold}{percentsizewrong}{unknownobject}. {maskignore}, {preds.Count} predictions(s), Enabled={this.EnabledCount} of {this.ObjectList.Count}, IsNew={IsNew}"); } } else { AITOOL.Log($"Debug: RelevantObjectManager: Skipping '{this.TypeName}{DbgDetail}' because there were no PREDICTIONS."); } return(ret); }