多线程MFC处理视频

来源:互联网 发布:自由风软件 编辑:程序博客网 时间:2024/05/19 10:09

由于之前在做ALLIED TECNOLOGY工业相机,在工业相机获取视频的基础上,将工业相机存储的pBuffer数据(包含了一幅图像的所有像素点数据,数据存储规律为B0G0R0,B1G1R1……先行后列)转换成为Mat类图像,因而,可以在OPENCV中进行图像处理。程序如下:

void CopyToMat(Mat* img, VmbUchar_t*pInBuffer)//自定义  pBffer即为工业相机获取到的图像数据容器
{
 for (int i = 0; i<(*img).rows; i++)
 {
  for (int j = 0; j < (*img).cols; j++)
  {
   ((*img).ptr<uchar>(i,j))[0] = *(pInBuffer  +i*(*img).cols*3 + (j * 3) + 0);
   ((*img).ptr<uchar>(i,j))[1] = *(pInBuffer  +i*(*img).cols * 3 + (j * 3) + 1);
   ((*img).ptr<uchar>(i,j))[2] = *(pInBuffer  +i*(*img).cols * 3 + (j * 3) + 2);
  }
 }
}

 

     由于有很多大型算法进行图像处理,所以要解决视频丢帧问题,因而需要用多线程来解决视频丢帧问题。

     思路是:用定时器来不断的获取图像,然后立即向队列里缓存图像,然后再开一个线程来不断的从队列的头部取出,在从线程中进行图像处理。

     添加定时器的方法是 添加一个定时器消息。

      定时器的初始化是: SetTimer(1,300,NULL);//300ms

     定义一个结构体来存储图像(这个结构体的作用是将图像存储到结构体里,然后再从结构体传递给队列,个人理解)。结构体定义如下:

struct DataInfo
{
Mat pBuf;//缓存内容
int iSize;//缓存大小


DataInfo()
{
pBuf = NULL;
iSize = 0;
}
};

定义一个函数,用队列来存储图像。如下:

 void ImgBuffer(Mat image)
 {
if (hthread1 == NULL)
{
hthread1 = CreateThread(NULL, 0, thread_work, &image, 0, NULL);
InitializeCriticalSection(&m_lock);//线程锁初始化
}
else
{
DataInfo dataInfo;
dataInfo.pBuf = image;
EnterCriticalSection(&m_lock);//进入临界区
m_dq_buf.push(dataInfo);//把图像压入队列
LeaveCriticalSection(&m_lock);//退出临界区
}
 }

定义线程函数,从队列中取出来图像进行图像处理。函数如下:


 DWORD WINAPI thread_work(LPVOID IpParmeter)
 {
//当缓存队列中的数据大于0时,不断将数据取出进行处理
DataInfo dataInfo;//定义一个临时变量

while (1) {
if (m_dq_buf.size() > 0)
{
dataInfo  = m_dq_buf.front();//从队列中取得第一幅图像

Mat imgGray, imgHarris, harrisCorner;
cvtColor(dataInfo.pBuf, imgGray, CV_BGR2GRAY);//将彩色图像转换为灰度图
cornerHarris(imgGray, imgHarris, 2, 3, 0.001);//角点检测
threshold(imgHarris, harrisCorner, 0.00001, 255, THRESH_BINARY);//图像二值化
imshow("线程读取结果", dataInfo.pBuf);
imshow("角点检测", harrisCorner);



//使用临界区加锁
EnterCriticalSection(&m_lock);//进入临界区
m_dq_buf.pop();//将缓存从队列中删除
LeaveCriticalSection(&m_lock);//退出临界区
}
Sleep(500);//休眠500ms,也就是每隔500ms从队列中取一次图像进行处理
}
 }


遇到的问题:

1.如果不在初始化函数中添加

namedWindow("线程读取结果", WINDOW_AUTOSIZE);//若不初始化窗口,则会在主线程所创建的从线程中,图片显示灰色
namedWindow("角点检测", WINDOW_AUTOSIZE);//同上

则会出现窗口为灰色。

2.线程函数应该是一个死循环。


PS.我是做视觉的,某人是做飞控的,这个程序是某人帮我调出来的,结果他竟然说感觉他也就能帮我到这里了,后面的都要我自己来了。

原创粉丝点击