public ClsRelevantObject MoveDown(ClsRelevantObject ro, out int NewIDX) { ClsRelevantObject ret = ro; NewIDX = 0; if (ro == null) { return(ro); } ClsRelevantObject rofound = this.Get(ro, false, out int FoundIDX, true); if (!rofound.IsNull()) { NewIDX = FoundIDX + 1; if (NewIDX < this.ObjectList.Count - 1) { this.ObjectList.Move(FoundIDX, NewIDX); this.Update(false); ret = this.ObjectList[NewIDX]; } } return(ret); }
public bool TryAdd(ClsRelevantObject ro, bool Enable, out int AddedIDX) { bool ret = false; AddedIDX = -1; if (ro.IsNull()) { return(false); } ClsRelevantObject rofound = this.Get(ro, false, out int FoundIDX, true); if (rofound.IsNull()) { ro.Priority = this.ObjectList.Count + 1; ro.Enabled = Enable; if (ro.Enabled) { this.EnabledCount++; } ro.Update(); this.ObjectList.Add(ro); AddedIDX = this.ObjectList.Count - 1; ret = true; } return(ret); }
public ClsRelevantObject Delete(ClsRelevantObject ro, out int NewIDX) { ClsRelevantObject ret = ro; NewIDX = 0; if (ro == null) { return(ro); } ClsRelevantObject rofound = this.Get(ro, false, out int FoundIDX, true); if (!rofound.IsNull()) { this.ObjectList.RemoveAt(FoundIDX); NewIDX = FoundIDX - 1; this.Update(false); if (NewIDX > -1) { ret = this.ObjectList[NewIDX]; } } return(ret); }
public bool TryDelete(ClsRelevantObject ro) { bool ret = false; if (ro.IsNull()) { return(false); } if (ObjectDict.Contains(ro.Name.ToLower())) { ObjectDict.Remove(ro.Name.ToLower()); ret = true; } return(ret); }
public void Update(bool ResetIfNeeded = true) { //sort //this.ObjectList = this.ObjectList.OrderByDescending(ro => ro.Enabled).ThenBy(ro => ro.Priority).ThenBy(ro => ro.CreatedTime).ThenBy(ro => ro.Name).ToList(); if (this.cam.IsNull()) { this.Init(); } if (ResetIfNeeded && this.ObjectList.Count == 0 && !this.CameraName.EqualsIgnoreCase("default")) { this.Reset(); } bool restrict = !this.cam.IsNull() && !this.cam.DefaultTriggeringObjects.IsNull() && this.cam.DefaultTriggeringObjects.TypeName != this.TypeName; //make sure no priority is in order and the minimum is not less than the main cameras list for (int i = 0; i < this.ObjectList.Count; i++) { if (restrict) { ClsRelevantObject ro = this.Get(this.ObjectList[i].Name, false, out int FoundIDX, UseMainCamList: true); if (!ro.IsNull()) { this.ObjectList[i].Update(ro.Threshold_lower, ro.Threshold_upper, ro.IgnoreDynamicMask, ro.IgnoreImageMask); } else { this.ObjectList[i].Update(); } } else { this.ObjectList[i].Update(); } this.ObjectList[i].Priority = i + 1; } }
public bool TryAdd(ClsRelevantObject ro, bool Enable) { bool ret = false; if (ro.IsNull()) { return(false); } if (!ObjectDict.Contains(ro.Name.ToLower())) { ro.Priority = ObjectDict.Count + 1; ro.Enabled = Enable; if (ro.Enabled) { this.EnabledCount++; } ObjectDict.Add(ro.Name.ToLower(), ro); ret = true; } 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); }
public List <ClsRelevantObject> FromString(string Objects, bool Clear, bool ExactMatchonly) { using var Trace = new Trace(); //This c# 8.0 using feature will auto dispose when the function is done. List <ClsRelevantObject> ret = new List <ClsRelevantObject>(); this.Init(); if (!this.Initialized) { return(ret); } try { if (Clear) { this.ObjectList.Clear(); this.EnabledCount = 0; } //take anything before the first semicolon: if (Objects.Contains(";")) { Objects = Objects.GetWord("", ";"); } bool AlreadyHasItems = ObjectList.Count > 0; List <string> lst = Objects.SplitStr(","); List <ClsRelevantObject> DefaultObjectList = new List <ClsRelevantObject>(); if (!this.Camera.EqualsIgnoreCase("default")) { DefaultObjectList = this.GetDefaultObjectList(false); } foreach (var obj in lst) { ClsRelevantObject ro = new ClsRelevantObject(obj); ClsRelevantObject rofound = this.Get(ro, false, out int FoundIDX, ExactMatchonly, ret); if (rofound.IsNull()) { //Only add items as enabled if we started out from an empty list if (AlreadyHasItems) { ro.Enabled = false; } if (ro.Enabled) { this.EnabledCount++; } //set the order if found in the default list ClsRelevantObject defRo = this.Get(ro, false, out int DefFoundIDX, false, DefaultObjectList); if (DefFoundIDX > -1) { ro.Priority = DefFoundIDX + 1; } else { ro.Priority = ret.Count + 1; } ret.Add(ro); } } } catch (Exception ex) { AITOOL.Log("Error: " + ex.Msg()); } return(ret); }
public List <ClsRelevantObject> FromList(List <ClsRelevantObject> InList, bool Clear, bool ExactMatchOnly) { List <ClsRelevantObject> ret = new List <ClsRelevantObject>(); if (InList.Count == 0) { return(ret); } this.Init(); if (!this.Initialized) { return(ret); } if (Clear) { this.ObjectList.Clear(); this.EnabledCount = 0; } ret.AddRange(this.ObjectList); int order = ret.Count - 1; bool AlreadyHasItems = ret.Count > 0; int dupes = 0; foreach (var ro in InList) { ClsRelevantObject rofound = this.Get(ro, false, out int FoundIDX, ExactMatchOnly, ret); if (rofound.IsNull()) { //Only add items as enabled if we started out from an empty list if (AlreadyHasItems) { ro.Enabled = false; } order++; this.EnabledCount++; ro.Priority = order; ro.Update(); ret.Add(ro.CloneJson()); } else { dupes++; } } ////force disabled items to be lower priority //foreach (var ro in InList) //{ // ClsRelevantObject rofound = this.Get(ro, false, out int FoundIDX); // if (rofound.IsNull()) // { // //Only add items as enabled if we started out from an empty list // if (!AlreadyHasItems) // ro.Enabled = true; // else // ro.Enabled = false; // if (!ro.Enabled) // { // order++; // ro.Priority = order; // ro.Update(); // ret.Add(ro); // } // } //} return(ret); }
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); }