实战小项目之ffmpeg推流yolo视频实时检测

之前实现了yolo图像的在线检测,这次主要完成远程视频的检测。主要包括推流--収流--检测显示三大部分

  首先说一下推流,主要使用ffmpeg命令进行本地摄像头的推流,为了实现首屏秒开使用-g设置gop大小,同时使用-b降低网络负载,保证流畅度。

ffmpeg -r 30  -i /dev/video0 -vcodec h264 -max_delay 100 -f flv -g 5 -b 700000 rtmp://219.216.87.170/live/test1

  其次是収流,収流最开始的时候,有很大的延迟,大约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 = 20000000;
    pFormatCtx->max_analyze_duration = 2000;
//    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", 0);
//    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) != 0) {
        printf("Couldn‘t open input stream.\n");
        return -1;
    }
    av_dict_free(&options);
    printf("wating for finding stream\n");
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        printf("Couldn‘t find stream information.\n");
        return -1;
    }
    videoindex = -1;
    for (i = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoindex = i;
            break;
        }
    if (videoindex == -1) {
        printf("Didn‘t find a video stream.\n");
        return -1;
        }

    pCodecCtx = pFormatCtx->streams[videoindex]->codec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL) {
        printf("Codec not found.\n");
        return -1;
        }
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        printf("Could not open codec.\n");
        return -1;
        }
    /*
     * 在此处添加输出视频信息的代码
     * 取自于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, 0, filepath, 0);
    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, 3);
    cvSetData(image, out_buffer, imagesize.width * 3);
    cvNamedWindow(filepath, CV_WINDOW_AUTOSIZE);

    frame_cnt = 0;
    int num = 0;
    while (av_read_frame(pFormatCtx, packet) >= 0) {
        if (packet->stream_index == videoindex) {
            /*
             * 在此处添加输出H264码流的代码
             * 取自于packet,使用fwrite()
             */
            ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,
                    packet);
            if (ret < 0) {
                printf("Decode Error.\n");
                return -1;
            }
            if (got_picture) {
                sws_scale(img_convert_ctx,
                        (const uint8_t* const *) pFrame->data, pFrame->linesize,
                        0, pCodecCtx->height, pFrameRGB->data,
                        pFrameRGB->linesize);

                printf("Decoded frame index: %d\n", frame_cnt);

                /*
                 * 在此处添加输出YUV的代码
                 * 取自于pFrameYUV,使用fwrite()
                 */

                frame_cnt++;
                cvShowImage(filepath, image);
                cvWaitKey(30);

            }
        }
        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 0;

  将解压后的数据区与opencv的IplImage的数据区映射,实现opencv显示。

  

  检测部分,主要使用IplImage与yolo中的图像进行对接,在图像转换方面,进行了部分优化,缩减一些不必要的步骤。然后使用线程区接收ffmepg流,主循环里区做检测并显示。需要做线程同步处理,只有当收到新流时,才去检测。

时间: 2024-10-18 11:45:28

实战小项目之ffmpeg推流yolo视频实时检测的相关文章

实战小项目之基于嵌入式的视频直播客户端

项目简介 本项目就是RtmpApp嵌入式版本,在此基础上,融入之前的v4l2采集.ipu转码等内容,实现了usb摄像头的采集(yuv422).ipu或者软件转码.x264编码.rtmp传输. 与前一个项目最大的不同在于数据衔接,以及数据转换,这里使用单独线程进行编码传输,里面涉及友元类的使用,是如下 void PushStream::worker(const CapFbTest &ct){ while(runflag){ lastTime=RTMP_GetTime(); if(frameInde

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

上个月,对微服务及web service有了一些想法,看了一本app后台开发及运维的书,主要是一些概念性的东西,对service有了一些基本了解.互联网最开始的构架多是cs构架,浏览器兴起以后,变成了bs,最近几年,随着移动互联网的兴起,cs构架再次火了起来,有了一个新的概念,web service. 最近两天,想结合自己这段时间学的东西,实现一个cs构架的service接口.说一下大体流程,client上传图片到http服务器,http后台使用yolo进行图片的检测,之后将检测结果封装成jso

Android开发不得不看的11个实战小项目

是不是想学Android开发(http://www.maiziedu.com/course/android-px/)却不知道如何下手?懂得一点点入门基础知识却无法应用到实际开发中?看相关资料觉得都懂了实际动手却发现什么都不懂?本地搭建Android开发环境太麻烦? 如果你有以上的各种问题,那么今天小编推荐的Android开发的这11个小项目,你一定要看!! 因为,这些实战项目都是基于google 官方的API Demos制作而成,而且全部配有Android在线开发环境,你可以随时动手跟着课程操作

必知的11个android开发实战小项目

是不是想学Android开发(http://www.maiziedu.com/course/android-px/)却不知道如何下手?懂得一点点入门基础知识却无法应用到实际开发中?看相关资料觉得都懂了实际动手却发现什么都不懂?本地搭建Android开发环境太麻烦? 如果你有以上的各种问题,那么今天小编推荐的Android开发的这11个小项目,你一定要看!! 因为,这些实战项目都是基于google 官方的API Demos制作而成,而且全部配有Android在线开发环境,你可以随时动手跟着课程操作

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

有很多开源自动化运维工具都很好用如ansible/salt stack等,完全不用重复造轮子.只不过,很多运维同学学习Python之后,苦于没小项目训练,本篇演示用Python写一个批量操作主机的工具,大家空余时候可以试着写写,完善完善. 1 思路分析 在运维工作中,古老的方式部署环境.上线代码可能都需要手动在服务器上敲命令,不胜其烦.所以,脚本,自动化工具等还是很有必要的.我觉得一个批量操作工具应该考虑以下几点: (1)本质上,就是到远程主机上执行命令并返回结果. (2)做到批量.也就是要并发

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

项目简介 windows下使用基于Qt对之前的RtmpApp进行封装与应用,单独功能使用线程执行,主要包括以下几个功能: 视频下载 推送文件 推送摄像头数据或者桌面 基于libvlc的播放器 视频下载部分 最大的坑就是,文件名的那个数组设小了,导致数组越界,写下一个功能的时候,总是崩溃,调了一上午,内心崩溃 推送文件 推送摄像头数据或者桌面 使用videoinput作为视频采集驱动,没有使用qt的camera类,videoinput采集出来的数据是rgb(bgr,可选),直接送入label显示,

实战小项目之借书系统

项目简介 基于Qt做了一个用户管理和借书系统,主要是为了练手,学了mysql而不是白学,通过这个小软件,对数据库增删改查操作更为熟悉,对于操作失败时,能通过一些返回信息判断错误原因,不废话了,下面是这个小项目的组成: 用户管理 图书管理 借书系统 主界面 借书界面 图书管理界面 完整工程 https://github.com/tla001/PowerSystemV1

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

项目简介      本次编程实战主要是围绕嵌入式linux v4l2采集框架展开,包括以下几个部分: v4l2视频采集 IPU转码 framebuffer显示 自定义UDP简单协议进行传输 上位机软件(QT) 首先是采集部分 #include "includes.h" int fd_cam; struct cam_buffer *buffers=NULL; unsigned int n_buffers=0; int frameIndex=0; void initVideo() { in

Python爬虫实战小项目

爬取国家药品监督管理总局中基于中华人民共和国化妆品生产许可证相关数据 import requests from fake_useragent import UserAgent ua = UserAgent(use_cache_server=False,verify_ssl=False).random headers = { 'User-Agent':ua } url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkz