2.5 C#视觉程序开发实例2----图片内存管理 Csharp实现
mat-buffer
// Mat buffer 用于保存Mat 图片内存 //Mat[0]:register //Mat[1]:cur img //Mat[2-6]:colorfilter //Mat[7-16]:grayfilter public static int n_max_buffers = 17; public Mat[,] mat_buffers;//Mat[camCount,17]
VisionManager初始化时自动初始化内存数组
public VisionManager() { try { // 初始化 mat_buffers mat_buffers = new Mat[n_max_CamCount, n_max_buffers]; for (int i = 0; i < n_max_CamCount; i++) { for (int j = 0; j < n_max_buffers; j++) { mat_buffers[i, j] = new Mat(); } } } catch(Exception ex) { ExceptionManager.Add_Exception(TraceHelper.GetFuncName(), ex); } }
用于应用程序切换程序时导入视觉工具参数,这里只是举例说明读取注册图片
/// /// LoadProgram /// /// /// public int LoadProgram(int ProNO) { int nRet = 0; try { //stp0 读取注册图片 nRet = Read_Register_Img(); } catch(Exception ex) { nRet = -2; } return nRet; } /***************************************************************/ /// /// get_Path /// 获取当前程序号的全路径 /// /// /// private string get_Path(int proNO) { return @appPath + "Program" + proNO.ToString("000") + "/"; } /// /// Read_CamParams /// /// /// private int Read_Register_Img(int CamNO) { int nRet = 0; string CameraName, FilePath, FileName; CameraName = CamNO.ToString(); FilePath = get_Path(Program_NO)+"Cam" + CameraName+@"/"; FileName = "camParams.xml"; try { // 判断是否文件夹存在 // 先清空内存 BD_OperateSet.Assign_Temp(ref mat_buffers[CamNO,0],new Mat()); // 读取保存的注册画面 FileName = "Img.png"; if (ContextManager.get_fileopCtx().FileExist(FilePath, FileName)) { Mat tmp= Cv2.ImRead(FilePath + FileName, ImreadModes.Unchanged); BD_OperateSet.Assign_Mat(ref mat_buffers[CamNO, 0], ref tmp); BD_OperateSet.Assign_Temp(ref tmp);// 清空临时变量 } } catch(Exception ex) { ExceptionManager.Add_Exception(TraceHelper.GetFuncName(), ex); nRet = (int)STATUS_ENUM.STATUS_EXCEPTION; } return nRet; } /// /// 读取全部相机注册图片 /// /// private int Read_Register_Img() { int nRet = 0; for(int i=0;i nRet = Read_Register_Img(i); if (nRet != 0) break; } return nRet; }
//visionManager private static VisionManager vision_Ctx; public static VisionManager get_visionCtx() { if (vision_Ctx == null) vision_Ctx = new VisionManager(); return vision_Ctx; }
/// /// Load_Program /// 导入当前程序参数 /// /// /// private int Load_Program( ) { int nRet = 0; ContextManager.get_visionCtx().LoadProgram(VisionManager.Program_NO); return nRet; }
Form_vision_Load时 ,按照以下流程进行处理
private void Form_vision_Load(object sender, EventArgs e) { //打开资源 Open_Resources(); // load 程序参数 VisionManager.Program_NO = 0; // 导入程序参数 Load_Program(); // 初始化显示控件 Init_Display(); // 创建线程 CreateThread(); timer1.Interval = 100; timer1.Start(); }
Init_Display()实现
/// /// Init_Display /// 显示控件第一次显示, 目的进行画布的初始化布局 /// private void Init_Display() { //显示控件第一次显示, 目的进行画布的初始化布局 for(int i=0;i // 初始化显示注册图片, if(BD_OperateSet.MatisNotNull(ContextManager.get_visionCtx().mat_buffers[i,0])) bdDisplay_Runsets1.picture_cam.InitDisplay_Mat(ref ContextManager.get_visionCtx().mat_buffers[i, 0]); } }
//C# Class是地址传递,这里直接用= tmp = imgs_buffer.Pop_Front(); // bdDisplay_Runsets1.flush_Display = false; int CamNO = 0; // stp0 matbuffer[CamNO,1],代表当前最新抓取图片 BD_OperateSet.Assign_Mat(ref ContextManager.get_visionCtx().mat_buffers[CamNO, 1], ref tmp); ok_message.Add("采集图片成功");
输入源mat_buffer[1],输出源mat_buffer[2]
// stp1 cfilter 处理 if (tmp.Type() == MatType.CV_8UC3)//判断是否彩色图片,一般采集图片都是8位的 { Mat[] bgr = new Mat[3]; // 分解成三通道, 默认是通道0:B ,通道1:G ,通道2: R Cv2.Split(tmp, out bgr); // 获取其中 R 通道,赋值给 mat_buffers[CamNO, 2] BD_OperateSet.Assign_Mat(ref ContextManager.get_visionCtx().mat_buffers[CamNO, 2], ref bgr[2]); // 销毁临时变量 BD_OperateSet.Mats_Clear(bgr); bgr = null; ok_message.Add("彩色过滤器,获取R通道成功"); }
输入源mat_buffer[2],输出源mat_buffer[7]
// stp2 filter 处理 // 联系 scale img if (BD_OperateSet.MatisNotNull(ContextManager.get_visionCtx().mat_buffers[CamNO, 2])) { Mat scale_img = new Mat(); // dst=src*1.2+add; double scale = 1.2; double add = 0; ContextManager.get_visionCtx().mat_buffers[CamNO, 2].ConvertTo(scale_img, -1, scale, add); //输出结果到 mat_buffers[CamNO, 6] BD_OperateSet.Assign_Mat(ref ContextManager.get_visionCtx().mat_buffers[CamNO, 7], ref scale_img); // 销毁临时变量 BD_OperateSet.Assign_Temp(ref scale_img); ok_message.Add("灰度过滤器,图片增强成功"); }
处理效果
// stp3 intensity处理 if (BD_OperateSet.MatisNotNull(ContextManager.get_visionCtx().mat_buffers[CamNO, 7])) { //获取平均亮度 Scalar intensity = Cv2.Mean(ContextManager.get_visionCtx().mat_buffers[CamNO, 7]); ok_message.Add("获取图片平均亮度,亮度=" + intensity.Val0.ToString("0")); }
结果显示效果
/// /// ImgProcessCCD0 /// remark: thread 图像process0 /// private void ImgProcessCCD(int n_thread_index = 0) { ListViewItem DATA = new ListViewItem(); DateTime ts3 = DateTime.Now; DateTime current = DateTime.Now; bool status = true; // OK结果信息记录 List ok_message = new List(); // NG结果信息记录 List ng_message = new List(); while ( newImgEvent_thread.WaitOne()) //相机1&2都已经已拍照 { Mat tmp = null; ok_message.Clear(); ng_message.Clear(); try { // 添加线程统计信息 //C# Class是地址传递,这里直接用= tmp = imgs_buffer.Pop_Front(); // bdDisplay_Runsets1.flush_Display = false; int CamNO = 0; // stp0 matbuffer[CamNO,1],代表当前最新抓取图片 BD_OperateSet.Assign_Mat(ref ContextManager.get_visionCtx().mat_buffers[CamNO, 1], ref tmp); ok_message.Add("采集图片成功"); // stp1 cfilter 处理 if (tmp.Type() == MatType.CV_8UC3)//判断是否彩色图片,一般采集图片都是8位的 { Mat[] bgr = new Mat[3]; // 分解成三通道, 默认是通道0:B ,通道1:G ,通道2: R Cv2.Split(tmp, out bgr); // 获取其中 R 通道,赋值给 mat_buffers[CamNO, 2] BD_OperateSet.Assign_Mat(ref ContextManager.get_visionCtx().mat_buffers[CamNO, 2], ref bgr[2]); // 销毁临时变量 BD_OperateSet.Mats_Clear(bgr); bgr = null; ok_message.Add("彩色过滤器,获取R通道成功"); } // stp2 filter 处理 // 联系 scale img if (BD_OperateSet.MatisNotNull(ContextManager.get_visionCtx().mat_buffers[CamNO, 2])) { Mat scale_img = new Mat(); // dst=src*1.2+add; double scale = 1.2; double add = 0; ContextManager.get_visionCtx().mat_buffers[CamNO, 2].ConvertTo(scale_img, -1, scale, add); //输出结果到 mat_buffers[CamNO, 6] BD_OperateSet.Assign_Mat(ref ContextManager.get_visionCtx().mat_buffers[CamNO, 7], ref scale_img); // 销毁临时变量 BD_OperateSet.Assign_Temp(ref scale_img); ok_message.Add("灰度过滤器,图片增强成功"); } // stp3 intensity处理 if (BD_OperateSet.MatisNotNull(ContextManager.get_visionCtx().mat_buffers[CamNO, 7])) { //获取平均亮度 Scalar intensity = Cv2.Mean(ContextManager.get_visionCtx().mat_buffers[CamNO, 7]); ok_message.Add("获取图片平均亮度,亮度=" + intensity.Val0.ToString("0")); } // 图片结果刷新 bdDisplay_Runsets1.flush_Display = true; if (BD_OperateSet.MatisNotNull(tmp)) { int index = index_mat_buffer; if (index == -1) index = 1; switch (index_mat_buffer) { case 0: bdDisplay_Runsets1.Display(tmp); break; default: bdDisplay_Runsets1.Display(ContextManager.get_visionCtx().mat_buffers[CamNO, index]); break; } } else { status = false; } // 结果信息刷新 bdDisplay_Runsets1.Display_Result(ok_message,ng_message,Color.DarkGreen,Color.Red); //统计结果显示 thead0_summary.Update_Statistics(status); // 相机状态栏更新 bdDisplay_Runsets1.Update_Cam_Text(status, thead0_summary.toString()); } catch(Exception ex) { ExceptionManager.Add_Exception(TraceHelper.GetFuncName(), ex); } // 输出脉冲 ContextManager.get_IOCtx().task_out_server_thread0.Add_One_Task(status); // 临时变量赋值null tmp = null; if (StopProgramEvent.WaitOne(0, true)) break; } //end while return; }