【问题标题】:OpenCV : How to display webcam capture in windows form application?OpenCV:如何在 Windows 窗体应用程序中显示网络摄像头捕获?
【发布时间】:2011-02-21 06:39:50
【问题描述】:

通常我们在opencv窗口中显示网络摄像头或视频运动:

      CvCapture* capture = cvCreateCameraCapture(0);
            cvNamedWindow( "title", CV_WINDOW_AUTOSIZE );
   cvMoveWindow("title",x,y);
   while(1) 
   {
    frame = cvQueryFrame( capture );
    if( !frame )
    {
     break;
    }
    cvShowImage( "title", frame );
    char c = cvWaitKey(33);
    if( c == 27 )
    {
     break;
    }
   }

我尝试使用pictureBox,它成功地以windows形式显示图像:

 pictureBox1->Image = gcnew System::Drawing::Bitmap( image->width,image->height,image->widthStep,System::Drawing::Imaging::PixelFormat::Undefined, ( System::IntPtr ) image-> imageData);

但是当我尝试从视频中显示捕获的图像时它不起作用,这是源代码:

            CvCapture* capture = cvCreateCameraCapture(0);
   while(1) 
   {
    frame = cvQueryFrame( capture );
    if( !frame )
    {
     break;
    }
    pictureBox1->Image = gcnew System::Drawing::Bitmap( frame->width,frame->height,frame->widthStep,System::Drawing::Imaging::PixelFormat::Undefined, ( System::IntPtr ) frame-> imageData);
    char c = cvWaitKey(33);
    if( c == 27 )
    {
     break;
    }
   }

有没有办法使用 windows 窗体而不是 opencv windows 来显示视频或网络摄像头?

还是我的代码有问题? 谢谢你的帮助.. :)

【问题讨论】:

    标签: c++ forms video opencv webcam


    【解决方案1】:

    您可能要考虑的另一个选项是使用 emgu。这是带有 winforms 控件的 opencv 的 .Net 包装器。

    【讨论】:

      【解决方案2】:

      我不知道你是否会喜欢这个,但你可以使用 OpenGL 在其他窗口中显示视频流,而不是 opencv 提供的窗口。 (捕获框架并将其显示在矩形上......或类似的东西......)

      【讨论】:

        【解决方案3】:

        当您从相机捕获图像时,应该知道像素格式,它很可能是 24 位 BGR 的格式。 System::Drawing::Imaging::PixelFormat::Format24bppRgb 将是最接近的格式,但您可能会得到奇怪的颜色显示。重新排列颜色分量将解决此问题。

        其实这里有.net版本的opencv库: http://code.google.com/p/opencvdotnet/ 和这里: http://www.emgu.com/wiki/index.php/Main_Page

        希望对您有所帮助!

        【讨论】:

          【解决方案4】:

          建议:使用VideoInput 而不是 CvCapture(CvCapture 是 highgui 库的一部分,该库不用于生产用途,仅用于快速测试)。是的,VideoInput 主页看起来很奇怪,但是这个库非常值得。

          这里是一个使用 VideoInput 的快速示例(从 VideoInput.h 文件中提取):

          //create a videoInput object
          videoInput VI;
          
          //Prints out a list of available devices and returns num of devices found
          int numDevices = VI.listDevices();  
          
          int device1 = 0;  //this could be any deviceID that shows up in listDevices
          int device2 = 1;  //this could be any deviceID that shows up in listDevices
          
          //if you want to capture at a different frame rate (default is 30) 
          //specify it here, you are not guaranteed to get this fps though.
          //VI.setIdealFramerate(dev, 60);    
          
          //setup the first device - there are a number of options:
          
          VI.setupDevice(device1);                          //setup the first device with the default settings
          //VI.setupDevice(device1, VI_COMPOSITE);              //or setup device with specific connection type
          //VI.setupDevice(device1, 320, 240);                  //or setup device with specified video size
          //VI.setupDevice(device1, 320, 240, VI_COMPOSITE);  //or setup device with video size and connection type
          
          //VI.setFormat(device1, VI_NTSC_M);                 //if your card doesn't remember what format it should be
                                                              //call this with the appropriate format listed above
                                                              //NOTE: must be called after setupDevice!
          
          //optionally setup a second (or third, fourth ...) device - same options as above
          VI.setupDevice(device2);                          
          
          //As requested width and height can not always be accomodated
          //make sure to check the size once the device is setup
          
          int width   = VI.getWidth(device1);
          int height  = VI.getHeight(device1);
          int size    = VI.getSize(device1);
          
          unsigned char * yourBuffer1 = new unsigned char[size];
          unsigned char * yourBuffer2 = new unsigned char[size];
          
          //to get the data from the device first check if the data is new
          if(VI.isFrameNew(device1)){
              VI.getPixels(device1, yourBuffer1, false, false);   //fills pixels as a BGR (for openCV) unsigned char array - no flipping
              VI.getPixels(device1, yourBuffer2, true, true);     //fills pixels as a RGB (for openGL) unsigned char array - flipping!
          }
          
          //same applies to device2 etc
          
          //to get a settings dialog for the device
          VI.showSettingsWindow(device1);
          
          
          //Shut down devices properly
          VI.stopDevice(device1);
          VI.stopDevice(device2);
          

          【讨论】:

          • 同一信息的视频输出和背景图同时处理,对性能影响大吗?
          • 不确定我是否正确理解了您的问题。据我记得,抓取的图像并没有直接复制到屏幕缓冲区。但是 VideoInput 是基于 DirectShow 的,这意味着两件事:它真的很快,而且它是一个 PITA 来编译(您需要从 Microsoft 获得相应的 DirectShow 实现)。上次我尝试时,我必须获得旧版本的 DirectShow 库。但是,下载中提供了 VideoInput 库的编译版本。
          猜你喜欢
          • 2012-03-23
          • 1970-01-01
          • 2023-04-08
          • 2015-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-06
          • 2013-08-02
          相关资源
          最近更新 更多