Opencv摄像头视频处理(还在完成中)

文章目录

  • opencv
  • QtRO(Qt remote objects)
    • rep 文件的产生(server & client 的信息交换接口)
  • 遇到的问题:
    • 子线程完成图像采集并发送主线程-遇到的bug
    • Qt线程相关问题与总结

opencv

  • Mat
    图像的存储容器。

  • 完成一个video设备录像的关键步骤

  1. 打开video设备,同时打开目标保存文件。
VideoCapture videoCap;
VideoWriter videoWrite;
videoCap.open(1);
videoWrite.open(".\\test.avi", CV_FOURCC('M','J','P','G'), 30.0, Size(640, 480), true);
  1. 每隔1ms,将一帧图像写入已经打开的视频文件
void videomonitorthread::run()
{
    QEventLoop loop;
    QTimer timer;
    timer.setInterval(0.001 *1000);
    connect(&timer, &QTimer::timeout, [&loop, this](){
        if(enableRun)
        {
            qDebug()<<"running exit"<<endl;
            loop.exit();
        }
        videoCap >> matFrame;
        if(!matFrame.empty())
       {
            videoWrite.write(matFrame);  //保存视频帧
            emit timerFrameSignal(matFrame);//发送到主线程通过ui显示
        }
    });
    timer.start();
    loop.exec();
    //关闭设备
    videoCap.release();
    videoWrite.release();//关闭打开的视频文件,否则视频文件可能无法打开
    timer.stop();
}

QtRO(Qt remote objects)

关键词 解释
acquire 获得
source 词汇解释:信息来源
本文代之服务端(功能提供节点)
Replica 词汇翻译:复制品
本文代之客户端实体

QtRO解释
QtRO本质上是一个点对点的通信网络。每个进程通过QRemoteObjectNode接入QtRO网络。功能提供节点(可以理解为服务器)需要使用QRemoteObjectHost将一个提供实际功能的QObject派生类注册(rep定义的函数接口,两边信息交换的接口)进QtRO网络中,然后其他使用该功能的程序则通过各自的QRemoteObjectNode连接到该Host上,然后acquire一个该功能对象的Replica。等到该Replica初始化好后,该程序就能够使用Replica中的信号、槽以及属性,就好像功能类就在本地一样。

QtRO关键步骤

  • Server端需要把功能类通过QRemoteObjectHost的enableRemoting方法共享出来
  • Client连接到该QRemoteObjectHost,然后acquire到Replica
  • QtRO会自动初始化该Replica,待初始化完后客户端就可以用该Replica

rep 文件的产生(server & client 的信息交换接口)

新建两个工程分别为clientPro, serverPro,新建.rep文件(定义所需要的信息交换接口),rep文件参考。
server 端.pro文件添加:
REPC_SOURCE +=
./Reps/CommonInterface.rep
client端.pro添加:
REPC_REPLICA +=
./Reps/CommonInterface.rep
server & client的.pro都添加 Qt += remoteobjects,编译构建后产生在构建目录下(两个头文件是不一样的,头文件内容如下)。
Opencv摄像头视频处理(还在完成中)_第1张图片

参考:(QtRO)实现进程间通信

遇到的问题:

子线程完成图像采集并发送主线程-遇到的bug

  • 问题 1:
    Q: Qt5.9 修改界面控件名称不生效;
    A: 删除Debug,重新构建,对比Debug目录下的ui文件和工程目录下的ui,发现Debug目录下ui文件中存在所修改的名称,但是工程目录下的没有,因此,备份工程目录下的文件,用Debug目录下的ui文件替换,编译正常。
  • 问题 2:
    Q: 在主线程th1 创建的子线程th2, th2中采用Qtimer + connect + eventloop 完成事件循环,当给出退出线程的条件时,程序报出如下警告。
 QObject::startTimer: Timers cannot be started from another thread

A: 在run之外创建的对象也属于主线程(当前子线程类中的对象除了run内部的都属于主线程),定时器相关的逻辑和对象只能用在一个线程中使用,因此不能将父线程的timer对象用于子线程中。

  • 问题 3:
    Q: 点击主窗口的X关闭程序时,提示系统崩溃了,如下:
QThread: Destroyed while thread is still running
20:13:27: 程序异常结束。

A: 当关闭主线程时,子线程还处于运行状态,因此,需要等待并将所有子线程关闭完成,最后再关闭主线程。

  • 问题 4:
    QtRO实现server&client发送数据时出错-遇到的bug
    提示:
    qt.remoteobjects: connectionToSource is null
    问题原因:
    server端的QRemoteObjectHost通过enableRemoting注册rep文件接口后才设定Url,导致host的url未生效,或者没有与共享接口完成某种绑定,因此client通过acquire获取Replica后,使用时找不到主机的共享接口。
    正常的顺序如下:
//server 侧
    //host完成对提供实际功能的Qobject派生类的注册
    pRemoteObj = new QRemoteObjectHost(this);//创建remotehost,设置主机url
    pRemoteObj->setHostUrl(QUrl(NODE_ADDRESS));
    pInterfaceObj = new CommonInterface(this);//host注册rep信息交互对象
    pRemoteObj->enableRemoting(pInterfaceObj);

Qt线程相关问题与总结

如下对象在线程中使用时,定义和逻辑只能在同一个线程中使用,否则会出现一些问题。

  • QTimer
  • QtRO
    如果source的QtRO对象定义在父线程中,source 通过rep的sig向client发送消息时,消息事发送不过去的,但是可以接收到client的消息(有知道原因的的伙伴可以留言,谢谢!)

你可能感兴趣的:(opencv,ui,qt5)