Beispiel #1
0
        public void CleanActionNetworkFolder()
        {
            if (this.Action_image_copy_enabled &&
                !string.IsNullOrWhiteSpace(this.Action_network_folder) &&
                this.Action_network_folder_purge_older_than_days > 0 &&
                LastJPGCleanDay != DateTime.Now.DayOfYear &&
                Directory.Exists(this.Action_network_folder))
            {
                AITOOL.Log($"Debug: Cleaning out jpg files older than '{this.Action_network_folder_purge_older_than_days}' days in '{this.Action_network_folder}'...");

                List <FileInfo> filist  = new List <FileInfo>(Global.GetFiles(this.Action_network_folder, "*.jpg"));
                int             deleted = 0;
                int             errs    = 0;
                foreach (FileInfo fi in filist)
                {
                    if ((DateTime.Now - fi.LastWriteTime).TotalDays > this.Action_network_folder_purge_older_than_days)
                    {
                        try { fi.Delete(); deleted++; }
                        catch { errs++; }
                    }
                }
                if (errs == 0)
                {
                    AITOOL.Log($"Debug: ...Deleted {deleted} out of {filist.Count} files");
                }
                else
                {
                    AITOOL.Log($"Debug: ...Deleted {deleted} out of {filist.Count} files with {errs} errors.");
                }

                LastJPGCleanDay = DateTime.Now.DayOfYear;
            }
        }
        private void SelectionChanged()
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.
            try
            {
                if (this.FOLV_RelevantObjects.SelectedObjects != null && this.FOLV_RelevantObjects.SelectedObjects.Count > 0)
                {
                    ////save the last one just in case
                    this.SaveRO();

                    //set current selected object
                    this.ro = (ClsRelevantObject)this.FOLV_RelevantObjects.SelectedObjects[0];

                    //enable toolstrip buttons
                    toolStripButtonDelete.Enabled = true;
                    toolStripButtonDown.Enabled   = true;
                    toolStripButtonUp.Enabled     = true;
                }
                else
                {
                    toolStripButtonDelete.Enabled = false;
                    toolStripButtonDown.Enabled   = false;
                    toolStripButtonUp.Enabled     = false;
                    this.ro = null;
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Msg()}");
            }

            LoadRO();
        }
        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 SaveRO([CallerMemberName()] string memberName = null)
 {
     using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.
     try
     {
         if (!Loading && NeedsSaving && !this.ro.IsNull() && this.tb_Name.Enabled && !this.tb_Name.Text.IsEmpty())
         {
             this.ro.Enabled         = this.cb_enabled.Checked;
             this.ro.Name            = this.tb_Name.Text;
             this.ro.ActiveTimeRange = this.tb_Time.Text;
             this.ro.Threshold_lower = this.tb_ConfidenceLower.Text.ToDouble();
             this.ro.Threshold_upper = this.tb_ConfidenceUpper.Text.ToDouble();
             this.ro.Trigger         = this.rb_trigger.Checked;
             this.FOLV_RelevantObjects.Refresh();
         }
     }
     catch (Exception ex)
     {
         AITOOL.Log("Error: " + ex.Msg());
     }
     finally
     {
         NeedsSaving = false;
     }
 }
Beispiel #5
0
        private void FaceSelectionChanged()
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.
            try
            {
                if (this.FOLV_Faces.SelectedObjects != null && this.FOLV_Faces.SelectedObjects.Count > 0)
                {
                    //set current selected object
                    ClsFace face = (ClsFace)this.FOLV_Faces.SelectedObjects[0];

                    string mainface = Path.Combine(face.FaceStoragePath, $"{face.Name}.jpg");
                    if (File.Exists(mainface))
                    {
                        pictureBoxCurrentFace.BackgroundImage = Image.FromFile(mainface);
                    }
                    else
                    {
                        pictureBoxCurrentFace.BackgroundImage = null;
                    }

                    Global_GUI.UpdateFOLV(FOLV_FaceFiles, face.Files.Values.ToList(), FullRefresh: true);
                }
                else
                {
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Msg()}");
            }
        }
Beispiel #6
0
 public void Resume()
 {
     this.Paused               = false;
     this.ResumeTime           = DateTime.MinValue;
     this._pauseTimer.Elapsed -= ev;
     this._pauseTimer.Stop();
     AITOOL.Log($"Debug: Resuming paused camera '{this.Name}' after '{this.PauseMinutes}' minutes. ");
 }
        private void LoadRO([CallerMemberName()] string memberName = null)
        {
            Loading = true;

            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.
            try
            {
                if (this.ro.IsNull())
                {
                    this.cb_enabled.Checked      = false;
                    this.cb_enabled.Enabled      = false;
                    this.tb_Name.Text            = "";
                    this.tb_Time.Text            = "";
                    this.tb_ConfidenceLower.Text = "";
                    this.tb_ConfidenceUpper.Text = "";
                }
                else
                {
                    this.cb_enabled.Checked      = this.ro.Enabled;
                    this.cb_enabled.Enabled      = true;
                    this.tb_Name.Text            = this.ro.Name;
                    this.tb_Time.Text            = this.ro.ActiveTimeRange;
                    this.tb_ConfidenceLower.Text = this.ro.Threshold_lower.ToString();
                    this.tb_ConfidenceUpper.Text = this.ro.Threshold_upper.ToString();

                    if (this.tb_Name.Text.EqualsIgnoreCase("NEW OBJECT") || this.tb_Name.Text.IsEmpty())
                    {
                        this.tb_Name.Enabled = true;
                    }
                    else
                    {
                        this.tb_Name.Enabled = false;
                    }

                    if (this.ro.Trigger)
                    {
                        rb_trigger.Checked = true;
                        rb_ignore.Checked  = false;
                    }
                    else
                    {
                        rb_trigger.Checked = false;
                        rb_ignore.Checked  = true;
                    }
                }

                Global_GUI.GroupboxEnableDisable(groupBox1, cb_enabled);
            }
            catch (Exception ex)
            {
                AITOOL.Log("Error: " + ex.Msg());
            }
            finally
            {
                NeedsSaving = false;
                Loading     = false;
            }
        }
        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();
                }
            }
        }
Beispiel #9
0
 public void Pause()
 {
     this.Paused               = true;
     this.ResumeTime           = DateTime.Now.AddMinutes(this.PauseMinutes);
     this._pauseTimer.Interval = 1000;
     //register event handler to run clean history every minute
     ev = new System.Timers.ElapsedEventHandler(this.PauseEvent);
     this._pauseTimer.Elapsed += ev;
     this._pauseTimer.Start();
     AITOOL.Log($"Debug: Camera '{this.Name}' paused for '{this.PauseMinutes}' minutes until '{this.ResumeTime}'.");
 }
Beispiel #10
0
        private async Task <PushoverUserResponse> PushoverPost(Uri uri, MultipartFormDataContent parameters)
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.

            PushoverUserResponse ret = new PushoverUserResponse();

            if (this.httpClient == null)
            {
                this.httpClient         = new HttpClient();
                this.httpClient.Timeout = TimeSpan.FromSeconds(AppSettings.Settings.HTTPClientRemoteTimeoutSeconds);
            }

            // Remove content type that is not in the docs
            //foreach (HttpContent param in parameters)
            //    param.Headers.ContentType = null;

            try
            {
                HttpResponseMessage response = null;
                string json = "";

                response = await httpClient.PostAsync(uri, parameters);

                json = await response.Content.ReadAsStringAsync();

                json = json.CleanString();

                if (response.IsSuccessStatusCode && !string.IsNullOrWhiteSpace(json))
                {
                    //var json = this.Encoding.GetString(await wc.UploadValuesTaskAsync(uri, parameters).ConfigureAwait(false));
                    ret = await ParseResponse <PushoverUserResponse>(json, response.Headers);
                }
                else
                {
                    if (response.StatusCode.ToString().Contains("TooLarge"))
                    {
                        ret.Errors = new string[] { $"StatusCode='{response.StatusCode}', Reason='{response.ReasonPhrase}' (Max pushover attachment size is 2.5MB), ResponseText='{json}'" };
                    }
                    else
                    {
                        ret.Errors = new string[] { $"StatusCode='{response.StatusCode}', Reason='{response.ReasonPhrase}', ResponseText='{json}'" };
                    }
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Msg()}");
                ret.Errors = new string[] { ex.Msg() };
            }

            return(ret);
        }
 private void btnSave_Click(object sender, EventArgs e)
 {
     using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.
     try
     {
         //this.Save();
         this.DialogResult = DialogResult.OK;
         this.Close();
     }
     catch (Exception ex)
     {
         AITOOL.Log("Error: " + ex.Msg());
     }
 }
Beispiel #12
0
        public void UpdateTriggeringObjects()
        {
            try
            {
                //Convert string Triggering objects to RelevantObjectManager instances
                if (this.DefaultTriggeringObjects == null || !this.triggering_objects_as_string.IsEmpty() || !this.additional_triggering_objects_as_string.IsEmpty())
                {
                    this.DefaultTriggeringObjects                = new ClsRelevantObjectManager(this.triggering_objects_as_string + "," + this.additional_triggering_objects_as_string, "Default", this);
                    this.triggering_objects_as_string            = "";
                    this.additional_triggering_objects_as_string = "";
                }
                else  //force the camera name to stay correct if renamed
                {
                    this.DefaultTriggeringObjects.Init(this);
                }

                if (this.TelegramTriggeringObjects == null || !this.telegram_triggering_objects.IsEmpty())
                {
                    this.TelegramTriggeringObjects   = new ClsRelevantObjectManager(this.telegram_triggering_objects, "Telegram", this);
                    this.telegram_triggering_objects = "";
                }
                else  //force the camera name to stay correct if renamed
                {
                    this.TelegramTriggeringObjects.Init(this);
                }

                if (this.PushoverTriggeringObjects == null || !this.telegram_triggering_objects.IsEmpty())
                {
                    this.PushoverTriggeringObjects          = new ClsRelevantObjectManager(this.Action_pushover_triggering_objects, "Pushover", this);
                    this.Action_pushover_triggering_objects = "";
                }
                else  //force the camera name to stay correct if renamed
                {
                    this.PushoverTriggeringObjects.Init(this);
                }

                if (this.MQTTTriggeringObjects == null)
                {
                    this.MQTTTriggeringObjects = new ClsRelevantObjectManager(AppSettings.Settings.ObjectPriority, "MQTT", this);
                }
                else  //force the camera name to stay correct if renamed
                {
                    this.MQTTTriggeringObjects.Init(this);
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: While updating camera '{this.Name}', got error: {ex.Msg()}");
            }
        }
        private void FillCombo()
        {
            try
            {
                toolStripComboBoxCameras.Items.Clear();
                int idx = 0;
                int fnd = -1;
                foreach (Camera cam in AppSettings.Settings.CameraList)
                {
                    foreach (PropertyInfo prop in cam.GetType().GetProperties())
                    {
                        if (prop.PropertyType == typeof(ClsRelevantObjectManager))
                        {
                            ClsRelevantObjectManager rom = (ClsRelevantObjectManager)prop.GetValue(cam);
                            string item = $"{cam.Name}\\{rom.TypeName}";
                            toolStripComboBoxCameras.Items.Add(item);
                            if (item.EqualsIgnoreCase(this.ROMName))
                            {
                                fnd = idx;
                            }
                            idx++;
                        }
                    }
                    string item2 = $"{cam.Name}\\{cam.maskManager.MaskTriggeringObjects.TypeName}";
                    toolStripComboBoxCameras.Items.Add(item2);
                    if (item2.EqualsIgnoreCase(this.ROMName))
                    {
                        fnd = idx;
                    }
                    idx++;
                }

                if (fnd != -1)
                {
                    toolStripComboBoxCameras.SelectedIndex = fnd;
                }
                else if (idx > 0)
                {
                    toolStripComboBoxCameras.SelectedIndex = 0;
                }

                this.Text = $"Relevant Objects - {this.ROMName}";
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Message}");
            }
        }
        public bool CopyFileTo(string outputFilePath)
        {
            bool ret = false;

            int bufferSize = 1024 * 1024;

            try
            {
                if (this.IsValid())  //loads into memory if not already loaded
                {
                    DirectoryInfo d = new DirectoryInfo(Path.GetDirectoryName(outputFilePath));
                    if (d.Root != null && !d.Exists)
                    {
                        //dont try to create if working off root drive
                        d.Create();
                    }
                    Stream inStream = this.ToStream();

                    if (File.Exists(outputFilePath))
                    {
                        File.Delete(outputFilePath);
                    }

                    using (FileStream fileStream = new FileStream(outputFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        fileStream.SetLength(inStream.Length);
                        int    bytesRead = -1;
                        byte[] bytes     = new byte[bufferSize];

                        while ((bytesRead = inStream.Read(bytes, 0, bufferSize)) > 0)
                        {
                            fileStream.Write(bytes, 0, bytesRead);
                        }
                    }
                    ret = true;
                }
                else
                {
                    AITOOL.Log($"Error: File not valid: {this.image_path}");
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: Copying to {outputFilePath}: {Global.ExMsg(ex)}");
            }

            return(ret);
        }
        private void SetROM()
        {
            try
            {
                if (this.ROMName.IsEmpty())
                {
                    return;
                }

                this.TempObjectManager = null;

                foreach (Camera cam in AppSettings.Settings.CameraList)
                {
                    foreach (PropertyInfo prop in cam.GetType().GetProperties())
                    {
                        if (prop.PropertyType == typeof(ClsRelevantObjectManager))
                        {
                            ClsRelevantObjectManager rom = (ClsRelevantObjectManager)prop.GetValue(cam);
                            if ($"{cam.Name}\\{rom.TypeName}".EqualsIgnoreCase(this.ROMName))
                            {
                                this.TempObjectManager = rom;
                                break;
                            }
                        }
                    }

                    string item = $"{cam.Name}\\{cam.maskManager.MaskTriggeringObjects.TypeName}";
                    if (item.EqualsIgnoreCase(this.ROMName))
                    {
                        this.TempObjectManager = cam.maskManager.MaskTriggeringObjects;
                        break;
                    }
                }

                if (this.TempObjectManager.IsNull())
                {
                    MessageBox.Show($"Error: Could not match '{this.ROMName}' to existing RelevantObjectManager?");
                }
                else
                {
                    this.TempObjectManager.Update();
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Message}");
            }
        }
Beispiel #16
0
        public void FromString(string Objects)
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.

            try
            {
                //take anything before the first semicolon:
                if (Objects.Contains(";"))
                {
                    Objects = Objects.GetWord("", ";");
                }

                this.EnabledCount = 0;
                int order = 0;

                List <string> lst    = Objects.SplitStr(",");
                List <string> deflst = AppSettings.Settings.ObjectPriority.ToLower().SplitStr(",");

                foreach (var obj in lst)
                {
                    ClsRelevantObject ro = new ClsRelevantObject(obj);

                    if (!ObjectDict.Contains(ro.Name.ToLower()))
                    {
                        if (ro.Enabled)
                        {
                            this.EnabledCount++;
                        }

                        order = deflst.IndexOf(ro.Name.ToLower());

                        if (order > -1)
                        {
                            ro.Priority = order + 1;
                        }

                        ObjectDict.Add(ro.Name.ToLower(), ro);
                    }
                }

                AddDefaults();
            }
            catch (Exception ex)
            {
                AITOOL.Log("Error: " + ex.Msg());
            }
        }
        private void FOLV_AIServers_SelectionChanged(object sender, EventArgs e)
        {
            try
            {
                if (this.FOLV_AIServers.SelectedObjects != null && this.FOLV_AIServers.SelectedObjects.Count > 0)
                {
                    this.CurURL = (ClsURLItem)this.FOLV_AIServers.SelectedObjects[0];
                }
                else
                {
                    this.CurURL = null;
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Msg()}");
            }

            UpdateButtons();
        }
        private void SaveRO([CallerMemberName()] string memberName = null)
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.
            try
            {
                if (!Loading && NeedsSaving && !this.ro.IsNull() && !this.tb_Name.Text.IsEmpty())
                {
                    this.ro.Enabled           = this.cb_enabled.Checked;
                    this.ro.Name              = this.tb_Name.Text;
                    this.ro.ActiveTimeRange   = this.tb_Time.Text;
                    this.ro.Trigger           = this.cb_ObjectTriggers.Checked;
                    this.ro.IgnoreImageMask   = this.cb_ObjectIgnoreImageMask.Checked;
                    this.ro.IgnoreDynamicMask = this.cb_ObjectIgnoreDynamicMask.Checked;
                    double lower = this.tb_ConfidenceLower.Text.ToDouble();
                    double upper = this.tb_ConfidenceUpper.Text.ToDouble();
                    //if (!this.TempObjectManager.TypeName.EqualsIgnoreCase("default"))
                    //{
                    //    ClsRelevantObject ro = this.TempObjectManager.Get(this.ro.Name, false, out int FoundIDX, UseMainCamList: true);
                    //    if (!ro.IsNull() && lower < ro.Threshold_lower || upper > ro.Threshold_upper)
                    //    {
                    //        MessageBox.Show($"The threshold cannot be lower or higher than {this.TempObjectManager.CameraName}\\Default setting: ({ro.Threshold_lower}-{ro.Threshold_upper}%)");
                    //        return;
                    //    }
                    //}
                    this.ro.Threshold_lower = lower;
                    this.ro.Threshold_upper = upper;

                    this.ro.PredSizeMinPercentOfImage = tb_MinPercent.Text.ToDouble();
                    this.ro.PredSizeMaxPercentOfImage = tb_maxpercent.Text.ToDouble();
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log("Error: " + ex.Msg());
            }
            finally
            {
                this.FOLV_RelevantObjects.Refresh();
                NeedsSaving = false;
            }
        }
        public MemoryStream ToStream()
        {
            MemoryStream ms = new MemoryStream();

            if (this.IsValid())
            {
                try
                {
                    ms = new MemoryStream(this.ImageByteArray, false);
                }
                catch (Exception ex)
                {
                    AITOOL.Log($"Error: Cannot convert to MemoryStream: {ex.Message}");
                }
            }
            else
            {
                AITOOL.Log($"Error: Cannot convert to MemoryStream because image is not valid.");
            }
            return(ms);
        }
        private void SaveROM()
        {
            try
            {
                if (this.ROMName.IsEmpty())
                {
                    return;
                }


                foreach (Camera cam in AppSettings.Settings.CameraList)
                {
                    foreach (PropertyInfo prop in cam.GetType().GetProperties())
                    {
                        if (prop.PropertyType == typeof(ClsRelevantObjectManager))
                        {
                            ClsRelevantObjectManager rom = (ClsRelevantObjectManager)prop.GetValue(cam);
                            if ($"{cam.Name}\\{rom.TypeName}".EqualsIgnoreCase(this.ROMName))
                            {
                                rom.ObjectList = this.TempObjectManager.ObjectList;
                                //rom = this.TempObjectManager;
                                break;
                            }
                        }
                    }

                    string item = $"{cam.Name}\\{cam.maskManager.MaskTriggeringObjects.TypeName}";
                    if (item.EqualsIgnoreCase(this.ROMName))
                    {
                        cam.maskManager.MaskTriggeringObjects.ObjectList = this.TempObjectManager.ObjectList;
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Message}");
            }
        }
        private void btnSave_Click(object sender, EventArgs e)
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.
            try
            {
                SaveRO();

                List <ClsRelevantObject> rolist = new List <ClsRelevantObject>();
                foreach (ClsRelevantObject ro in FOLV_RelevantObjects.Objects)
                {
                    rolist.Add(ro);
                }

                this.ObjectManager.FromList(rolist);

                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            catch (Exception ex)
            {
                AITOOL.Log("Error: " + ex.Msg());
            }
        }
        private void UpdateMaskFile()
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.

            try
            {
                this._maskfilename = this.Cam.GetMaskFile(false, null, this._imageRes);
                this.Text          = "Custom Masking - " + this._maskfilename;

                if (!File.Exists(this._maskfilename))
                {
                    this.Text += " (Missing)";
                }

                this.BrushSize          = this.Cam.mask_brush_size;
                this.numBrushSize.Value = this.Cam.mask_brush_size;
                this.ShowImage();
            }
            catch (Exception ex)
            {
                AITOOL.Log($"Error: {ex.Msg()}");
            }
        }
Beispiel #23
0
        public MemoryStream ToStream()
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.

            MemoryStream ms = new MemoryStream();

            if (this.IsValid())
            {
                try
                {
                    ms = new MemoryStream(this.ImageByteArray, false);
                    ms.Flush();
                }
                catch (Exception ex)
                {
                    AITOOL.Log($"Error: Cannot convert to MemoryStream: {ex.Message}");
                }
            }
            else
            {
                AITOOL.Log($"Error: Cannot convert to MemoryStream because image is not valid.");
            }
            return(ms);
        }
        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 void Reset()
 {
     AITOOL.Log($"Using Relevant Objects list from the 'Default' camera for {this.TypeName} RelevantObjectManager.");
     this.ObjectList = this.GetDefaultObjectList(true);
 }
Beispiel #27
0
        public bool UpdateIsValid()
        {
            bool ret = false;

            this.UrlFixed = false;

            Uri uri = null;

            if (this.Type == URLTypeEnum.DOODS)
            {
                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "http://" + this.url;
                }

                if (!(this.url.IndexOf("/detect", StringComparison.OrdinalIgnoreCase) >= 0))
                {
                    this.UrlFixed = true;
                    this.url      = this.url + "/detect";
                }

                if (Global.IsValidURL(this.url) && this.url.IndexOf("/detect", StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    uri = new Uri(this.url);
                    if (uri.Port > 0)
                    {
                        ret = true;
                        this.IsLocalHost = Global.IsLocalHost(uri.Host);
                        if (this.IsLocalHost)
                        {
                            if (this.IsLocalHost)
                            {
                                //force it to always be 127.0.0.1 for localhost
                                uri      = new Uri($"{uri.Scheme}://127.0.0.1:{uri.Port}{uri.PathAndQuery}");
                                this.url = uri.ToString();
                            }
                        }
                    }
                }
            }
            else if (this.Type == URLTypeEnum.AWSRekognition)
            {
                this.IsLocalHost = false;
                if (this.url.Equals("amazon", StringComparison.OrdinalIgnoreCase))
                {
                    ret = true;
                }
            }
            else if (this.Type == URLTypeEnum.SightHound_Person)
            {
                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "https://" + this.url;
                }

                bool hasdet = this.url.IndexOf("/v1/detections", StringComparison.OrdinalIgnoreCase) >= 0;
                bool hasrec = this.url.IndexOf("/v1/recognition", StringComparison.OrdinalIgnoreCase) >= 0;

                if (!hasdet)
                {
                    this.UrlFixed = true;
                    this.url      = this.url + "/v1/recognition?objectType=vehicle,licenseplate";
                }

                if (Global.IsValidURL(this.url) && hasdet && !hasrec)
                {
                    ret = true;
                }
            }
            else if (this.Type == URLTypeEnum.SightHound_Vehicle)
            {
                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "https://" + this.url;
                }

                bool hasdet = this.url.IndexOf("/v1/detections", StringComparison.OrdinalIgnoreCase) >= 0;
                bool hasrec = this.url.IndexOf("/v1/recognition", StringComparison.OrdinalIgnoreCase) >= 0;

                if (!hasrec)
                {
                    this.UrlFixed = true;
                    this.url      = this.url + "/v1/detections?type=face,person&faceOption=gender,landmark,age,pose,emotion";
                }

                if (Global.IsValidURL(this.url) && hasrec && !hasdet)
                {
                    ret = true;
                }
            }
            else // assume deepstack
            {
                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "http://" + this.url.Trim();
                }


                bool hasdet = this.url.IndexOf("/v1/vision/detection", StringComparison.OrdinalIgnoreCase) >= 0;
                bool hascus = this.url.IndexOf("/v1/vision/custom", StringComparison.OrdinalIgnoreCase) >= 0;

                if (!hasdet && !hascus)
                {
                    this.UrlFixed = true;
                    this.url      = this.url.Trim() + ":80/v1/vision/detection";
                }
                ///v1/vision/custom/catsanddogs
                if (Global.IsValidURL(this.url) && (hasdet || hascus))
                {
                    uri = new Uri(this.url);
                    if (uri.Port > 0)
                    {
                        ret = true;
                        this.IsLocalHost = Global.IsLocalHost(uri.Host);
                        if (this.IsLocalHost)
                        {
                            //force it to always be 127.0.0.1 for localhost
                            uri      = new Uri($"{uri.Scheme}://127.0.0.1:{uri.Port}{uri.PathAndQuery}");
                            this.url = uri.ToString();
                        }
                    }
                }
            }

            if (uri != null)
            {
                this.CurSrv = uri.Host + ":" + uri.Port;
            }

            if (!ret)
            {
                AITOOL.Log($"Error: '{this.Type.ToString()}' URL is not valid: '{this.url}'");
            }

            this.IsValid = ret;

            if (!this.isValid)
            {
                this.Enabled.WriteFullFence(false);
            }

            return(ret);
        }
Beispiel #28
0
        public ClsURLItem(String url, int Order, URLTypeEnum type)
        {
            this.UrlFixed = false;

            if (string.IsNullOrWhiteSpace(url))
            {
                if (type == URLTypeEnum.DOODS)
                {
                    this.DefaultURL = "http://127.0.0.1:8080/detect";
                    url             = this.DefaultURL;
                }
                else if (type == URLTypeEnum.AWSRekognition) // || this.url.Equals("aws", StringComparison.OrdinalIgnoreCase) || this.url.Equals("rekognition", StringComparison.OrdinalIgnoreCase))
                {
                    this.DefaultURL = "Amazon";
                    url             = this.DefaultURL;
                }
                else if (type == URLTypeEnum.SightHound_Vehicle)
                {
                    this.DefaultURL = "https://dev.sighthoundapi.com/v1/recognition?objectType=vehicle,licenseplate";
                    url             = this.DefaultURL;
                }
                else if (type == URLTypeEnum.SightHound_Person)
                {
                    this.DefaultURL = "https://dev.sighthoundapi.com/v1/detections?type=face,person&faceOption=gender,landmark,age,pose,emotion";
                    url             = this.DefaultURL;
                }
                else // assume deepstack //if (this.Type == URLTypeEnum.DeepStack || this.url.IndexOf("/v1/vision/detection", StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    this.DefaultURL = "http://127.0.0.1:80/v1/vision/detection";
                    url             = this.DefaultURL;
                }
            }

            this.url = url.Trim();

            this.Type  = type;
            this.Order = Order;


            if (this.Type == URLTypeEnum.DOODS || this.url.EndsWith("/detect", StringComparison.OrdinalIgnoreCase))
            {
                this.DefaultURL = "http://127.0.0.1:8080/detect";
                this.HelpURL    = "https://github.com/snowzach/doods";
                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "http://" + this.url;
                }
                this.Type = URLTypeEnum.DOODS;
                if (!(this.url.IndexOf("/detect", StringComparison.OrdinalIgnoreCase) >= 0))
                {
                    this.UrlFixed = true;
                    this.url      = this.url + "/detect";
                }

                Uri uri = new Uri(this.url);
                this.CurSrv             = uri.Host + ":" + uri.Port;
                this.Port               = uri.Port;
                this.IsLocalHost        = Global.IsLocalHost(uri.Host);
                this.HttpClient         = new HttpClient();
                this.HttpClient.Timeout = TimeSpan.FromSeconds(AppSettings.Settings.HTTPClientTimeoutSeconds);
                this.IsValid            = true;
                this.Enabled.WriteFullFence(true);
            }
            else if (this.Type == URLTypeEnum.AWSRekognition || this.url.Equals("amazon", StringComparison.OrdinalIgnoreCase)) // || this.url.Equals("aws", StringComparison.OrdinalIgnoreCase) || this.url.Equals("rekognition", StringComparison.OrdinalIgnoreCase))
            {
                this.DefaultURL = "Amazon";

                this.HelpURL     = "https://docs.aws.amazon.com/rekognition/latest/dg/setting-up.html";
                this.Type        = URLTypeEnum.AWSRekognition;
                this.IsLocalHost = false;

                string error = AITOOL.UpdateAmazonSettings();

                if (string.IsNullOrEmpty(error))
                {
                    this.CurSrv  = "Amazon:" + AppSettings.Settings.AmazonRegionEndpoint;
                    this.IsValid = true;
                    this.Enabled.WriteFullFence(true);
                    this.MaxImagesPerMonth = 5000;
                }
                else
                {
                    AITOOL.Log($"Error: {error}");
                    this.IsValid = false;
                    this.Enabled.WriteFullFence(false);
                }
            }
            else if (this.Type == URLTypeEnum.SightHound_Person || this.url.IndexOf("/v1/detections", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                this.MaxImagesPerMonth     = 5000;
                this.UseAsRefinementServer = true;
                this.RefinementObjects     = "person";
                this.DefaultURL            = "https://dev.sighthoundapi.com/v1/detections?type=face,person&faceOption=gender,landmark,age,pose,emotion";
                this.HelpURL = "https://docs.sighthound.com/cloud/detection/";
                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "https://" + this.url;
                }
                this.Type = URLTypeEnum.SightHound_Person;
                if (!(this.url.IndexOf("/v1/detections", StringComparison.OrdinalIgnoreCase) >= 0))
                {
                    this.UrlFixed = true;
                    this.url      = this.url + "/v1/detections?type=face,person&faceOption=gender,landmark,age,pose,emotion";
                }

                Uri uri = new Uri(this.url);
                this.CurSrv      = uri.Host + ":" + uri.Port;
                this.Port        = uri.Port;
                this.IsLocalHost = false;
                this.HttpClient  = null;
                this.IsValid     = true;
                this.Enabled.WriteFullFence(true);
            }
            else if (this.Type == URLTypeEnum.SightHound_Vehicle || this.url.IndexOf("/v1/recognition", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                //https://docs.sighthound.com/cloud/recognition/
                this.MaxImagesPerMonth     = 5000;
                this.UseAsRefinementServer = true;
                this.RefinementObjects     = "car,truck,bus,suv,van,motorcycle";
                this.DefaultURL            = "https://dev.sighthoundapi.com/v1/recognition?objectType=vehicle,licenseplate";
                this.HelpURL = "https://docs.sighthound.com/cloud/recognition/";
                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "https://" + this.url;
                }
                this.Type = URLTypeEnum.SightHound_Vehicle;
                if (!(this.url.IndexOf("/v1/recognition", StringComparison.OrdinalIgnoreCase) >= 0))
                {
                    this.UrlFixed = true;
                    this.url      = this.url + "/v1/recognition?objectType=vehicle,licenseplate";
                }

                Uri uri = new Uri(this.url);
                this.CurSrv      = uri.Host + ":" + uri.Port;
                this.Port        = uri.Port;
                this.IsLocalHost = false;
                this.HttpClient  = null;
                this.IsValid     = true;
                this.Enabled.WriteFullFence(true);
            }
            else // assume deepstack //if (this.Type == URLTypeEnum.DeepStack || this.url.IndexOf("/v1/vision/detection", StringComparison.OrdinalIgnoreCase) >= 0)
            {
                this.DefaultURL = "http://127.0.0.1:80/v1/vision/detection";
                this.HelpURL    = "https://ipcamtalk.com/threads/tool-tutorial-free-ai-person-detection-for-blue-iris.37330/";

                if (!this.url.Contains("://"))
                {
                    this.UrlFixed = true;
                    this.url      = "http://" + this.url;
                }


                this.Type = URLTypeEnum.DeepStack;

                bool valid = Global.IsValidURL(this.url);

                //only add path if none already given, for example /vision/custom/model-name
                if (!valid)
                {
                    this.UrlFixed = true;
                    this.url      = this.url.Trim() + "/v1/vision/detection";
                }

                Uri uri = new Uri(this.url);
                this.CurSrv = uri.Host + ":" + uri.Port;
                this.Port   = uri.Port;

                this.IsLocalHost = Global.IsLocalHost(uri.Host);

                this.HttpClient         = new HttpClient();
                this.HttpClient.Timeout = TimeSpan.FromSeconds(AppSettings.Settings.HTTPClientTimeoutSeconds);
                this.IsValid            = true;
                this.Enabled.WriteFullFence(true);
            }


            this.UpdateIsValid();
        }
Beispiel #29
0
        public void ScanImages(int MaxFiles = 3000, int MaxTimeScanningMS = 60000, int MaxDaysOld = -4)
        {
            using var Trace = new Trace();  //This c# 8.0 using feature will auto dispose when the function is done.

            List <FileInfo> files = new List <FileInfo>();

            Stopwatch fscansw = Stopwatch.StartNew();

            if (!string.IsNullOrEmpty(this.input_path) && Directory.Exists(this.input_path))
            {
                List <FileInfo> newfiles = Global.GetFiles(this.input_path, $"{this.Prefix}*.jpg", this.input_path_includesubfolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly, DateTime.Now.AddDays(MaxDaysOld), DateTime.Now, MaxFiles);
                files.AddRange(newfiles);
                AITOOL.Log($"Debug: Found {newfiles.Count} {this.Prefix}*.jpg files in {this.input_path}");
            }

            if (files.Count < MaxFiles && !string.IsNullOrEmpty(AppSettings.Settings.input_path) && AppSettings.Settings.input_path != this.input_path && Directory.Exists(AppSettings.Settings.input_path))
            {
                List <FileInfo> newfiles = Global.GetFiles(AppSettings.Settings.input_path, $"{this.Prefix}*.jpg", AppSettings.Settings.input_path_includesubfolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly, DateTime.Now.AddDays(MaxDaysOld), DateTime.Now, MaxFiles);
                files.AddRange(newfiles);
                AITOOL.Log($"Debug: Found {newfiles.Count} {this.Prefix}*.jpg files in {AppSettings.Settings.input_path}");
            }

            if (files.Count < MaxFiles && !string.IsNullOrEmpty(this.Action_network_folder) && Directory.Exists(this.Action_network_folder))
            {
                List <FileInfo> newfiles = Global.GetFiles(this.Action_network_folder, $"{this.Prefix}*.jpg", SearchOption.TopDirectoryOnly, DateTime.Now.AddDays(MaxDaysOld), DateTime.Now, MaxFiles);
                files.AddRange(newfiles);
                AITOOL.Log($"Debug: Found {newfiles.Count} {this.Prefix}*.jpg files in {this.Action_network_folder}");
            }

            if (!string.IsNullOrEmpty(this.last_image_file) && File.Exists(this.last_image_file))
            {
                if (!files.Any(x => string.Equals(x.FullName, this.last_image_file, StringComparison.OrdinalIgnoreCase)))
                {
                    files.Add(new FileInfo(this.last_image_file));
                }
            }

            files = files.OrderByDescending(t => t.CreationTime).ToList();

            fscansw.Stop();


            int cnt     = 0;
            int updated = 0;
            int invalid = 0;

            AITOOL.Log($"Debug: Found {files.Count} images in {fscansw.ElapsedMilliseconds} ms. Scanning images...");

            Stopwatch sw = Stopwatch.StartNew();

            foreach (FileInfo fi in files)
            {
                try
                {
                    ClsImageQueueItem img = new ClsImageQueueItem(fi.FullName, 0, true);
                    if (img.IsValid())
                    {
                        if (this.UpdateImageResolutions(img))
                        {
                            updated++;
                        }

                        cnt++;
                    }
                    else
                    {
                        invalid++;
                    }
                }
                catch (Exception ex)
                {
                    invalid++;
                    AITOOL.Log($"Debug: {fi.Name}: {ex.Message}");
                }

                if (sw.ElapsedMilliseconds >= MaxTimeScanningMS)
                {
                    AITOOL.Log($"Debug: Max search time exceeded: {sw.ElapsedMilliseconds} ms >= {MaxTimeScanningMS} ms");
                    break;
                }
            }

            sw.Stop();

            string reseseses = "";

            foreach (ImageResItem res in this.ImageResolutions)
            {
                reseseses += $"{res.ToString()};";
            }

            if (string.IsNullOrEmpty(this.last_image_file) && files.Count > 0)
            {
                this.last_image_file = files[0].FullName;
            }

            AITOOL.Log($"Debug: {cnt} of {files.Count} image files processed, {updated} new resolutions found ({invalid} invalid) in {sw.ElapsedMilliseconds} ms (Max={MaxTimeScanningMS} ms), {this.ImageResolutions.Count} different image resolutions found: {reseseses}");
        }
Beispiel #30
0
        public string GetMaskFile(bool MustExist, ClsImageQueueItem CurImg = null, ImageResItem ir = null)
        {
            string ret = "";

            lock (CamLock)
            {
                try
                {
                    String resstr = "";

                    if (CurImg != null)
                    {
                        resstr = $"_{CurImg.Width}x{CurImg.Height}";
                    }
                    else if (ir == null && this.ImageResolutions.Count > 0)
                    {
                        ir     = this.ImageResolutions[0]; //the first one should be the most recent image processed because of the sort.
                        resstr = $"_{ir.Width}x{ir.Height}";
                    }
                    else if (ir != null)
                    {
                        resstr = $"_{ir.Width}x{ir.Height}";
                    }

                    string CamMaskFile = "";
                    if (!string.IsNullOrEmpty(this.MaskFileName))
                    {
                        if (this.MaskFileName.Contains("\\") && this.MaskFileName.Contains("."))
                        {
                            CamMaskFile = this.MaskFileName;
                        }
                        else if (this.MaskFileName.Contains("."))
                        {
                            CamMaskFile = Path.Combine(Path.GetDirectoryName(AppSettings.Settings.SettingsFileName), $"{this.MaskFileName}");
                        }
                        else
                        {
                            CamMaskFile = Path.Combine(Path.GetDirectoryName(AppSettings.Settings.SettingsFileName), $"{this.MaskFileName}.bmp");
                        }

                        //Add WidthxHeight to filename
                        string ResFile = Path.Combine(Path.GetDirectoryName(CamMaskFile), $"{Path.GetFileNameWithoutExtension(CamMaskFile)}{resstr}.bmp");

                        bool resempty     = string.IsNullOrEmpty(resstr);
                        bool cammaskexist = File.Exists(CamMaskFile);
                        bool resexist     = File.Exists(ResFile);
                        if (!resempty && cammaskexist && !Path.GetFileName(CamMaskFile).Contains("_") && !resexist)
                        {
                            //lets rename it to appropriate ResFile name
                            string tmpresstr = "";
                            using (FileStream fileStream = new FileStream(CamMaskFile, FileMode.Open, FileAccess.Read))
                            {
                                using Image img = Image.FromStream(fileStream, false, false);
                                tmpresstr       = $"_{img.Width}x{img.Height}";
                            }
                            if (tmpresstr == resstr)
                            {
                                AITOOL.Log($"Debug: Renaming mask file from '{CamMaskFile}' to '{ResFile}'...");
                                File.Move(CamMaskFile, ResFile);
                            }
                            else
                            {
                                AITOOL.Log($"Debug: Cannot rename mask file because it does not match the current image resolution of '{resstr}' (!={tmpresstr}):  MaskFile='{CamMaskFile}'...");
                            }
                        }
                        else
                        {
                            //AITOOL.Log($"Debug: ResEmpty={resempty}, CamMaskExist={cammaskexist}, ResMaskFileExist={resexist}, CurRes={resstr}, MaskRes={resstr}, CamMaskFile='{CamMaskFile}', ResMaskFile={ResFile}...");
                        }

                        if (MustExist)
                        {
                            if (File.Exists(ResFile))
                            {
                                return(ResFile);
                            }
                            else
                            {
                                return("");
                            }
                        }
                        else
                        {
                            return(ResFile);
                        }
                    }
                }
                catch (Exception ex)
                {
                    AITOOL.Log("Error: " + ex.Msg());
                }
            }

            return(ret);
        }