使用OpenCV捕捉相机的灰屏画面

4

我有一个从我的Web摄像头(内置于惠普DV5)捕获图像的问题。唯一的结果是灰色屏幕。以下是代码:

#include "StdAfx.h"
#include "cv.h"
#include "highgui.h"
#include <stdio.h>  // A Simple Camera Capture Framework
int main() { 
    CvCapture* capture;
    for (int i = -1;i < 100;i++) {
        capture = cvCaptureFromCAM( i );   
        if( !capture ) {
            fprintf( stderr, "ERROR: capture is NULL \n" ); 

        } else {
            break;
        }
    }
    //cvSetCaptureProperty( capture, CV_CAP_PROP_FPS,15);
    //cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 160 );
    //cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 120 );
    // Create a window in which the captured images will be presented   
    cvNamedWindow( "mywindow", CV_WINDOW_AUTOSIZE );    // Show the image captured from the camera in the window and repeat   
    while( 1 ) {     // Get one frame     
        IplImage* frame = cvQueryFrame( capture );
        cvGrabFrame(capture);
        frame = cvRetrieveFrame(capture);

        if( !frame ) {
            fprintf( stderr, "ERROR: frame is null...\n" );
            getchar();
            break;
        } else {
            fprintf( stderr, "OK\n" );  
        }
        cvShowImage( "mywindow", frame );     // Do not release the frame!      
        //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),     //remove higher bits using AND operator     
        int c = cvWaitKey(100);
    }    // Release the capture device housekeeping   
    cvReleaseCapture( &capture );   
    cvDestroyWindow( "mywindow" );   
    return 0; 
}

这是修改自OpenCV维基的代码。我知道用这种方法找相机很疯狂,但使用-1或0并没有起作用。我添加了一些额外的属性(已注释),但仍然没有起作用。提前感谢您的帮助 :) 问候, Chris

3个回答

1
我将图像捕获封装成了一个名为“Capture”的类,也许你可以试试。以下是main.cpp、capture.h和capture.cpp文件,希望你喜欢 :)

main.cpp

#include "capture.h"
#include <string>
using namespace std;

    int main(int argc, char* argv[]) {

        // --- read file --- //
        //Capture capture("test.wmv", windowSize, windowSize);

        // --- read camera --- //
        CvSize windowSize = cvSize(640, 480);
        Capture capture(2, windowSize, windowSize);

        while (1) {

            capture.captureNext();

            for (int i = 0; i < capture.channelNum; ++i) {

                ostringstream oss;
                oss << i;
                string winName = "WINDOW-" + (oss.str());

                cvShowImage(winName.c_str(), capture.channelframeList[i]);

            }

            int c = cvWaitKey(30);
            if ( (char) c == 27 ) { // 'Esc' to terminate

                break;
            }

        }

        return 0;

    }

caputure.h

#ifndef _CAPTURE_H_
#define _CAPTURE_H_

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <string>
#include <vector>
#include <iostream>
using namespace std;

enum VIDEO_TYPE {
    CAMMERA = 0,
    VIDEOFILE
};

class Capture {

public:

    Capture(int num, CvSize dispSize, CvSize resolutionSize);
    Capture(string fileName, CvSize dispSize, CvSize resolutionSize);

    int channelNum;
    vector<IplImage*> channelframeList;

    void captureNext();

    ~Capture();

private:

    string m_fileName;
    vector<CvCapture*> m_channelList;

    CvSize m_resolutioSize;
    CvSize m_displaySize;

    void initChannelList(VIDEO_TYPE type);
    void initChannelImgList(CvSize sz);
    IplImage* getNextVideoFrame(CvCapture* pCapture);


};

#endif

capture.cpp

#include "capture.h"

Capture::Capture(int num, CvSize dispSize, CvSize resolutionSize) {

    channelNum = num;
    m_fileName = "";
    m_resolutioSize = resolutionSize;

    m_channelList.resize(channelNum);
    channelframeList.resize(channelNum);

    initChannelList(CAMMERA);
    initChannelImgList(dispSize);

}

Capture::Capture(string fileName, CvSize dispSize, CvSize resolutionSize) {

    channelNum = 1;
    m_fileName = fileName;
    m_resolutioSize = resolutionSize;

    m_channelList.resize(channelNum);
    channelframeList.resize(channelNum);

    initChannelList(VIDEOFILE);
    initChannelImgList(dispSize);

}

void Capture::captureNext() {

    for (int i = 0; i < channelNum; ++i) {

        IplImage* nextFrame = getNextVideoFrame(m_channelList[i]);
        IplImage* channelFrame = channelframeList[i];
        cvResize(nextFrame, channelFrame);

    }
}

void Capture::initChannelList(VIDEO_TYPE type) {

    if (type == CAMMERA) {

        for (int i = 0; i < channelNum; ++i) {

            m_channelList[i] = cvCreateCameraCapture(i);

            //set resolution
            cvSetCaptureProperty(m_channelList[i], CV_CAP_PROP_FRAME_WIDTH, m_resolutioSize.width);
            cvSetCaptureProperty(m_channelList[i], CV_CAP_PROP_FRAME_HEIGHT, m_resolutioSize.height);

            if ( !(m_channelList[i]) ) {
                cout << "failed to initialize video capture" << endl;
                exit(EXIT_FAILURE);

            }
        }

    } else if (type == VIDEOFILE) {

        const char* fileNameChar = m_fileName.c_str();
        m_channelList[0] = cvCreateFileCapture(fileNameChar);

        if ( !(m_channelList[0]) ) {
            cout << "failed to initialize video capture" << endl;
            exit(EXIT_FAILURE);
        }

    }

}

void Capture::initChannelImgList(CvSize sz) {

    for (int i = 0; i < channelNum; ++i)
        channelframeList[i] = cvCreateImage(sz, 8, 3);

}

IplImage* Capture::getNextVideoFrame(CvCapture* pCapture) {

    IplImage* nextFrame = cvQueryFrame(pCapture);

    if (!nextFrame) {
        cout << "failed to get a video frame" << endl;
        exit(EXIT_FAILURE);
    }

    return nextFrame;

}

Capture::~Capture() {

    for (int i = 0; i < channelNum; ++i) {
        cvReleaseImage( &(channelframeList[i]) );
        cvReleaseCapture(&m_channelList[i]);
    }

}

灰屏 :) 但现在我使用OpenCV的inputVideo,一切都正常工作。 - Krzysztof Kaczor

1

在Windows系统中,我尝试使用Python的OpenCV包时,发现相机无法正常工作,只显示灰屏。

通过调试器追踪,我发现有两个名为“Google Camera Adapter 0”和“Google Camera Adapter 1”的相机接口。

我通过以下步骤解决了相机输入问题:

  1. 进入“添加/删除程序”,卸载“Google Talk Plugin”
  2. 拔掉网络摄像头并重新插入,以安装新的驱动程序。

现在相机已经可以正常工作。

(请注意,我不确定步骤1是否重要,它可能会导致其他问题出现,因此建议您先尝试步骤2...)


0

这不是解决问题的正确方法。所以我来了:首先,隔离当前正在工作的相机ID。它是哪一个?-1、0、1?

其次,请检查函数的返回值,拜托了!如果有什么问题,你永远不会知道。

CvCapture* capture = NULL;
if ((capture = cvCaptureFromCAM(-1)) == NULL)
{
    fprintf(stderr, "ERROR: capture is NULL \n"); 
    return -1;
}

cvNamedWindow("mywindow", CV_WINDOW_AUTOSIZE);

cvQueryFrame(capture); // Sometimes needed to get correct data

while (1) 
{     
    IplImage* frame = cvQueryFrame(capture); // check return
    {
        fprintf( stderr, "ERROR: cvQueryFrame failed\n");
        break;
    }

    // At this point you already have the frame! There's no need to
    // repeat the thing 10x with cvGrabFrame and cvRetrieveFrame. 
    // You are probably sabotaging yourself doing this multiple times.

    cvShowImage("mywindow", frame); // Do not release the frame!

    int key = cvWaitKey(10);
    if (key  == 0x1b)
        break;
}    

cvReleaseCapture(&capture);   
cvDestroyWindow("mywindow");   

return 0;

我试图隔离相机ID,但是很奇怪...我在我的循环中添加了正确ID的cout,但如果我将其放入cvCaptureFromCAM中,它不起作用。只有当我重复这一行时才有效(第一次找不到相机)。当我第一次运行程序时,它可以毫无问题地找到设备。 使用您的代码时,输出显示“ERROR:cvQueryFrame失败”。相机在其他应用程序中正常工作。我正在使用Win 7。 - Krzysztof Kaczor
@SyntaxError 你使用的是哪个OpenCV版本? - karlphillip
2.2 - 我认为是最新版本。使用Visual Studio 2010。 - Krzysztof Kaczor
2
请查看此答案:https://dev59.com/gHRB5IYBdhLWcg3wF0HH#4920669 - karlphillip
在Windows下我必须使用 cvCaptureFromCAM(0) - karlphillip
我成功地使用videoInput库运行了它,但我找不到该项目的任何文档:/ 而且我想使用openCV,因为有大量的教程。我担心我的C++水平太菜了,无法将此代码重写为Windows :/ 以下是代码: - Krzysztof Kaczor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接