2.5 C#视觉程序开发实例1----CamManager实现模拟相机采集图片(Form_Vision部分代码)
1 目标效果视频
CamManager
2 增加一个class IMG_BUFFER 用来管理采集的图片
// <summary>
/// IMG_BUFFER 用来管理内存图片的抓取队列
/// </summary>
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();
}
/// <summary>
/// 图片入栈
/// </summary>
/// <param name="himg_acq"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取一张图片
/// </summary>
/// <returns></returns>
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线程增加图片处理代码
- BDDisplay_Runsets中增加一个Display函数
Q:为什么使用invoke()?
A: 因为从另外一个线程调用资源显示,可能会报警
解决方法1:CheckForIllegalCrossThreadCalls = false; //不检查线程间操作(如果程序抛出了“线程间操作无效”异常,可以添加该行代码)
解决方法2:invoke()
/// <summary>
/// Display
/// </summary>
/// <param name="himg"></param>
public void Display( OpenCvSharp.Mat himg)
{
if (BD_OperateSet.MatNull(himg)) return;
this.Invoke(new Action(() => {
picture_cam.Display_Mat(ref himg);
}));
}
- ImgProcessCCD(int n_thread_index = 0)增加代码
// 添加线程统计信息
Mat tmp = imgs_buffer.Pop_Front();
if(BD_OperateSet.MatisNotNull(tmp))
{
bdDisplay_Runsets1.Display(tmp);
}
else
{
status = false;
}