• 2.5 C#视觉程序开发实例1----CamManager实现模拟相机采集图片(Form_Vision部分代码)


    2.5 C#视觉程序开发实例1----CamManager实现模拟相机采集图片(Form_Vision部分代码)

    1 目标效果视频

    CamManager

    2 增加一个class IMG_BUFFER 用来管理采集的图片

    // 
    /// IMG_BUFFER 用来管理内存图片的抓取队列
    /// 
    public class IMG_BUFFER
    {
        public List<Mat> list_imgs_acq;
        private object mutex;
        private int max_count = 3;
        public IMG_BUFFER()
        {
            list_imgs_acq = new List<Mat>();
            mutex = new object(); 
        }
        /// 
        /// 图片入栈
        /// 
        /// 
        /// 
        public  int Add(Mat himg_acq)
        {
            int nRet = 0;
            if (list_imgs_acq.Count >= max_count) return -1;
            lock(mutex)
            {
                list_imgs_acq.Add(himg_acq);
            }
            return nRet;
        }
    
        /// 
        /// 获取一张图片
        /// 
        /// 
        public Mat Pop_Front()
        {
             
            Mat tmp = new Mat();
            if (list_imgs_acq.Count ==0) return tmp;
            lock (mutex)
            {
                tmp = list_imgs_acq[0];
                list_imgs_acq.RemoveAt(0);
            }
            return tmp;
        }
    }
    

    3 本地Debug目录下增加一下文件,用于模拟相机采集的图片

    在这里插入图片描述
    在Cam0中放入3张图片
    在这里插入图片描述

    4 Form_vision初始化 读取一张照片,并显示在屏幕上

    Open_Resources()中增加代码

    // opencamCtx
    int CamNO = 0;
    ContextManager.get_camCtx().Open(CamNO);
    ContextManager.get_camCtx().Grab(ref himg_tmp, CamNO);
    
     bdDisplay_Runsets1.picture_cam.InitDisplay_Mat(ref himg_tmp);
    

    5 ImgAcq线程增加采集图片代码

    if (n_trig0_cur > 0 && n_trig0_last == 0)  //判断上升沿触发
    {
        //相机采集
        int nRet = 0;
        nRet = ContextManager.get_camCtx().Grab(ref himg_tmp, CamNO);
        if(nRet==0)
        {
            // 图片入栈
            imgs_buffer.Add(himg_tmp);
            //AutoEvent set,通知ImgProcess
            newImgEvent_thread.Set();
        }
    }
    

    6 ImgProcess线程增加图片处理代码

    1. BDDisplay_Runsets中增加一个Display函数
      Q:为什么使用invoke()?
      A: 因为从另外一个线程调用资源显示,可能会报警
      解决方法1:CheckForIllegalCrossThreadCalls = false; //不检查线程间操作(如果程序抛出了“线程间操作无效”异常,可以添加该行代码)
      解决方法2:invoke()
    /// 
    /// Display
     /// 
     /// 
     public void Display(  OpenCvSharp.Mat himg)
     {
         if (BD_OperateSet.MatNull(himg)) return;
         this.Invoke(new Action(() => { 
             picture_cam.Display_Mat(ref himg);
         }));
     }
    
    1. ImgProcessCCD(int n_thread_index = 0)增加代码
    // 添加线程统计信息
    Mat tmp = imgs_buffer.Pop_Front();
     if(BD_OperateSet.MatisNotNull(tmp))
     { 
         bdDisplay_Runsets1.Display(tmp);
     }
     else
     {
         status = false;
     }
    
  • 相关阅读:
    【软件测试】自动化测试 Selenium 篇(一)
    分布式锁之 redis & redisson (你学了 synchronized 真的有用吗?)
    使用Selenium的Python脚本实现自动登录
    【数据结构初阶】八、非线性表里的二叉树(二叉树的实现 -- C语言链式结构)
    SPA项目开发之登录注册
    一文详解微服务架构
    JavaScript 27 JavaScript 数组迭代
    Python应用:画出任意二维函数的轨迹
    SQL Proxy 角色重叠
    【Java】数组
  • 原文地址:https://blog.csdn.net/weixin_42490025/article/details/140264503