(四)加入摄像头的系统

打开摄像头的方法在第一章里就讲到了,而且使用了多线程完成。所以这一章的内容就是将之前第一章的代码做移植,进行小幅度的修改,应用到当前系统上就可以了。


在UI界面上已经放好了用来显示摄像头信息的label

(四)加入摄像头的系统_第1张图片

在项目中创建一个新的线程,用于处理摄像头有关的数据

class CamerWidget_camer_thread : public QThread
{
    Q_OBJECT
public:
    explicit CamerWidget_camer_thread(QObject *parent = 0);
    ~CamerWidget_camer_thread();

    void stop();

    QImage Mat2QImage(cv::Mat cvImg);
    void opencam();
    cv::Mat frame;
    cv::VideoCapture capture;
    struct CamerInfo_data camer_info_data;

public slots:

protected:
    void run();

signals:
    void camer_image_sig(struct CamerInfo_data);

private:
    volatile bool stopped;

};

具体的函数实现可以参考第一章的代码

自定义了一个新的结构体用于存放摄像头有关的数据

// opencv camer info struct
struct CamerInfo_data
{
    QImage image;
    double fps;
};

在线程中发射信号

emit camer_image_sig(camer_info_data); //emit image signal

在主线程中接收信号并更新显示

void CamerWidget::camer_updata(CamerInfo_data camer_info_data)
{
    ui->camer_label->setPixmap(QPixmap::fromImage(camer_info_data.image).scaled(ui->camer_label->size()));

    //this->update();
}

为了提高兼容性,在构造函数里对摄像头的设备结点进行了判断,如果存在设备节点才进行摄像头的处理,否则说明并没有识别到摄像头,显示错误信息。

QFile cam_dev("/dev/video0");
    if(cam_dev.open(QFile::ReadOnly))
    {
        cam_dev.close();
        camerwidget_camer_thread = new CamerWidget_camer_thread;
        //使用自定义结构体在信号槽中传递时需要先注册,否则会报错
        qRegisterMetaType("CamerInfo_data");

        connect(camerwidget_camer_thread,&CamerWidget_camer_thread::camer_image_sig,this,&CamerWidget::camer_updata);

        camerwidget_camer_thread->start();
    }
    else
    {
        ui->camer_label->setText("无摄像头设备信息");
        qDebug() << "No file named /dev/video0";
    }

使用QFile尝试打开设备节点,如果没有该设备结点或者打开失败,则会进入else中执行。

同样注意,因为在信号槽中使用了自定义的结构体,需要先注册

//使用自定义结构体在信号槽中传递时需要先注册,否则会报错
qRegisterMetaType("CamerInfo_data");

另外注意在析构函数中释放线程指针,否则容易导致内存泄漏。有关于指针的幅值,特别是在new的时候没有指定父对象的指针,一定要进行内存释放。

if(camerwidget_camer_thread->isRunning())
    {
        camerwidget_camer_thread->stop();
        camerwidget_camer_thread->wait();
        camerwidget_camer_thread->quit();
    }
delete camerwidget_camer_thread;

测试

(四)加入摄像头的系统_第2张图片

 

补充

在PC端运行程序时,发现在关闭摄像头的时候会报错,但是再次打开也还是可以继续运行,但是在ARM板上运行时发现,这样做会导致程序崩溃,系统死机,报错信息如下。

GStreamer-CRITICAL **: gst_element_make_from_uri: assertion 'gst_uri_is_valid (uri)' failed
GStreamer: Error opening bin: no source element for URI "/dev/video0"

这是由于后端解码出现了问题,在QT下后端解码可以使用 vcl,mplayer,xine,gstreamer,在qt中使用gstreamer这个后端解码

apt-get install phonon-backend-gstreamer
apt-get install mplayer
apt-get install v4l-utils
v4l2-ctl -d /dev/video0 -D

 

Qt完整源码放在github上,有需要可以自行下载。 代码名称为190517.zip

https://github.com/ljy980330/opencv_face_sys

 

有任何问题可以在下面给我留言!大家一起学习!

你可能感兴趣的:(qt+opencv人脸识别项目)