实战小项目之ffmpeg推流yolo视频实时检测
之前实现了yolo图像的在线检测,这次主要完成远程视频的检测。主要包括推流--収流--检测显示三大部分
首先说一下推流,主要使用ffmpeg命令进行本地摄像头的推流,为了实现首屏秒开使用-g设置gop大小,同时使用-b降低网络负载,保证流畅度。
linux
ffmpeg -r -i /dev/video0 -vcodec h264 -max_delay -f flv -g -b rtmp://219.216.87.170/live/test1
window
ffmpeg -r -f vfwcap -i -vcodec h264 -max_delay -f flv -g -b rtmp://219.216.87.170/live/test1
ffmpeg -list_devices true -f dshow -i dummy
ffmpeg -r -f dshow -i video="1.3M HD WebCam" -vcodec h264 -max_delay -f flv -g -b rtmp://219.216.87.170/live/tes
t1
其次是収流,収流最开始的时候,有很大的延迟,大约5秒,后来通过优化,现在延时保证在1s以内,还是可以接收的,直接上収流的程序
AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameRGB;
uint8_t *out_buffer;
AVPacket *packet;
//int y_size;
int ret, got_picture;
struct SwsContext *img_convert_ctx;
//输入文件路径
// char filepath[] = "rtmp://219.216.87.170/vod/test.flv";
char filepath[] = "rtmp://219.216.87.170/live/test1";
int frame_cnt; printf("wait for playing %s\n", filepath);
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
printf("size %ld\tduration %ld\n", pFormatCtx->probesize,
pFormatCtx->max_analyze_duration);
pFormatCtx->probesize = ;
pFormatCtx->max_analyze_duration = ;
// pFormatCtx->interrupt_callback.callback = timout_callback;
// pFormatCtx->interrupt_callback.opaque = pFormatCtx;
// pFormatCtx->flags |= AVFMT_FLAG_NONBLOCK; AVDictionary* options = NULL;
av_dict_set(&options, "fflags", "nobuffer", );
// av_dict_set(&options, "max_delay", "100000", 0);
// av_dict_set(&options, "rtmp_transport", "tcp", 0);
// av_dict_set(&options, "stimeout", "6", 0); printf("wating for opening file\n");
if (avformat_open_input(&pFormatCtx, filepath, NULL, &options) != ) {
printf("Couldn't open input stream.\n");
return -;
}
av_dict_free(&options);
printf("wating for finding stream\n");
if (avformat_find_stream_info(pFormatCtx, NULL) < ) {
printf("Couldn't find stream information.\n");
return -;
}
videoindex = -;
for (i = ; i < pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex = i;
break;
}
if (videoindex == -) {
printf("Didn't find a video stream.\n");
return -;
} pCodecCtx = pFormatCtx->streams[videoindex]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return -;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < ) {
printf("Could not open codec.\n");
return -;
}
/*
* 在此处添加输出视频信息的代码
* 取自于pFormatCtx,使用fprintf()
*/
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
out_buffer = (uint8_t *) av_malloc(
avpicture_get_size(AV_PIX_FMT_BGR24, pCodecCtx->width,
pCodecCtx->height));
avpicture_fill((AVPicture *) pFrameRGB, out_buffer, AV_PIX_FMT_BGR24,
pCodecCtx->width, pCodecCtx->height);
packet = (AVPacket *) av_malloc(sizeof(AVPacket));
//Output Info-----------------------------
printf("--------------- File Information ----------------\n");
av_dump_format(pFormatCtx, , filepath, );
printf("-------------------------------------------------\n");
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
CvSize imagesize;
imagesize.width = pCodecCtx->width;
imagesize.height = pCodecCtx->height;
IplImage *image = cvCreateImageHeader(imagesize, IPL_DEPTH_8U, );
cvSetData(image, out_buffer, imagesize.width * );
cvNamedWindow(filepath, CV_WINDOW_AUTOSIZE); frame_cnt = ;
int num = ;
while (av_read_frame(pFormatCtx, packet) >= ) {
if (packet->stream_index == videoindex) {
/*
* 在此处添加输出H264码流的代码
* 取自于packet,使用fwrite()
*/
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,
packet);
if (ret < ) {
printf("Decode Error.\n");
return -;
}
if (got_picture) {
sws_scale(img_convert_ctx,
(const uint8_t* const *) pFrame->data, pFrame->linesize,
, pCodecCtx->height, pFrameRGB->data,
pFrameRGB->linesize); printf("Decoded frame index: %d\n", frame_cnt); /*
* 在此处添加输出YUV的代码
* 取自于pFrameYUV,使用fwrite()
*/ frame_cnt++;
cvShowImage(filepath, image);
cvWaitKey(); }
}
av_free_packet(packet);
} sws_freeContext(img_convert_ctx); av_frame_free(&pFrameRGB);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx); return ;
将解压后的数据区与opencv的IplImage的数据区映射,实现opencv显示。
检测部分,主要使用IplImage与yolo中的图像进行对接,在图像转换方面,进行了部分优化,缩减一些不必要的步骤。然后使用线程区接收ffmepg流,主循环里区做检测并显示。需要做线程同步处理,只有当收到新流时,才去检测。
实战小项目之ffmpeg推流yolo视频实时检测的更多相关文章
- Flask框架的学习与实战(二):实战小项目
昨天写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统. blog系统很简单,只有一个页面,然而麻雀虽小五脏俱全.这里目的不是为了做项目而做项目,这篇文章本意是通过这次练习传达 ...
- 实战小项目之基于yolo的目标检测web api实现
上个月,对微服务及web service有了一些想法,看了一本app后台开发及运维的书,主要是一些概念性的东西,对service有了一些基本了解.互联网最开始的构架多是cs构架,浏览器兴起以后,变成了 ...
- 实战小项目BUG纪录
果然,作为程序员最可爱的女朋友就是各种BUG,解决了你的开发能力和开发效率就会上升到一个新的层次.反之,在你面对BUG的时候,如果轻易的就放弃了,你也就失去了一次自我成长的机会.学习就是这样的,我们有 ...
- Django集成celery实战小项目
上一篇已经介绍了celery的基本知识,本篇以一个小项目为例,详细说明django框架如何集成celery进行开发. 本系列文章的开发环境: window 7 + python2.7 + pychar ...
- 【实战小项目】python开发自动化运维工具--批量操作主机
有很多开源自动化运维工具都很好用如ansible/salt stack等,完全不用重复造轮子.只不过,很多运维同学学习Python之后,苦于没小项目训练.本篇就演示用Python写一个批量操作主机的工 ...
- ASP.NET Core 2.1 Web API + Identity Server 4 + Angular 6 + Angular Material 实战小项目视频
视频简介 ASP.NET Core Web API + Angular 6的教学视频 我是后端开发人员, 前端的Angular部分讲的比较差一些, 可以直接看代码!!!! 这是一个小项目的实战视频, ...
- 实战小项目之RTMP流媒体演示系统
项目简介 windows下使用基于Qt对之前的RtmpApp进行封装与应用,单独功能使用线程执行,主要包括以下几个功能: 视频下载 推送文件 推送摄像头数据或者桌面 基于libvlc的播放器 视频下载 ...
- 实战小项目之IMX6 VPU使用
项目简介 基于官方的demo进行修改,限于能力问题,并没有将功能代码完全从官方的demo中分离出来,还是基于原来的框架进行修改,做了一些简单的封装,我做的工作如下: 使用自己的采集程序 定义6中工作模 ...
- 实战小项目之嵌入式linux图像采集与传输
项目简介 本次编程实战主要是围绕嵌入式linux v4l2采集框架展开,包括以下几个部分: v4l2视频采集 IPU转码 framebuffer显示 自定义UDP简单协议进行传输 上位机软件 ...
随机推荐
- Jquery中复选框选中取消实现文本框的显示隐藏
标签内容 <div class="box"> 请编写javascript代码,完成如下功能要求:<br /> 1.取消复选款后,要求促销价格.促销开始结束日 ...
- angularjs中控制器之间的通信----$on、$emit和$broadcast解析
$on.$emit和$broadcast使得event.data在controller之间的传递变的简单. $emit只能向parent controller传递event与data $broadca ...
- 使用java实现AES加密
公司最近做agent项目,需要对一些远程重要的请求参数进行加密.加密之前选型,选择了AES,而DES算法加密,容易被破解.网上有很多关于加密的算法的Demo案列,我发现这些Demo在Window平台运 ...
- Python入门 (三)
迭代器与生成器 迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器 ...
- 使用JAX-WS(JWS)发布WebService(一)
JAX-WS概述: 通过Main发布一个简单WebService: JAX-WS(Java API for XML Web Services)规范是一组XML web services的JAVA AP ...
- 洛谷九月月赛T1 思考
很迷的一道题目,刚开始直接枚举n个1,然后去mod m ,爆0,后来发现一个神奇性质:找到递推公式An=An-1*10+1,枚举n,不断mod m,每递推一次就1的个数加一.居然可行! 听说余数具有可 ...
- javascript array.property.slice.call
function foo() { //var var1=Array.prototype.slice.call(arguments); var var1=[].slice.call(arguments) ...
- P1488 肥猫的游戏
题目描述 野猫与胖子,合起来简称肥猫,是一个班的同学,他们也都是数学高手,所以经常在一起讨论数学问题也就不足为奇了.一次,野猫遇到了一道有趣的几何游戏题目,便拿给胖子看.游戏要求在一个有n个顶点凸多边 ...
- jenkins通过maven指定testng的xml文件,并给testng代码传参
1.jenkins设置参数化构建,设置要传的参数名和值 2.指定testng的xml文件,在jenkins的输入以下 3.在pom.xml文件分别引用jenkins的参数,设置两个property & ...
- PS 抠图和添加背景图
1.打开需要抠的图--然后使用套索类工具,魔棒类工具,钢笔类工具均可选择需要扣的图片范围任何在Delete(如果抠反了可以进行反选Ctrl +shift+I) 2.然后把任一一张背景图直接拖到PS里面 ...