之前实现了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视频实时检测的更多相关文章

  1. Flask框架的学习与实战(二):实战小项目

    昨天写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统. blog系统很简单,只有一个页面,然而麻雀虽小五脏俱全.这里目的不是为了做项目而做项目,这篇文章本意是通过这次练习传达 ...

  2. 实战小项目之基于yolo的目标检测web api实现

    上个月,对微服务及web service有了一些想法,看了一本app后台开发及运维的书,主要是一些概念性的东西,对service有了一些基本了解.互联网最开始的构架多是cs构架,浏览器兴起以后,变成了 ...

  3. 实战小项目BUG纪录

    果然,作为程序员最可爱的女朋友就是各种BUG,解决了你的开发能力和开发效率就会上升到一个新的层次.反之,在你面对BUG的时候,如果轻易的就放弃了,你也就失去了一次自我成长的机会.学习就是这样的,我们有 ...

  4. Django集成celery实战小项目

    上一篇已经介绍了celery的基本知识,本篇以一个小项目为例,详细说明django框架如何集成celery进行开发. 本系列文章的开发环境: window 7 + python2.7 + pychar ...

  5. 【实战小项目】python开发自动化运维工具--批量操作主机

    有很多开源自动化运维工具都很好用如ansible/salt stack等,完全不用重复造轮子.只不过,很多运维同学学习Python之后,苦于没小项目训练.本篇就演示用Python写一个批量操作主机的工 ...

  6. ASP.NET Core 2.1 Web API + Identity Server 4 + Angular 6 + Angular Material 实战小项目视频

    视频简介 ASP.NET Core Web API + Angular 6的教学视频 我是后端开发人员, 前端的Angular部分讲的比较差一些, 可以直接看代码!!!! 这是一个小项目的实战视频, ...

  7. 实战小项目之RTMP流媒体演示系统

    项目简介 windows下使用基于Qt对之前的RtmpApp进行封装与应用,单独功能使用线程执行,主要包括以下几个功能: 视频下载 推送文件 推送摄像头数据或者桌面 基于libvlc的播放器 视频下载 ...

  8. 实战小项目之IMX6 VPU使用

    项目简介 基于官方的demo进行修改,限于能力问题,并没有将功能代码完全从官方的demo中分离出来,还是基于原来的框架进行修改,做了一些简单的封装,我做的工作如下: 使用自己的采集程序 定义6中工作模 ...

  9. 实战小项目之嵌入式linux图像采集与传输

    项目简介      本次编程实战主要是围绕嵌入式linux v4l2采集框架展开,包括以下几个部分: v4l2视频采集 IPU转码 framebuffer显示 自定义UDP简单协议进行传输 上位机软件 ...

随机推荐

  1. Archlinux下安装微信小程序开发工具

    由于微信小程序没有Linux版本,所以需要用wine来跑 一.安装wine sudo pacman -S wine 二.安装nwjs-sdk 微信开发工具包基于nwjs-sdk #没有wget就先安装 ...

  2. SQL Server 2012 - 动态SQL查询

    动态SQL的两种执行方式:EXEC @sql 和 EXEC sys.sp_executesql @sql DECLARE @c_ids VARCHAR(200) SET @c_ids ='1,2' - ...

  3. Google+百度,自动识别知名人物的性别

    最近有一个任务,需要采集一批知名学者的性别信息.该任务的难点在于提供学者信息的网站并不会主动标注学者的性别性别,因此只能靠别的方法了. 对一个普通人来说,在网上判断一个人的性别的最快的方式就是看他的照 ...

  4. Win7配置express4环境

    本机环境: $ node -v v10.14.1 $ npm -v 6.4.1 配置node环境变量: #配置全局安装目录 npm config set prefix "G:\WEB\nod ...

  5. 关于php中数字0与其他变量的相等判断

    在实践过程中,经常需要做`==`判断,有时候会把0当做false一样用,但是0和false在用来做比较的时候还是不一样的, false false==0 等于true false=='0' 等于tru ...

  6. Leecode刷题之旅-C语言/python-121买卖股票的最佳时机

    /* * @lc app=leetcode.cn id=121 lang=c * * [121] 买卖股票的最佳时机 * * https://leetcode-cn.com/problems/best ...

  7. LeetCode二叉树实现

    LeetCode二叉树实现 # 定义二叉树 class TreeNode: def __init__(self, x): self.val = x self.left = None self.righ ...

  8. Lucene第二讲——索引与搜索

    一.Feild域 1.Field域的属性 是否分词:Tokenized 是:对该field存储的内容进行分词,分词的目的,就是为了索引. 否:不需要对field存储的内容进行分词,不分词,不代表不索引 ...

  9. Caliburn.Micro 杰的入门教程4,事件聚合器

    Caliburn.Micro 杰的入门教程1(原创翻译)Caliburn.Micro 杰的入门教程2 ,了解Data Binding 和 Events(原创翻译)Caliburn.Micro 杰的入门 ...

  10. 网络流Edmonds-Karp算法入门

    今天自习课没事干,看书自学了一下网络流中的EK算法.(求最大流) 设s为源点,t为汇点,C为容量矩阵,F为流量矩阵,f为最大流量. 1.初始化F,f 2.用BFS在残量网络中找到一条从s到t的最短增广 ...