using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using OpenCvSharp; using System.Collections.Concurrent; using System.Diagnostics; using System.Text; namespace LB_VisionProcesses.Cameras { [Process("相机取图", Category = "取像工具", Description = "创建相机取图工具")] public class CameraConfig : IProcess { /// /// 相机集合(Key:相机SN,Value:相机句柄) /// public ConcurrentDictionary dicCameras { get; set; } public BaseCamera Camera { get; set; } public CameraConfig(ConcurrentDictionary dicCameras = null) { this.dicCameras = dicCameras; strProcessName = "相机取图"; strProcessClass = "LB_VisionProcesses.CameraConfig.CommunicatorConfig"; Params.Inputs.Add("相机SN", ""); Params.Inputs.Add("触发模式", TriggerMode.On); Params.Inputs.Add("触发方式", TriggerSource.Software); Params.Inputs.Add("触发极性", TriggerPolarity.RisingEdge); Params.Inputs.Add("触发消抖", 0); Params.Inputs.Add("触发延时", 0); Params.Inputs.Add("曝光时间", 1000); Params.Inputs.Add("增益", 1); Params.Inputs.Add("是否每次写入参数", false); Params.Inputs.Add("是否本地取图", false); Params.Inputs.Add("本地取图路径", ""); Params.Inputs.Add("本地取图序号", 0); Params.Inputs.Add("超时时间", 1000); Params.Inputs.Add("是否失败重新取图", false); } /// /// 加载算法 /// /// 完整路径带.json /// public override bool Load(string fullPath = null) { try { if (string.IsNullOrEmpty(fullPath)) return false; if (!fullPath.Contains(".json")) { Debug.WriteLine("文件路径不完整"); return false; } if (string.IsNullOrEmpty(fullPath) || fullPath.Trim() == "") { Debug.WriteLine("文件路径不完整"); return false; } // 获取不带文件名的目录路径 string directoryPath = Path.GetDirectoryName(fullPath); strProcessName = Path.GetFileNameWithoutExtension(fullPath); if (!File.Exists(fullPath)) { Debug.WriteLine("文件不存在创建空文件"); Save(directoryPath); return true; } string strJson = string.Empty; using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8)) { strJson = streamReader.ReadToEnd(); streamReader.Close(); } Params = JsonConvert.DeserializeObject(strJson); if (Params == null) return false; Params.FixDeserializedData(); #region 加载后把参数写入到相机中 bool isLocal = Convert.ToBoolean(Params.Inputs["是否本地取图"].ToString()); if (!isLocal) { string SN = Params.Inputs["相机SN"].ToString(); if (dicCameras == null || !dicCameras.ContainsKey(SN)) return false; BaseCamera BaseCamera = dicCameras[SN]; if (BaseCamera == null) return false; if (!BaseCamera.isGrabbing) { if (!BaseCamera.StartGrabbing()) return false; } BaseCamera.SetCamConfig(this); } #endregion return true; } catch { return false; } } /// /// 保存算法 /// /// 不带.json /// public override bool Save(string filePath = null) { try { if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "") { Debug.WriteLine("文件路径不完整"); return false; } string strJson = string.Empty; var settings = new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented, // 自定义缩进(4空格) ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() } }; strJson = JsonConvert.SerializeObject(Params, settings); Params = JsonConvert.DeserializeObject(strJson); if (Params == null) return false; //判断文件夹是否存在,防呆输入为文件名称 if (!Directory.Exists(filePath)) { try { Directory.CreateDirectory(filePath); } catch (Exception) { } } File.WriteAllText(filePath + "//" + strProcessName + ".json", strJson, Encoding.UTF8); return true; } catch { return false; } } public override bool Run() { DateTime StartTime = DateTime.Now; try { InitRunParams(); string SN = string.Empty; bool isLocal = Convert.ToBoolean(Params.Inputs["是否本地取图"]?.ToString()); bool isUpParams = Convert.ToBoolean(Params.Inputs["是否每次写入参数"]?.ToString()); bool isRegrab = Convert.ToBoolean(Params.Inputs["是否失败重新取图"]?.ToString()); int timeout = Convert.ToInt16(Params.Inputs["超时时间"]?.ToString()); if (isLocal) { if (Params.Inputs["本地取图路径"] is List) { List lstPaths = Params.Inputs["本地取图路径"] as List; if (lstPaths != null && int.TryParse(Params.Inputs["本地取图序号"]?.ToString(), out int indexPath) && lstPaths.Count > indexPath) { SN = lstPaths[indexPath]; if (lstPaths.Count > indexPath + 1) Params.Inputs["本地取图序号"] = indexPath + 1; else Params.Inputs["本地取图序号"] = 0; Mat src = Cv2.ImRead(SN); if (src != null && !src.Empty()) OutputImage = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(src); } } } else { SN = Params.Inputs["相机SN"].ToString(); if (dicCameras == null || !dicCameras.ContainsKey(SN)) { Msg = $"相机[{SN}]不存在"; Result = false; RunTime = (DateTime.Now - StartTime).TotalMilliseconds; return Result; } if (Camera == null || Camera.SN != SN) { if (dicCameras.ContainsKey(SN)) Camera = dicCameras[SN]; else Camera = null; } if (Camera == null) { Msg = $"相机[{SN}]未实例化"; Result = false; RunTime = (DateTime.Now - StartTime).TotalMilliseconds; return Result; } CameraConfig oriConfig = new CameraConfig(); if (isUpParams) { Camera.GetCamConfig(out oriConfig); Camera.SetCamConfig(this); } if (!Enum.TryParse(Params.Inputs["触发方式"].ToString(), out TriggerSource TriggerSource)) { Msg = $"相机[{SN}]设置的触发方式不正确,值为:{Params.Inputs["触发方式"].ToString()}"; Result = false; RunTime = (DateTime.Now - StartTime).TotalMilliseconds; return Result; } Bitmap bitmap = null; int times = 5; do { times--; if (TriggerSource == TriggerSource.Software) Camera.GetImageWithSoftTrigger(out bitmap, timeout); else Camera.GetImage(out bitmap, timeout); if (bitmap != null) break; else if (isRegrab) { Debug.WriteLine($"取图失败,重新取图,剩余次数:{times}"); } } while (times > 0 && isRegrab); if (isUpParams) Camera.SetCamConfig(oriConfig); OutputImage = bitmap; } if (OutputImage == null) { Msg = $"相机[{SN}]获取图像失败"; Result = false; } } catch (Exception ex) { Msg = ex.Message; Result = false; } RunTime = (DateTime.Now - StartTime).TotalMilliseconds; return Result; } public override void InitRunParams() { Result = true; Msg = ""; OutputImage = null; if (Record != null) Record.Dispose(); } public override void Dispose() { return; } public override object Clone() { try { var obj = (CameraConfig)MemberwiseClone(); // 浅拷贝 // 手动处理引用类型 if (OutputImage != null) { if (OutputImage is Bitmap) obj.OutputImage = ((Bitmap)OutputImage).Clone(); } return obj; } catch { return (CameraConfig)MemberwiseClone(); } } } }