OpenCV 显示和处理网络摄像头流

Posted

技术标签:

【中文标题】OpenCV 显示和处理网络摄像头流【英文标题】:OpenCV display and processing webcam stream 【发布时间】:2015-01-21 15:49:12 【问题描述】:

我正在寻找使用来自网络摄像头的 opencv 处理流。我的目标是检测每个帧的矩形。我可以显示结果,但帧率真的很慢,~1 fps。

这里是我的源代码的概述:

int main( int argc, char** argv ) 

CvCapture* cap=cvCreateCameraCapture(0);
cvNamedWindow("LiveFeed",CV_WINDOW_AUTOSIZE);

    while(true) 
    frame=cvQueryFrame(cap);
    if(!frame) 
        printf("\n no");
    else 
        Mat mat_img(frame);
        std::vector<std::vector<cv::Point>> rectangle = findSquaresInImage(mat_img);
        rectangle=filterRectangleSimilaire(rectangle,20.0);
        Mat res=debugSquares(rectangle,mat_img);

        cvShowImage("LiveFeed",new IplImage(res));//new IplImage(res));
    
    char c=cvWaitKey(33);
    if(c==27)
        break;


cvReleaseCapture(&cap);
cvDestroyAllWindows();
return 0;

我想知道是否可以使其线程化以获得至少 30fps 的速度?

我正在使用 Windows 8.1、Visual 2010、c++ 和 OpenCV 2.4.10

【问题讨论】:

【参考方案1】:

您可以在while(true) 循环之前使用线程。当然,从相机读取帧并显示它们必须是序列化的。

我看到您正在使用 C++ std::vector,所以我建议您使用 C++11 线程和互斥锁。我能想到的最高效的方式是在启动时打开所有线程(在while(true) 循环之前),然后接收主线程捕获的帧。所有线程将被锁定在同一个互斥体上以读取帧队列,并锁定在第二个互斥体上以显示它。帧队列可以实现为:

struct frameQueue
    std::vector<Mat> frames;
    std::mutex mtx;
;

根据项目的大小和副作用,它甚至可以声明为全局。

【讨论】:

我假设您正在体验这个解决方案,它应该可以工作。我询问了线程解决方案,但我从 stacoverflow 优化/找到了一些用于图像处理的不同代码,现在我至少有 30 fps。无论如何,感谢您的解决方案 有用的建议!【参考方案2】:

我使用 *** 上的另一个解决方案解决了这个问题。 这是我的完整代码:

Mat mat_img(frame);
Mat gray_mat_img, threshold_mat_img, detected_edges;
std::vector<std::vector<cv::Point>> contours;
vector<Vec4i> hierarchy;

cvtColor(mat_img, gray_mat_img, CV_BGR2GRAY);
blur(gray_mat_img, gray_mat_img, Size(10,10));
cv::threshold(gray_mat_img, threshold_mat_img, 140, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
Canny(threshold_mat_img, detected_edges, 100, 100, 3);
cv::findContours(detected_edges, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

RNG rng(12345);
//contours = filterRectangleSimilaire(contours, 10);
//if (contours.size() < 5) 
vector<Rect> boundRect( contours.size() );
vector<Point> approx;


for (size_t i = 0; i < contours.size(); i++) 
    approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
    if (approx.size() == 4 && fabs(contourArea(Mat(approx))) > 100 && isContourConvex(Mat(approx))) 
        double maxCosine = 0;
        for (int j = 2; j < 5; j++) 
            double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
            maxCosine = MAX(maxCosine, cosine);
        
        if (maxCosine < 0.3) 
            Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255));
            boundRect[i] = boundingRect( Mat(approx) );
            rectangle( mat_img, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );
            drawContours(mat_img, contours, i, color, 2, 8, hierarchy, 0, Point());
        
    

这是我的参考资料:OpenCV C++/Obj-C: Detecting a sheet of paper / Square Detection

【讨论】:

以上是关于OpenCV 显示和处理网络摄像头流的主要内容,如果未能解决你的问题,请参考以下文章

QImage OpenCV - setPixel 只有绿色和黑色

Opencv:代码中没有错误,但网络摄像头未显示在结果中

发送到 pyvirtualcam 的网络摄像头输入为蓝色(使用 pyvirtualcam 和 opencv)

在opencv中使用网络摄像头未显示图像

OpenCV 网络摄像头提要未在 PictureBox Visual Studio 2015 中显示

我的 OpenCV 实时网络摄像头演示没有显示准​​确的情绪