除了监控专用的摄像头以外,有一些应用场景用的还是USB摄像头,甚至还有一些单片机或者开发板上用的CMOS摄像头,而Qt在嵌入式领域应用相当广,所以用Qt来读取加载显示USB摄像头和CMOS摄像头,也是非常多Qter做过的事情,qt本身就封装了qcamera类,专用于本地摄像头的读取显示,这个类主要是在windows系统和安卓系统比较好使,在嵌入式上歇菜,而且安卓上widget的qcamera也不好使,要用qml的camera才好使,所以开发人员很多时候,就是在找坑填坑,找到一种最佳的适中方案,比如我自己做过的一个手机app,需要调用手机的摄像头,前置后置还要能切换,抓图做一些处理,用的就是qml嵌入到widget,通过信号槽来通信。
用Qt来加载USB摄像头解码,主要就三种方案,一种是Qt自带的,一种是ffmpeg来处理,一种是v4l2框架,每种方案都各自有优缺点和对应的应用场景,比如Qt自带的就非常适合windows下的只需要显示摄像头的场景,代码简单Qt内置使用方便,如果是需要拿到每张图片自己还要做分析处理比如人脸识别啥的,用ffmpeg是最好的,速度快资源占用低,可以自己GPU绘制,爽得很,如果是嵌入式linux的话,那用v4l2框架处理是最适合的,原生的通用api框架。
QCamera方案处理流程:
//widget版本
static void getCameraInfo(QStringList &deviceNames, QStringList &descriptions)
{
#ifndef __arm__
#if (QT_VERSION > QT_VERSION_CHECK(5,5,0))
deviceNames.clear();
descriptions.clear();
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
if (cameras.count() == 0) {
qDebug() << TIMEMS << "not find USBCamera";
} else {
foreach (QCameraInfo camera, cameras) {
deviceNames << camera.deviceName();
descriptions << camera.description();
}
}
#endif
#endif
}
void CameraThread::stateChanged()
{
#ifdef __arm__
#else
#if (QT_VERSION > QT_VERSION_CHECK(5,5,0))
if (camera->state() == QCamera::ActiveState) {
//输出当前设备支持的分辨率
QList<QSize> sizes = camera->supportedViewfinderResolutions();
emit resolutions(sizes);
//重新设置分辨率
QCameraViewfinderSettings set;
set.setResolution(cameraWidth, cameraHeight);
camera->setViewfinderSettings(set);
}
#endif
#endif
}
bool CameraThread::init()
{
#ifdef __arm__
#else
#if (QT_VERSION > QT_VERSION_CHECK(5,5,0))
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
if (cameras.count() == 0) {
qDebug() << TIMEMS << "not find USBCamera";
return false;
} else {
QWidget *frm = (QWidget *)parent();
camera = new QCamera(frm);
connect(camera, SIGNAL(stateChanged(QCamera::State)), this, SLOT(stateChanged()));
viewfinder = new QCameraViewfinder(frm);
viewfinder->installEventFilter(this);
camera->setViewfinder(viewfinder);
QRect rect = frm->rect();
viewfinder->setAspectRatioMode(fillImage ? Qt::IgnoreAspectRatio : Qt::KeepAspectRatio);
int offset = borderWidth * 1 + 0;
viewfinder->setGeometry(offset / 2, offset / 2, rect.width() - offset, rect.height() - offset);
viewfinder->setVisible(true);
imageCapture = new QCameraImageCapture(camera);
connect(imageCapture, SIGNAL(imageCaptured(int, QImage)), this, SLOT(displayImage(int, QImage)));
return true;
}
#endif
#endif
}
//qml版本
import QtQuick 2.0
import QtMultimedia 5.6
Item {
signal receiveImage();
Video {
id: video
anchors.fill: parent
//source: "rtsp://192.168.1.247:554/av0_0"
source: "g:/mp4/1.mp4"
MouseArea {
anchors.fill: parent
onClicked: {
video.play()
}
}
focus: true
Keys.onSpacePressed: video.playbackState == MediaPlayer.PlayingState ? video.pause() : video.play()
Keys.onLeftPressed: video.seek(video.position - 5000)
Keys.onRightPressed: video.seek(video.position + 5000)
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。