使用Qt+OpenCV+VideoInput 显示摄像头图像

缘由:

最近使用Qt+openCV获取摄像头的图像

但是仅仅只是使用openCV自带的方法显示图像时,发现计算机CPU使用率比较高,最主要的一点是摄像头驱动自带的设置图像参数的无法直接调用出来

网上查找了很多资料发现 openCV内部是使用了videoInput类的方法实现的.但是没有引用它自身的方法.

经过几天的研究,成功使用videoinput显示摄像头图像,并且可以弹出摄像头驱动自带的图像设置窗口,

不过好像那种USB免驱动的摄像头无法打开,因为用不到就没深入探究.

工具环境:

openCV2.48

Qt5.2.1 用的是VS2010的编译器

videoInput 0.1995 

源码及程序点击这里

步骤:

1.新建一个Qt工程

做界面什么的,这个不是重点,不详述了

2.解压videoInput 并配置openCV环境


videoinput解压出来有源码和已经编译好的库

我用的是vs2008编译好的库

然后再Qt,pro文件中添加openCV以及video的路径

INCLUDEPATH += D:\opencv\build\include
CONFIG(release,debug|release){
    LIBS += D:\opencv\build\x86\vc10\lib\opencv_calib3d248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_contrib248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_core248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_features2d248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_flann248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_gpu248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_highgui248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_imgproc248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_legacy248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_ml248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_nonfree248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_objdetect248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_ocl248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_photo248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_stitching248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_superres248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_ts248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_video248.lib \
            D:\opencv\build\x86\vc10\lib\opencv_videostab248.lib \
            D:\opencv\build\include\opencv2\videoInput\videoInput.lib\
}
CONFIG(debug,debug|release){
    LIBS += D:\opencv\build\x86\vc10\lib\opencv_calib3d248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_contrib248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_core248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_features2d248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_flann248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_gpu248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_highgui248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_imgproc248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_legacy248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_ml248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_nonfree248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_objdetect248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_ocl248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_photo248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_stitching248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_ts248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_superres248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_ts248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_video248d.lib \
            D:\opencv\build\x86\vc10\lib\opencv_videostab248d.lib \
D:\opencv\build\include\opencv2\videoInput\videoInput.lib\ }
然后将include中的videoInput.h文件添加到项目中,

3.进行操作

我将video常用的类写道一个新的类中.引出了一些常用的方法,直接调用videoinput也是可以的

    int getTotalCameraCount(); //获得总共可用摄像头数量
    char * getDeviceName(int deviceID); //根据摄像头编号获取驱动名称
    void showSettingsWindow(int deviceID);//显示属性设置窗口
    bool setupDevice(int deviceID, int w, int h); //配置摄像设备
    bool setupDevice(int deviceID); //配置摄像设备
    bool isFrameNew(int deviceID); //是否有新的一帧
    void stopDevice(int deviceID);//停止摄像头工作
    unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false );//获取图像数据
全部的方法可以看videoInput.h头文件中的源码

//turns off console messages - default is to print messages
		static void setVerbose(bool _verbose);
		
		//Functions in rough order they should be used.
		static int listDevices(bool silent = false);

		//needs to be called after listDevices - otherwise returns NULL
		static char * getDeviceName(int deviceID);
		
		//choose to use callback based capture - or single threaded
		void setUseCallback(bool useCallback);	
		
		//call before setupDevice
		//directshow will try and get the closest possible framerate to what is requested
		void setIdealFramerate(int deviceID, int idealFramerate);

		//some devices will stop delivering frames after a while - this method gives you the option to try and reconnect
		//to a device if videoInput detects that a device has stopped delivering frames. 
		//you MUST CALL isFrameNew every app loop for this to have any effect
		void setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect);
		
		//Choose one of these four to setup your device
		bool setupDevice(int deviceID);
		bool setupDevice(int deviceID, int w, int h);

		//These two are only for capture cards
		//USB and Firewire cameras souldn't specify connection 
		bool setupDevice(int deviceID, int connection);	
		bool setupDevice(int deviceID, int w, int h, int connection); 
		
		//If you need to you can set your NTSC/PAL/SECAM
		//preference here. if it is available it will be used.
		//see #defines above for available formats - eg VI_NTSC_M or VI_PAL_B
		//should be called after setupDevice
		//can be called multiple times
		bool setFormat(int deviceNumber, int format);	
				
		//Tells you when a new frame has arrived - you should call this if you have specified setAutoReconnectOnFreeze to true
		bool isFrameNew(int deviceID); 
		
		bool isDeviceSetup(int deviceID);
		    
		//Returns the pixels - flipRedAndBlue toggles RGB/BGR flipping - and you can flip the image too
		unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false);
		
		//Or pass in a buffer for getPixels to fill returns true if successful.
		bool getPixels(int id, unsigned char * pixels, bool flipRedAndBlue = true, bool flipImage = false);
		
		//Launches a pop up settings window
		//For some reason in GLUT you have to call it twice each time. 
		void showSettingsWindow(int deviceID);
		
		//Manual control over settings thanks..... 
		//These are experimental for now.
		bool setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
		bool setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags = NULL);
		bool getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue);

		bool setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
		bool setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags = NULL);
		bool getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long ¤tValue, long &flags, long &defaultValue);

		//bool setVideoSettingCam(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);

		//get width, height and number of pixels
		int  getWidth(int deviceID);
		int  getHeight(int deviceID);
		int  getSize(int deviceID);
		
		//completely stops and frees a device
		void stopDevice(int deviceID);
		
		//as above but then sets it up with same settings
		bool restartDevice(int deviceID);

videoinput使用起来很简单

(1)将可以可以使用的摄像头名称添加到列表框中,

  camera = new MyCamera();
    //设置可用摄像头列表
    int count =  camera->getTotalCameraCount();
    for(int i=0;i<count;i++){
        QString name = camera->getDeviceName(i);
        ui->comboBoxCamreaList->addItem(name);
    }

(2) 弹出摄像头显示界面,这个方法必须在摄像头打开后才有效

//显示摄像头设置界面
    camera->showSettingsWindow(ui->comboBoxCamreaList->currentIndex());

(3)根据传入的cv::Mat 对象在QLabel上绘制摄像头图像

void MainWindow::display(cv::Mat &mat)
{
     cv::Mat rgb = mat;
       QImage img;
       if(mat.channels()==3)
       {
          // cv::cvtColor(mat,rgb,CV_BGR2RGB);
           img = QImage((const uchar*)(rgb.data),rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
       }
       else
       {
           img = QImage((const uchar*)(mat.data),mat.cols,mat.rows,mat.cols*mat.channels(),QImage::Format_Indexed8);
       }

    ui->labelImage->setPixmap(QPixmap::fromImage(img));
  //  ui->labelImage->resize(ui->labelImage->pixmap()->size());
    ui->labelImage->show();
}

(4)打开选中的摄像头,并且开启一个定时器用来定时获取图像

//打开摄像头
void MainWindow::on_actionCamreaOpen_triggered()
{
    int width = 800;
    int height = 600;
    mat = cv::Mat(height,width,CV_32SC3);
    deviceID = ui->comboBoxCamreaList->currentIndex();
    camera->setupDevice(deviceID,width,height);//配置摄像机 设置宽为800X600
    timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(startLoopSlot()));
    timer->start(30);
}

(5)定时器开启后调的用图像循环,获取新的一帧的数据,并且调用display方法在QLabel上刷新显示

//图像显示循环
void MainWindow::startLoopSlot()
{
    if(camera->isFrameNew(deviceID)){
       mat.data = camera->getPixels(deviceID,flipRedAndBlue,flipImage);
        display(mat);
   }
}

(6)摄像头图像的关闭

//关闭摄像头
void MainWindow::on_actionCameraClose_triggered()
{
    timer->stop();
    delete timer;
    timer = NULL;
    camera->stopDevice(deviceID);
    qDebug()<<"close Camrea";
}









你可能感兴趣的:(qt,图像,摄像头,opencv2,videoInput)