进入到五一假期第三天,继续我们的项目。本来五一假期还是想好好休息一下的,因为最近学习的状态不太好,刷题都没有思路了,但是身边的同学太卷了,不过我还是想放松一下,所以上午睡觉,下午复盘一下这个项目分享出来。等假期结束之后,再好好冲刺一波。
前两天分别介绍了QT的基本使用以及UDP网络编程,实现了用QT编写一个上位机与开发板进行数据传输。这些工作完成之后我们就可以开始关注在上位机中显示视频画面了,这里面涉及到开发板内核的视频画面获取与处理,然后通过UDP网络通信发送给上位机实时显示。
首先介绍一下v4l2视频处理模块,V4L2是V4L的第二版,是Video For Linux的简称,V4L早在Linux 2.1中就已经被引入,到2.6.38时才有了V4L2的最终替代。V4L2是Linux视频处理模块的最新标准代码,包括对视频输入设备的处理,如高频(即、电视信号输入端子)或摄像头,还包括视频处理输出装置。一般来说,最常见的是使用V4L2来处理相机数据采集的问题。我们通常使用的相机实际上是一个图像传感器,将捕捉到的光线通过视频芯片处理后,编码成JPG/MJPG或YUV格式输出。我们可以很容易地通过V4L2与第一台摄像机设备“通信”,如设置或获取它们的工作参数。
在内核中,摄像头捕捉到的视频数据,我们可以使用一个队列来存储。我们做的工作大致是这样的:首先配置摄像头的相关参数,可以正常工作,然后申请一个号码的内核视频缓存,送他们到队列,像三个空盘子在传送带上。然后我们还需要三个内核缓存区域通过mmap函数映射到用户空间,这样我们就可以操作相机数据在用户层,然后我们可以启动相机开始数据采集,每一帧捕获数据我们可以做一个团队操作,读取数据,然后再阅读内核缓存的数据小组,依次循环。
下面是v4l2视频处理模块常用的函数:
linux_v4l2_device_init("/dev/video7");//利用v4l2初始化摄像头设备;
linux_v4l2_start_capturing();//启动摄像头
linus_v4l2_get_frame(&framebuf);//获取摄像头数据,并存放在freambuf中
linux_v4l2_stop_capturing();//停止摄像头
linux_v4l2_device_uinit();//卸载摄像头
这里又出现了一个重要的知识点,Framebuffer模块,简单介绍一些Framebuffer模块:Freambuffer简单来说就是一块内核中的内存,里面保存着一帧图像。
掌握这里知识点,我们就可以实现在上位机中实时显示摄像头拍摄的画面啦。
上位机我写的上位机程序里已经完成了显示图象的代码:
//头文件中声明
private:
QPixmap pix;
//主函数中显示
//QPixmap类显示图片
pix.loadFromData((uchar *)data, ret);
pix = pix.scaled(ui->label->width(), ui->label->height());
ui->label->setPixmap(pix);
开发板中运行的服务器程序可以在上一节中介绍的Server.c程序中修改,我这里采用的是使用多线程编程,用一个线程来实现实时监控功能
FrameBuffer freambuf;//声明一个FrameBuffer结构体,存放视频数据
void *Jpg_Real_Time(void *arg) //实时监控功能代码
{
/* 初始化摄像头设备*/
linux_v4l2_device_init("/dev/video7");
/* 启动摄像头*/
linux_v4l2_start_capturing();
while(1)
{
// 实时监控
/* 获取摄像头数据 存放jpg文件流*/
linux_v4l2_get_fream(&freambuf);
/* 显示摄像头图像*/
lcd_draw_jpg(80, 0, NULL, freambuf.buf, freambuf.length, 0);
/* WiFi发送摄像头图像*/
sendto(Socket_fd, freambuf.buf, freambuf.length, 0, (struct sockaddr *)&Phone_ipaddr, addrlen);
}
/* 停止摄像头*/
linux_v4l2_stop_capturing();
/* 卸载摄像头*/
linux_v4l2_device_uinit();
}
初始化UDP通信的网络接口
const char* ip = "192.168.5.100";
void Udp_Init() //创建UDP套接字。Bind指定的IP和端口号
{
Socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(Socket_fd < 0)
{
perror("socket failed");
return ;
}
Arm_ipaddr.sin_family = AF_INET;
Arm_ipaddr.sin_port = htons(2234);
inet_pton(AF_INET, ip, &Arm_ipaddr.sin_addr);
addrlen = sizeof(struct sockaddr_in);
int ret = bind(Socket_fd, (struct sockaddr *)&Arm_ipaddr, addrlen);
if(ret < 0)
{
perror("bind failed");
return ;
}
}
在主线程中需要完成的就是接收上位机发送过来的信息,并解析保存上位机的IP地址和端口号,线程Jpg_Real_Time( )得到上位机的IP地址和端口号之后,就可以将采集到视频数据通过UDP传输给上位机显示。
int main(int argc,char**argv)
{
//0,初始化udp网络通信
Udp_Init();
//1,创建一条线程去实现实时监控
pthread_t tid;
pthread_create(&tid, NULL, Jpg_Real_Time, NULL);
//2,主线程接受手机端发送的数据
char buf[128];
char ip_addr[20] = {0};
while(1)
{
bzero(buf, sizeof(buf));
recvfrom(Socket_fd, buf, sizeof(buf), 0,(struct sockaddr *)&Phone_ipaddr, &addrlen);
printf("from:%s port:%d recvbuf:%s\n", inet_ntop(AF_INET, &Phone_ipaddr.sin_addr, ip_addr, sizeof(ip_addr)), ntohs(Phone_ipaddr.sin_port), buf);
}
return 0;
}
到这里就全部完成了所有的程序设计,下面就需要在Ubuntu中编译要在开发板中运行的服务器程序了。使用如下命令编译程序。因为我们需要显示的是jpeg格式的图片数据,所以需要在编译文件路径下包含jpeg解码包。如果你用的YUYV格式的摄像头,还需要将采集到的图片转换成jepg格式的图片才能显示。
arm-linux-gnueabi-gcc realtime_video.c -o realtime_video -I ./libjpeg -L ./libjpeg -lapi_v4l2_arm -lpthread -ljpeg
解释一下上面的内容
-I./libjpeg : 指定动态库头文件位置
-L./libjpeg : 指定动态库,库文件位置
-ljpeg : 指定动态库名
之后在开发板上插入摄像头,运行程序,打开上位机,点击摄像头按钮,就可以显示摄像头采集的数据了

至此这个项目需要掌握的知识点基本上算是讲完了,后面无非就是对上位机的美化与重新设计了,牵扯到的还是网络编程,来发送数据的问题。
完整代码我会贴在公众号中,需要完整代码的关注公众号回复视频监控第三讲获取。有什么问题也可以在下方留言,我看到之后会回复你。
我是河边小乌龟爬,学习嵌入式软件开发路上的一名小学生,欢迎大家相互交流哇。公众号:河边小乌龟爬。
(群名称:嵌入式软件开发交流群;群 号:1004953094)
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc