首页 > 编程语言 >zlmediakit源码学习(扩展支持算法分析)

zlmediakit源码学习(扩展支持算法分析)

时间:2023-08-26 18:23:35浏览次数:40  
标签:zlmediakit int frame 算法 源码 video time const

在zlmediakit源码基础上继续探索扩展支持算法分析功能。参照上一篇帖子:https://www.cnblogs.com/feixiang-energy/p/17623567.html

算法模型使用opencv自带的人脸检测库:https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml

zlmediakit提供接口定时抽取视频帧进行算法分析,检测到视频画面中有人脸时,进行人脸区域绘制并保存图片。通过webhook的方式将算法分析结果回调给业务程序。

-----------------------------------------------------

关键代码如下:

1.cv::Mat FFmpegMuxer::avframeToCvmat。新增一个AvFrame到CV::Mat的转换函数,将ffmpeg解码后的Yuv图像转换成opencv对应的格式

cv::Mat FFmpegMuxer::avframeToCvmat(const AVFrame *frame) {
    int width = frame->width;
    int height = frame->height;
    cv::Mat image(height, width, CV_8UC3);
    int cvLinesizes[1];
    cvLinesizes[0] = image.step1();
    SwsContext *conversion = sws_getContext(
        width, height, (AVPixelFormat)frame->format, width, height, AVPixelFormat::AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR,
        NULL, NULL, NULL);
    sws_scale(conversion, frame->data, frame->linesize, 0, height, &image.data, cvLinesizes);
    sws_freeContext(conversion);
    return image;
}

2.FFmpegMuxer::addTrack。修改addTrack函数,设置视频解码器,视频解码回调的数据进行算法识别,识别结果通过"NoticeCenter"机制广播出去。

bool FFmpegMuxer::addTrack(const Track::Ptr &track) {
    if (track->getTrackType() == TrackVideo) {
        _video_dec.reset(new FFmpegDecoder(track));
        /*
        // 设置H264编码器
        H264Track::Ptr newTrack(new H264Track());
        VideoTrack::Ptr video = static_pointer_cast<VideoTrack>(track);
        newTrack->setVideoWidth(video->getVideoWidth());
        newTrack->setVideoHeight(video->getVideoHeight());
        newTrack->setBitRate(video->getBitRate());
        _video_enc.reset(new FFmpegEncoder(newTrack));
        _video_enc->setOnEncode([this](const Frame::Ptr &frame) {
            if (_cb) {
                _cb(frame);
            }
        });
        */
        _video_dec->setOnDecode([this](const FFmpegFrame::Ptr &frame) {
            /* 转码操作
            // 将解码后的视频帧写入到编码器重新编码
            _video_enc->inputFrame(frame, false);
            */
            /*
            // --- 抽帧操作 begin
            time_t now = ::time(NULL);
            if (now - _last_time >= _gapTime) {
                AVFrame *avFrame = frame->get();
                int bufSize = av_image_get_buffer_size(AV_PIX_FMT_BGRA, avFrame->width, avFrame->height, 64);
                uint8_t *buf = (uint8_t *)av_malloc(bufSize);
                int picSize = frameToImage(avFrame, AV_CODEC_ID_MJPEG, buf, bufSize);
                if (picSize > 0) {
                    auto file_path = _folder_path + getTimeStr("%H-%M-%S_") + std::to_string(_index) + ".jpeg";
                    auto f = fopen(file_path.c_str(), "wb+");
                    if (f) {
                        fwrite(buf, sizeof(uint8_t), bufSize, f);
                        fclose(f);
                    }
                }
                av_free(buf);
                _index++;
                _last_time = now;
            }
            // --- 抽帧操作 end
            */
            // 算法分析
            time_t now = ::time(NULL);
            if (now - _last_time >= _gapTime) {
                AVFrame *avFrame = frame->get();
                cv::Mat img = avframeToCvmat(avFrame);
                vector<cv::Rect> faces;
                if (!img.empty()) {
                    // 加载OpneCV人脸检测算法模型
                    cv::CascadeClassifier faceCascade;
                    faceCascade.load("model/haarcascade_frontalface_default.xml");
                    if (faceCascade.empty()) {
                        LogW("加载算法模型失败");
                        return;
                    }
                    // 检测是否包含人脸
                    faceCascade.detectMultiScale(img, faces, 1.1, 10);
                }
                if (faces.size() > 0) {
                    // 绘制人脸线框
                    for (int i = 0; i < faces.size(); i++) {
                        rectangle(img, faces[i].tl(), faces[i].br(), cv::Scalar(255, 0, 255), 3);
                    }
                    // 保存识别结果图片
                    auto pic_path = _folder_path + getTimeStr("%H-%M-%S_") + std::to_string(_index) + ".jpeg";
                    cv::imwrite(pic_path.c_str(), img);
                    _index++;
                    // 检测到人脸
                    int timestamp = int(::time(NULL));
                    std::string message = "检测到人脸";
                    NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastAiEvent, timestamp, message, pic_path);
                }
                _last_time = now;
            }
        });
    }
    return true;
}

3.在config.h中定义广播事件和参数定义

// 智能AI分析事件广播
extern const std::string kBroadcastAiEvent;
#define BroadcastAiEventArgs const int &timestamp, const std::string &message, const std::string &picPath

4.在webhook.cpp中增加一个监听器,监听Broadcast::kBroadcastAiEvent事件。并执行webhook的http回调

void installWebHook(){
      *****
      //AI智能分析事件广播
    NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastAiEvent, [](BroadcastAiEventArgs) {
        GET_CONFIG(string, hook_ai_event, Hook::kOnAiEvent);
        if (!hook_enable || hook_ai_event.empty()) {
            return;
        }
        ArgsType body;
        body["timestamp"] = timestamp;
        body["message"] = message;
        body["picPath"] = picPath;
        //执行hook
        do_http_hook(hook_ai_event, body, nullptr);
    });  
    *****
}

 

标签:zlmediakit,int,frame,算法,源码,video,time,const
From: https://www.cnblogs.com/feixiang-energy/p/17656212.html

相关文章

  • mall:redis项目源码解析
    目录一、mall开源项目1.1来源1.2项目转移1.3项目克隆二、Redis非关系型数据库2.1Redis简介2.2分布式后端项目的使用流程2.3分布式后端项目的使用场景2.4常见的缓存问题三、源码解析3.1集成与配置3.1.1导入依赖3.1.2添加配置3.1.3全局跨域配置3.2Redis测试3.2.1Redis......
  • linux系统批量查找网站源码并替换字符,查找替换指定内容
    问题描述:维护中需要批量修改代码中某个字符,如果单个打开页面进行修改则效率过低,linux系统下借助grep命令快速查找替换 命令示例1:grep-rl'查找的内容'.|xargssed-i's/查找的内容/替换的新内容/g'登录服务器后,根据实际情况输入需要查找/替换的内容即可,以上命令表示当......
  • 垃圾收集器ParNew&CMS与底层三色标记算法详解
    垃圾收集算法分代收集理论当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中,每次收集都会有大量对象(近9......
  • 在线拍卖直播系统源码(双端APP+H5前端+管理后台)
    "东莞梦幻网络科技"开发该拍卖直播系统采用了多种开发语言。具体而言,后端采用了PHP语言,并且使用了ThinkPHP框架。而在移动端方面,苹果端采用了Objective-C语言,而安卓端则采用了Java。前端H5部分则使用了Vue.js框架。以下是该拍卖直播系统的主要功能模块:1、直播拍卖:用户可以观看主播......
  • 智能化医疗护航:探秘智慧医疗电子处方系统源码
    时下,智慧医疗电子处方系统作为智能医疗的重要组成部分,正以其高效、精准的特性,为患者和医生带来全新的医疗体验。本文将深入探讨智慧医疗电子处方系统的源码,揭示其背后的技术原理和创新之处。一、引言传统医疗领域一直面临着繁琐的纸质处方、处方传递不便等问题。智慧医疗电子处方系......
  • 社团算法学习笔记
    社团算法学习笔记:https://gaowenxin95.github.io/le_graph/社团社区发现算法学习笔记.html......
  • 多元回归预测 | Matlab 粒子群算法优化随机森林(PSO-RF)回归预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 多元回归预测 | Matlab 鲸鱼算法优化随机森林(WOA-RF)回归预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 大厂算法每日总结(统计文件夹下的文件)
    //统计文件夹下的文件,是文件就累计1,隐藏文件空累计,文件不累计publicstaticvoidmain(String[]args){System.out.println(getFileNumber("D:\重要文件"));}publicstaticintgetFileNumber(StringfolderPath){Fileroot=newFile(folderPath);if(!root.isDirectory(......
  • 大厂算法题每日总结(num最近的,2的某次方)
    //给定一个非负整数num,不用循环,返回>=num,并离num最近的,2的某次方publicstaticfinalinttableSizeFor(intn){n--;n|=n>>>1;//>>>不带符号右移n|=n>>>2;n|=n>>>4;n|=n>>>8;n|=n>>>16;//打满,至此int32位,全打满return(n<0......