Qt5&OpenCV3 UDP协议实现实时视频传输与通信

2023-05-16

打算在树莓派上挂载摄像头,通过WIFI模块传输到上位机。局域网内带宽不是问题,为了保证实时性,也没有必要进行复杂的视频编码和解码,于是通过截图然后使用UDP协议传输应该是可以的。所以最近试探性地使用了Qt和opencv进行测试,上位机接收到视频帧后使用Haar人脸识别后再传回一个坐标给下位机,结果还行。

cv界女神lena

1.下位机(图像采集端)

Qt中使用QUdpSocket类来发送和接收UDP数据报。Socket就是套接字,简单来说就是一个IP地址加上port端口号。它支持IPv4广播,简单起见这里使用广播模式。VideoCapture类用于获取视频或者摄像头设备。

private:
    Ui::Sender *ui;
    QUdpSocket *sender;
    QUdpSocket *receiver;
    cv::Mat frame;
    int timerID;
    cv::VideoCapture capture;
  • 在.h文件中声明两个QUdpSocket和QVideoCapture成员变量
Sender::Sender(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Sender)
{
    ui->setupUi(this);
    sender = new QUdpSocket(this);
    capture.open(0);
    if(!capture.isOpened())
    {
        cout << "open failed" <<endl;
    }
    int delay =1000/10;
    timerID = this->startTimer(delay);

    receiver = new QUdpSocket(this);
    receiver->bind(45455, QUdpSocket::ShareAddress);
    connect(receiver, &QUdpSocket::readyRead, this, &Sender::processPendingDatagram);
}
  • VideoCapture对象使用open()方法来打开视频或者摄像头。传入int是指定设备ID,可以在设备管理器查找,一般是0。也可以传入路径来打开视频文件。startTimer方法是打开Qt的软件定时器,参数是毫秒,这里用来采集摄像头的图像。1000/10即10FPS。

  • 为了方便处理,这里创建两个QUdpSocket对象,一个用于传输,一个用于接收,并分开两个端口。bind方法第一个参数是端口号,QUdpSocket::ShareAddress指允许其他服务器绑定到相同的地址和端口上。

  • 每次有数据报到来时,QUdpSocket都会发射readyRead()信号。连接这个信号到自定义的槽中,便可进行读取操作。

void Sender::timerEvent( QTimerEvent *event)
{
    if(event->timerId() == timerID)
    {
        if(capture.isOpened())
        {
            capture.read(frame);
        }
        cvtColor(frame,frame,CV_BGR2RGB); //BGRtoRGB
        QImage image((unsigned char *)(frame.data),
                         frame.cols,frame.rows,
                         QImage::Format_RGB888);
        ui->label->setPixmap(QPixmap::fromImage(image));
        ui->label->resize(image.width(),image.height());

        QByteArray byte;
        //字节数组 要进行传输必须先转换成这个格式
        QBuffer buff(&byte);
        // 建立一个用于IO读写的缓冲区
        image.save(&buff,"JPEG");
        // image先向下转为byte的类型,再存入buff

        QByteArray compressByte = qCompress(byte,1);
        //数据压缩算法
        QByteArray base64Byte = compressByte.toBase64();

        //数据加密算法
        sender->writeDatagram(base64Byte.data(),base64Byte.size(),
                             QHostAddress::Broadcast, 45454);
    }
}
  • VideoCapture类使用read()方法来读取视频帧,存入一个Mat中。Mat存储图像默认是BGR编码,为了方便转换为Qimage格式进行操作,需要使用cvtColor改变编码模式。

  • Mat中的data()方法返回数据的一个uchar型的指针。使用这个指针,指定行数列数和编码模式,就可以构造一个Qimage对象,并在Qlabel中显示出来。

  • QBuffer类用于各种IO的读写。Qimagesave()方法将数据转为byte并存入一个QBuffer对象中。对byte对象进行简单的编码后便可进行发送。

  • 类似的,QByteArray有一个data()方法来返回uchar指针。writeDatagram用于发送数据报,QHostAddress::Broadcast指使用广播模式。

void Sender::processPendingDatagram()
{
    QByteArray datagram;

    // 让datagram的大小为等待处理的数据报的大小,这样才能接收到完整的数据
    datagram.resize(receiver->pendingDatagramSize());

    // 接收数据报,将其存放到datagram中
    receiver->readDatagram(datagram.data(), datagram.size());

    ui->label_2->setText(datagram);
}
  • 自定义的槽用于接收数据报。pendingDatagramSize()获得数据报的大小。readDatagram将数据存入一个QByteArray对象中。

2.上位机端(视频处理端)

Receiver::Receiver(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Receiver)
{
    ui->setupUi(this);
    sender = new QUdpSocket(this);
    receiver = new QUdpSocket(this);
    receiver->bind(45454, QUdpSocket::ShareAddress);
    connect(receiver, &QUdpSocket::readyRead, this, &Receiver::processPendingDatagram);
}

与发送端类似。

void Receiver::processPendingDatagram()
{
    QByteArray datagram;

    // 让datagram的大小为等待处理的数据报的大小,这样才能接收到完整的数据
    datagram.resize(receiver->pendingDatagramSize());

    // 接收数据报,将其存放到datagram中
    receiver->readDatagram(datagram.data(), datagram.size());

    QByteArray decryptedByte;
    decryptedByte=QByteArray::fromBase64(datagram.data());
    QByteArray uncompressByte=qUncompress(decryptedByte);
    QImage image;
    image.loadFromData(uncompressByte);

    Mat matImage(image.height(),image.width(),CV_8UC4,(void*)image.constBits(),
                 image.bytesPerLine());
}
  • 解码解压后,需要将QImage对象转为Mat用于识别。这里使用的是Mat一个比较复杂的重载构造。第三个参数是数据类型,Qimage中的数据是ARGB888,占32位。第四个参数需要一个指向数据块的指针,constBits方法返回一个void指针。第四个参数需要一行的数据量,bytePerLine()方法可以获取。
    Mat matImage_gray;
    char itc[10];

    if(frameCount >= 5)
    {
        cvtColor(matImage, matImage_gray, CV_BGR2GRAY);//转为灰度图
        equalizeHist(matImage_gray, matImage_gray);//直方图均衡化,增加对比度方便处理

        CascadeClassifier face_cascade;    //载入分类器

        if (!face_cascade.load(FACE_CLASSIFIER_PATH))
        {
            cout << "Load haarcascade_frontalface_alt failed!" << endl;
        }

        //检测关于脸部位置
        face_cascade.detectMultiScale(matImage_gray, faceRect, 1.1, 2, 0, Size(30, 30));
        for (size_t i = 0; i < faceRect.size(); i++)
        {
            //用矩形画出检测到的位置
            rectangle(matImage, faceRect[i], Scalar(0, 0, 255));      
            sprintf(itc,"%d,%d",(faceRect[i].br().x+faceRect[i].tl().x)/2,
                    (faceRect[i].br().y+faceRect[i].tl().y)/2);
            cout << itc <<endl;
            sender->writeDatagram(itc,7,QHostAddress::Broadcast, 45455);
        }
        frameCount=0;
        cvtColor(matImage,matImage,CV_BGR2RGB); //BGRtoRGB
        image = QImage((unsigned char *)(matImage.data),
                         matImage.cols,matImage.rows,
                         QImage::Format_RGB888);
        //sender->write()
    }
    else
    {
        for (size_t i = 0; i < faceRect.size(); i++)
        {
            //用矩形画出检测到的位置
            rectangle(matImage, faceRect[i], Scalar(0, 0, 255));      
        }
        cvtColor(matImage,matImage,CV_BGR2RGB); //BGRtoRGB
        image = QImage((unsigned char *)(matImage.data),
                         matImage.cols,matImage.rows,
                         QImage::Format_RGB888);
        frameCount++;

    }
    ui->label->setPixmap(QPixmap::fromImage(image));
    ui->label->resize(image.width(),image.height());
}

这里使用机器学习算法级联增强分类器Haar特征图像模型。opencv官方例程中已经帮我们训练好了,直接使用即可。

  • 识别需要一定时间,这里每5帧处理一次。
  • FACE_CLASSIFIER_PATH是官方例程中的xml文件路径
  • 将检测到的(人脸)矩形中心传回下位机端

3.实验结果

上位机端

下位机端,左下角是坐标

ok,实验结果还是很成功的,下一步就是移植到树莓派上了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt5&OpenCV3 UDP协议实现实时视频传输与通信 的相关文章

  • 白盒交换机NOS列表(picos/SnapRoute/ONL)

    WIKI NOS xff1a https en wikipedia org wiki Network operating system Examples JUNOS used in routers and switches from Jun
  • powershell

    常用单行命令 目录 查看当前目录的大小 xff0c 并排序输出 du h max depth 61 1 sort nr 自动选择单位 du m max depth 61 1 sort nr 选择M为单位 转载于 https www cnbl
  • 私有云对企业来说有什么好处

    企业是一个受控集团 xff0c 只有良好的管理 决策 xff0c 一个企业才有成功的希望 xff0c 所以管理在企业中占有重要的地位 私有云的使用是一只无形的手 xff0c 它控制着日常工作中的资源和效率 1 企业拥有基础设施 xff0c
  • JavaScript禁用页面刷新

    JavaScript禁用页面刷新代码如下 xff1a 禁用F5刷新 document onkeydown 61 function if event keyCode 61 61 116 event keyCode 61 0 event can
  • java 整除(/) 求余(%) 运算

    1 java 整除 求余 运算 1 求余 System out println 11 2 顾名思义就是11除2的余数 gt 1 System out println 11 2 结果 gt 1 System out println 11 2
  • C# 解决窗体闪烁

    C 解决窗体闪烁 在Windows窗体上造成 闪烁 的窗体上有很多控制 造成这种闪烁的原因有两个 xff1a 1 当控件需要被绘制时 xff0c Windows发送一个控件两个消息 第一个 xff08 WM ERASEBKGND xff09
  • OVN – OVN OpenStack(二)

    OpenStack networking ovn 项目为Neutron提供了一个基于ML2的OVN插件 xff0c 它使用OVN组件代替了各种Neutron的Python agent xff0c 也不再使用 RabbitMQ xff0c 而
  • 飞秋无法显示局域网好友

    1 飞秋无法显示局域网好友 无法查看网上邻居 无法适用共享打印机的问题是由于开启了 局域网隐身 的缘故 xff0c 打开 360安全卫士 xff1e 功能大全 xff1e 网络优化 xff1e 流量防火墙 xff1e 局域网防护 xff0c
  • pandas 按照某一列进行排序

    pandas排序的方法有很多 xff0c sort values表示根据某一列排序 pd sort values 34 xxx 34 inplace 61 True 表示pd按照xxx这个字段排序 xff0c inplace默认为False
  • 关系数据库和NoSQL结合使用:MySQL + MongoDB

    Home Page 作者使用一个案例来说明MySQL 43 MongoDB结合使用 xff0c 发挥各自所长 xff0c 并且认为他们互补性很强 当然 xff0c 这其中不可避免引入DDD中的编程设计模式 Repository仓储模式 xf
  • 查看网卡信息及状态和网卡日志信息

    查看网卡信息 1 mii tool v w em1 em2 l0 em1 negotiated 100baseTx FD link ok product info vendor 00 aa 00 model 57 rev 1 basic m
  • 筛选出sql 查询结果中 不包含某个字符

    select from table1 where patindex 39 关键字 39 aa 61 0 select from table1 where charindex 39 关键字 39 aa 61 0 select from tab
  • IE8正式版引发VS2005和VS2008添加变量向导出错的解决方案

    1 解决办法1 xff1a 2 卸载IE8 3 解决办法2 xff1a xff08 自己使用的方法 xff09 4 5 打开注册表编辑器 6 7 选择 HKEY CURRENT USER Software Microsoft Windows
  • Visual Studio 2010中文旗舰版+大家所关心的

    下载地址 xff08 VS2010不含MSDN xff09 xff1a http download microsoft com download 2 4 7 24733615 AA11 42E9 8883 E28CDCA88ED5 X16
  • CSS列表

    CSS列表属性可以放置 改变列表项的标志 xff0c 或者将图像作为列表项标志 list style xff1a 简写属性 用于把所有用于列表的属性设置在一个声明中 list style image xff1a 将图像设置为列表项的标志 U
  • Lodash源码讲解-compact函数

    原文首发于Lodash源码讲解 这是我们阅读Lodash源码的第3篇博客 xff0c 在这篇文章里我们来学习一下Lodash的compact方法 compact函数内部没有依赖别的函数 xff0c 让我们先来看一下compact函数的源码
  • CentOS 6.5下Squid代理服务器的安装与配置

    一 系统环境 操作系统 xff1a CentOS release 6 5 Squid版本 xff1a squid 3 1 10 20 el6 5 3 x86 64 SELINUX 61 disabled HTTP Service stope
  • 修改VNCSERVER的分辨率

    使用VNC远程连接时 xff0c 最大化窗口后仍旧在中间显示一个小屏幕 xff0c 并没有随着窗口最大化 xff0c 解决该问题需要首先在VNC窗口标题栏右键 gt Options gt Scaling 选择第二项 xff1a Scale
  • XMLHttpRequest - 原始AJAX初步

    我们知道 xff0c 传统的Web应用是request response形式的 xff0c 即浏览器向服务器发送请求 xff0c 服务器进行处理 xff0c 然后再对浏览器响应 这种形式最大的缺点就是 xff1a 客户端需要等服务器处理完之
  • Python面向对象编程 - 一个记事本程序范例(二)

    给程序加上控制台菜单 menu py import sys from notebook import Notebook Note class Menu 39 39 39 Display a menu and respond to choic

随机推荐

  • 个人代码库の自动粘合桌面边缘

    using System Windows Forms using System namespace public partial class form 必要事件 xff1a No 1 xff1a 窗体的 Move 事件 No 2 xff1a
  • 完全参照系统自带的DatePickerDialog、TimePickerDialog的源代码仿写的DateTimePickerDialog...

    完全参照系统自带的DatePickerDialog TimePickerDialog的源代码仿写的DateTimePickerDialog 具有同时选择日期 时间的功能 在2 2 2 3平台 xff0c 显示的效果可能会有一个大背景框在后面
  • Tracking your habits in Org-mode

    纯属记录 在org mode中 xff0c 你可以跟踪你的周期性事务或辅助培养习惯 xff0c 比如每天阅读半小时 xff0c 每天完成后org mode会予以记录 如果你正计划每月培养一个好习惯 xff0c 也可以使用这个功能来记录你的完
  • 算法的力量

    算法的力量 李开复 真正学懂计算机的人 xff08 不只是 编程匠 xff09 都对数学有相当的造诣 xff0c 既能用科学家的严谨思维来求证 xff0c 也能用工程师的务实手段来解决问题 而这种思维和手段的最佳演绎就是 算法 虽然在摩尔定
  • Xstream序列化实体

    Java序列化的日期为是很标准 xff0c XStream中转换为标准的做法 import java text DateFormat import java text ParseException import java text Simp
  • Booksort 启发式函数很重要h(s1)<=h(s2)+cost(s1,s2);

    Problem Description The Leiden University Library has millions of books When a student wants to borrow a certain book he
  • FreeBSD的基本系统下Shell设置(转)

    FreeBSD的基本系统下Shell设置 转 64 more 64 命令解释程序shell是与用户关系最密切的应用程序 xff0c 用户主要通过shell使用系统 在每次登录系统之后 xff0c 就启动了一个与用户交互的shell xff0
  • 20050410:他们不过是一群政客

    从来就没有把台湾人民的利益放在眼里 xff0c 甚至不惜拿他们来做挡箭牌 xff0c 一边还对日本谄媚有加 转载于 https www cnblogs com yidinghe archive 2005 04 10 134987 html
  • 排列组合公式

    注 xff1a 排列与元素的顺序有关 xff0c 组合与顺序无关 xff0e 如231与213是两个排列 xff0c 2 xff0b 3 xff0b 1的和与2 xff0b 1 xff0b 3的和是一个组合 xff0e 1 xff0e 排列
  • Mybatis初始化机制

    对于任何框架而言 xff0c 在使用前都要进行一系列的初始化 xff0c MyBatis也不例外 本章将通过以下几点详细介绍MyBatis的初始化过程 1 MyBatis的初始化做了什么 2 MyBatis基于XML配置文件创建Config
  • ValidationSummary控件

    ValidationSummary控件用于在页面中的一处地方显示所有验证错误的列表 这个控件在使用大的表单时特别有用 如果用户在页面底部的表单字段中输入了错误的值 xff0c 那么这个用户可能永远也看不到错误信息 不过 xff0c 如果使用
  • 数据特征分析——概述

    一 6个基础分析思路 xff1a 1 分布分析 2 对比分析 3 统计分析 4 帕累托分析 5 正态性检验 6 相关性分析 二 分布分析 分布分析 xff1a 研究数据的分布特征和分布类型 xff0c 分定量数据 定性数据区分基本统计量 三
  • Filebeat 6.0 把日志直接输入到ES中如何自定义index

    临时搭建了一套EFK xff08 elasticsearch xff0c filebeat xff0c kibana xff09 xff0c filebeat 6 0 默认的index 是filebeat 43 时间 xff0c 这样无法满
  • 人在异乡

    为什么到了上海五年 xff0c 还是没有归属感 to be continued
  • 怎么求矩阵对应的基

    怎么求矩阵对应的基呢 xff1f 对矩阵做初等行变换 xff0c 化为上三角形 或 对角型 xff0c 主对角元素不为0的列即为该矩阵的一组基 A 61 这个矩阵对应的一个基 为 其实 xff0c 将第二行的 1 倍加到第一行上 xff0c
  • javascript弹出窗口代码

    1 最基本的弹出窗口代码 lt SCRIPT LANGUAGE 61 34 javascript 34 gt lt window open 39 page html 39 gt lt SCRIPT gt 因为着是一段javascripts代
  • 大规模异步新闻爬虫【5】:网页正文的提取

    前面我们实现的新闻爬虫 xff0c 运行起来后很快就可以抓取大量新闻网页 xff0c 存到数据库里面的都是网页的html代码 xff0c 并不是我们想要的最终结果 最终结果应该是结构化的数据 xff0c 包含的信息至少有url xff0c
  • 网络安全态势可视化

    导语 网络态势可视化技术作为一项新技术 xff0c 是网络安全态势感知与可视化技术的结合 xff0c 将网络中蕴涵的态势状况通过可视化图形方式展示给用户 xff0c 并借助于人在图形图像方面强大的处理能力 xff0c 实现对网络异常行为的分
  • 滚动窗口

    本页目录 语法案例 滚动窗口 xff08 TUMBLE xff09 将每个元素分配到一个指定大小的窗口中 通常滚动窗口有一个固定的大小 xff0c 并且不会出现重叠 例如 xff1a 如果指定了一个5分钟大小的滚动窗口 xff0c 无限流的
  • Qt5&OpenCV3 UDP协议实现实时视频传输与通信

    打算在树莓派上挂载摄像头 xff0c 通过WIFI模块传输到上位机 局域网内带宽不是问题 xff0c 为了保证实时性 xff0c 也没有必要进行复杂的视频编码和解码 xff0c 于是通过截图然后使用UDP协议传输应该是可以的 所以最近试探性