想使用多线程对同一个视频进行处理,加快处理速度。首先进行一个最简单的多线程处理的视频的功能:两个线程同时读取视频,并在两个线程中分别显示读取的视频。
首先,为了实现这个功能,我的代码一开始是这样的:
#include <iostream>
#include "opencv2/opencv.hpp"
#include <Windows.h>
using namespace std;
using namespace cv;
char tmp[]="IMG";
LPCWSTR name=(WCHAR *)tmp;
HANDLE hMutex = CreateMutex(NULL, false,name);
DWORD WINAPI TL_FRAME(LPVOID lpParamter)
{
WaitForSingleObject(hMutex,INFINITE);
cout<<"Into the sub thread"<<endl;
IplImage* frame=(IplImage*)lpParamter;
cvShowImage("TL",frame);
cvWaitKey(5);
cout<<"leave the sub thread"<<endl;
ReleaseMutex(hMutex);
return 0;
}
void videoMultiThread()
{
CvCapture * cap=cvCreateFileCapture("D:\\JY\\JY_TrainingSamples\\TrafficSignVideo\\trafficSign6.avi");
IplImage * frame;
while(1)
{
WaitForSingleObject(hMutex,INFINITE);
cout<<"Into the main thread"<<endl;
frame=cvQueryFrame(cap);
if(!frame)break;
cvShowImage( "frame",frame);
//MultiThread
HANDLE hThread = CreateThread(NULL,0,TL_FRAME,frame,0,NULL);
CloseHandle(hThread);
char c=waitKey(5);
if (c==27)break;
cout<<"leave the main thread"<<endl;
ReleaseMutex(hMutex);
}
cvReleaseCapture(&cap);
cvDestroyAllWindows();
}
int main()
{
videoMultiThread();
return 0;
}
然后问题出现了。这段代码运行的结果是:只有main线程的视频可以显示,而TL_FRAME
线程的视频闪了一下秒退,之后就再也没有出现。但是控制台的输出信息是没有问题得,交替输出:
Into the main thread
leave the main thread
Into the sub thread
leave the sub thread
解决的方法
在主线程创建从线程TL_FRAME
之前,添加cvNamedWindow("TL")
,同时在从线程TL_FRAME
中的图像显示之前,添加cvNamedWindow("TL")
。且把线程锁去掉,才可以在两个视频中同时显示图像。
需要注意的是:之前我们显示图像时,喜欢偷懒,直接imshow
图像,会自动创建窗口然后图像在上面显示。但是在多线程中会出现问题。必须要在显示之前添加上cvNamedWindow()
。
使用openMP解决多线程读取问题
使用上述windows的多线程API处理,发现效率不高,CPU占用率很高,速度也不是很快,还会一卡一卡的,尝试使用openMP来解决,发现效果要好多了,CPU占用率下降好多,速度也比上一种方式快,而且使用起来要更加简单。代码如下:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/background_segm.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <omp.h>
//C++
#include <iostream>
#include <sstream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
//print help information
VideoCapture capture("video.avi");
if(!capture.isOpened()){
//error in opening the video input
cerr << "Unable to open video file: " <<0 << endl;
exit(EXIT_FAILURE);
}
Mat imgGrayScale;
for(;;)
{
bool bSuccess = capture.read(imgGrayScale); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read the frame from video file" << endl;
break;
}
// capture >> imgGrayScale;
Mat img1(imgGrayScale);
Mat img2(imgGrayScale);
#pragma omp parallel sections
{
#pragma omp section
{
Mat img1Gray;
cvtColor(img1,img1Gray,CV_BGR2GRAY);
namedWindow("img1Gray");
imshow("img1Gray",img1Gray);
waitKey(5);
}
#pragma omp section
{
Mat img2Gray;
cvtColor(img1,img2Gray,CV_BGR2GRAY);
namedWindow("img2Gray");
imshow("img2Gray",img2Gray);
waitKey(5);
}
}
}
waitKey();
getchar();
}