打开摄像头的方法在第一章里就讲到了,而且使用了多线程完成。所以这一章的内容就是将之前第一章的代码做移植,进行小幅度的修改,应用到当前系统上就可以了。
在UI界面上已经放好了用来显示摄像头信息的label
在项目中创建一个新的线程,用于处理摄像头有关的数据
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;
在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
有任何问题可以在下面给我留言!大家一起学习!