openh264 场景变化检测算法源码分析

文件位置

  • openh264/codec/processing/scenechangedetection/SceneChangeDetection.cpp
  • openh264/codec/processing/scenechangedetection/SceneChangeDetection.h

代码流程

在这里插入图片描述

  • 说明
    通过代码流程分析,当METHOD_SCENE_CHANGE_DETECTION_SCREEN场景类型为时候,创建CSceneChangeDetectorScreen子类进行场景变化检测;当METHOD_SCENE_CHANGE_DETECTION_VIDEO场景类型为时,创建CSceneChangeDetectorVideo子类进行场景变化检测。

原理

  • 开关控制参数:(bool)bEnableSceneChangeDetect

CSceneChangeDetectorVideo 类

  1. 功能:通过CSceneChangeDetection类模板调用CSceneChangeDetectorVideo类中方法实现摄像视频场景变化检测功能类
  2. 过程
  • 第一步:CSceneChangeDetection类中process 函数;
    • 初始化变量、参数设置;
    • 场景变化阈值iSceneChangeThresholdLarge、iSceneChangeThresholdMedium计算;
    • 设置eSceneChangeIdc类型为SIMILAR_SCENE;
    • 调用一个名为m_cDetector的对象的重载运算符(),传入m_sLocalParam作为参数,调用指向CSceneChangeDetectorVideo类中场景变化检测算法;
    • 场景变化判断;
      • 如果,iMotionBlockNum 大于等于iSceneChangeThresholdLarge,则设置eSceneChangeIdc类型为LARGE_CHANGED_SCENE;
      • 否则,iMotionBlockNum 大于等于iSceneChangeThresholdMedium,则设置eSceneChangeIdc类型为MEDIUM_CHANGED_SCENE;
  • 第二步:CSceneChangeDetectorVideo类中operator重载;
    • 双层嵌套 for 循环处理以 8x8 为单位的图像块,即处理每个 8x8 块;
      • 调用m_pfSad函数(指向具体的WelsSampleSad8x8_c函数)计算 iSad 值;
      • 比较 iSad 与HIGH_MOTION_BLOCK_THRESHOLD的大小,将结果累加到iMotionBlockNum中;
      • 指针更新,下一个 8x8 块以及下一行图像;
  1. 原理图
    在这里插入图片描述
  2. 相关源码
  • CSceneChangeDetection模板类
template<typename T>
class CSceneChangeDetection : public IStrategy {public:CSceneChangeDetection (EMethods eMethod, int32_t iCpuFlag): m_cDetector (m_sSceneChangeParam, iCpuFlag) {m_eMethod   = eMethod;WelsMemset (&m_sSceneChangeParam, 0, sizeof (m_sSceneChangeParam));}~CSceneChangeDetection() {}EResult Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {EResult eReturn = RET_INVALIDPARAM;m_sLocalParam.iWidth = pSrcPixMap->sRect.iRectWidth;m_sLocalParam.iHeight = pSrcPixMap->sRect.iRectHeight;m_sLocalParam.iBlock8x8Width = m_sLocalParam.iWidth >> 3;m_sLocalParam.iBlock8x8Height = m_sLocalParam.iHeight >> 3;m_sLocalParam.pRefY = (uint8_t*)pRefPixMap->pPixel[0];m_sLocalParam.pCurY = (uint8_t*)pSrcPixMap->pPixel[0];m_sLocalParam.iRefStride = pRefPixMap->iStride[0];m_sLocalParam.iCurStride = pSrcPixMap->iStride[0];m_sLocalParam.pStaticBlockIdc = m_sSceneChangeParam.pStaticBlockIdc;int32_t iBlock8x8Num = m_sLocalParam.iBlock8x8Width * m_sLocalParam.iBlock8x8Height;int32_t iSceneChangeThresholdLarge = WelsStaticCast (int32_t,m_cDetector.GetSceneChangeMotionRatioLarge() * iBlock8x8Num + 0.5f + PESN);int32_t iSceneChangeThresholdMedium = WelsStaticCast (int32_t,m_cDetector.GetSceneChangeMotionRatioMedium() * iBlock8x8Num + 0.5f + PESN);m_sSceneChangeParam.iMotionBlockNum = 0;m_sSceneChangeParam.iFrameComplexity = 0;m_sSceneChangeParam.eSceneChangeIdc = SIMILAR_SCENE;m_cDetector (m_sLocalParam);if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdLarge) {m_sSceneChangeParam.eSceneChangeIdc = LARGE_CHANGED_SCENE;} else if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdMedium) {m_sSceneChangeParam.eSceneChangeIdc = MEDIUM_CHANGED_SCENE;}eReturn = RET_SUCCESS;return eReturn;}EResult Get (int32_t iType, void* pParam) {if (pParam == NULL) {return RET_INVALIDPARAM;}* (SSceneChangeResult*)pParam = m_sSceneChangeParam;return RET_SUCCESS;}EResult Set (int32_t iType, void* pParam) {if (pParam == NULL) {return RET_INVALIDPARAM;}m_sSceneChangeParam = * (SSceneChangeResult*)pParam;return RET_SUCCESS;}private:SSceneChangeResult m_sSceneChangeParam;SLocalParam m_sLocalParam;T          m_cDetector;
};
  • CSceneChangeDetectorVideo
class CSceneChangeDetectorVideo {public:CSceneChangeDetectorVideo (SSceneChangeResult& sParam, int32_t iCpuFlag) : m_sParam (sParam) {m_pfSad = WelsSampleSad8x8_c;
#ifdef X86_ASMif (iCpuFlag & WELS_CPU_SSE2) {m_pfSad = WelsSampleSad8x8_sse21;}
#endif
#ifdef HAVE_NEONif (iCpuFlag & WELS_CPU_NEON) {m_pfSad = WelsProcessingSampleSad8x8_neon;}
#endif#ifdef HAVE_NEON_AARCH64if (iCpuFlag & WELS_CPU_NEON) {m_pfSad = WelsProcessingSampleSad8x8_AArch64_neon;}
#endif#ifdef HAVE_MMIif (iCpuFlag & WELS_CPU_MMI) {m_pfSad = WelsSampleSad8x8_mmi;}
#endifm_fSceneChangeMotionRatioLarge = SCENE_CHANGE_MOTION_RATIO_LARGE_VIDEO;m_fSceneChangeMotionRatioMedium = SCENE_CHANGE_MOTION_RATIO_MEDIUM;}virtual ~CSceneChangeDetectorVideo() {}void operator() (SLocalParam& sLocalParam) {int32_t iRefRowStride = 0, iCurRowStride = 0;uint8_t* pRefY = sLocalParam.pRefY;uint8_t* pCurY = sLocalParam.pCurY;uint8_t* pRefTmp = NULL, *pCurTmp = NULL;iRefRowStride  = sLocalParam.iRefStride << 3;iCurRowStride  = sLocalParam.iCurStride << 3;for (int32_t j = 0; j < sLocalParam.iBlock8x8Height; j++) {pRefTmp = pRefY;pCurTmp = pCurY;for (int32_t i = 0; i < sLocalParam.iBlock8x8Width; i++) {int32_t iSad = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmp, sLocalParam.iRefStride);m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD;pRefTmp += 8;pCurTmp += 8;}pRefY += iRefRowStride;pCurY += iCurRowStride;}}float  GetSceneChangeMotionRatioLarge() const {return m_fSceneChangeMotionRatioLarge;}float  GetSceneChangeMotionRatioMedium() const {return m_fSceneChangeMotionRatioMedium;}protected:SadFuncPtr m_pfSad;SSceneChangeResult& m_sParam;float    m_fSceneChangeMotionRatioLarge;float    m_fSceneChangeMotionRatioMedium;
};
  • WelsSampleSad8x8_c函数
int32_t WelsSampleSad8x8_c (uint8_t* pSample1, int32_t iStride1, uint8_t* pSample2, int32_t iStride2) {int32_t iSadSum = 0;int32_t i = 0;uint8_t* pSrc1 = pSample1;uint8_t* pSrc2 = pSample2;for (i = 0; i < 8; i++) {iSadSum += WELS_ABS ((pSrc1[0] - pSrc2[0]));iSadSum += WELS_ABS ((pSrc1[1] - pSrc2[1]));iSadSum += WELS_ABS ((pSrc1[2] - pSrc2[2]));iSadSum += WELS_ABS ((pSrc1[3] - pSrc2[3]));iSadSum += WELS_ABS ((pSrc1[4] - pSrc2[4]));iSadSum += WELS_ABS ((pSrc1[5] - pSrc2[5]));iSadSum += WELS_ABS ((pSrc1[6] - pSrc2[6]));iSadSum += WELS_ABS ((pSrc1[7] - pSrc2[7]));pSrc1 += iStride1;pSrc2 += iStride2;}return iSadSum;
}

CSceneChangeDetectorScreen类

  1. 功能:通过CSceneChangeDetection类模板调用CSceneChangeDetectorScreen类中方法实现桌面视频场景变化检测功能类
  2. 过程
  • 第一步:同CSceneChangeDetectorVideo类中检测过程;
  • 第二步:CSceneChangeDetectorScreen类中operator重载;
    • 获取滚动检测标志bScrollDetectFlag和 mv 坐标iScrollMvX、iScrollMvY;
    • 初始化工作;
    • 双层 for 嵌套循环处理每个 8x8 图像块;
      • 调用m_pfSad函数计算 iSad;
      • 如果 iSad 为 0,则标记当前块为COLLOCATED_STATIC,表明是静止的;
      • 如果滚动检测标志为真,并且滚动向量不为空,当前块的坐标加上滚动向量后仍在图像范围内;
        • 使用滚动向量调整参考块的位置pRefTmpScroll;
        • 再次调用m_pfSad函数,得到iSadScroll值;
        • 如果 iSadScroll 为 0,则标记当前块为COLLOCATED_STATIC,表明是静止的;
        • 否则,
          • 将 iSad 累加到iFrameComplexity;
          • 判断 iSad 与HIGH_MOTION_BLOCK_THRESHOLD的大小关系,将结果累加到iMotionBlockNum;
      • 否则,
        • 将 iSad 累加到iFrameComplexity;
        • 判断 iSad 与HIGH_MOTION_BLOCK_THRESHOLD的大小关系,将结果累加到iMotionBlockNum;
      • 更新图像块位置。
  1. 相关源码
  • CSceneChangeDetection模板类
template<typename T>
class CSceneChangeDetection : public IStrategy {public:CSceneChangeDetection (EMethods eMethod, int32_t iCpuFlag): m_cDetector (m_sSceneChangeParam, iCpuFlag) {m_eMethod   = eMethod;WelsMemset (&m_sSceneChangeParam, 0, sizeof (m_sSceneChangeParam));}~CSceneChangeDetection() {}EResult Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {EResult eReturn = RET_INVALIDPARAM;m_sLocalParam.iWidth = pSrcPixMap->sRect.iRectWidth;m_sLocalParam.iHeight = pSrcPixMap->sRect.iRectHeight;m_sLocalParam.iBlock8x8Width = m_sLocalParam.iWidth >> 3;m_sLocalParam.iBlock8x8Height = m_sLocalParam.iHeight >> 3;m_sLocalParam.pRefY = (uint8_t*)pRefPixMap->pPixel[0];m_sLocalParam.pCurY = (uint8_t*)pSrcPixMap->pPixel[0];m_sLocalParam.iRefStride = pRefPixMap->iStride[0];m_sLocalParam.iCurStride = pSrcPixMap->iStride[0];m_sLocalParam.pStaticBlockIdc = m_sSceneChangeParam.pStaticBlockIdc;int32_t iBlock8x8Num = m_sLocalParam.iBlock8x8Width * m_sLocalParam.iBlock8x8Height;int32_t iSceneChangeThresholdLarge = WelsStaticCast (int32_t,m_cDetector.GetSceneChangeMotionRatioLarge() * iBlock8x8Num + 0.5f + PESN);int32_t iSceneChangeThresholdMedium = WelsStaticCast (int32_t,m_cDetector.GetSceneChangeMotionRatioMedium() * iBlock8x8Num + 0.5f + PESN);m_sSceneChangeParam.iMotionBlockNum = 0;m_sSceneChangeParam.iFrameComplexity = 0;m_sSceneChangeParam.eSceneChangeIdc = SIMILAR_SCENE;m_cDetector (m_sLocalParam);if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdLarge) {m_sSceneChangeParam.eSceneChangeIdc = LARGE_CHANGED_SCENE;} else if (m_sSceneChangeParam.iMotionBlockNum >= iSceneChangeThresholdMedium) {m_sSceneChangeParam.eSceneChangeIdc = MEDIUM_CHANGED_SCENE;}eReturn = RET_SUCCESS;return eReturn;}EResult Get (int32_t iType, void* pParam) {if (pParam == NULL) {return RET_INVALIDPARAM;}* (SSceneChangeResult*)pParam = m_sSceneChangeParam;return RET_SUCCESS;}EResult Set (int32_t iType, void* pParam) {if (pParam == NULL) {return RET_INVALIDPARAM;}m_sSceneChangeParam = * (SSceneChangeResult*)pParam;return RET_SUCCESS;}private:SSceneChangeResult m_sSceneChangeParam;SLocalParam m_sLocalParam;T          m_cDetector;
};
  • CSceneChangeDetectorScreen
class CSceneChangeDetectorScreen : public CSceneChangeDetectorVideo {public:CSceneChangeDetectorScreen (SSceneChangeResult& sParam, int32_t iCpuFlag) : CSceneChangeDetectorVideo (sParam,iCpuFlag) {m_fSceneChangeMotionRatioLarge = SCENE_CHANGE_MOTION_RATIO_LARGE_SCREEN;m_fSceneChangeMotionRatioMedium = SCENE_CHANGE_MOTION_RATIO_MEDIUM;}virtual ~CSceneChangeDetectorScreen() {}void operator() (SLocalParam& sLocalParam) {bool bScrollDetectFlag = m_sParam.sScrollResult.bScrollDetectFlag;int32_t iScrollMvX = m_sParam.sScrollResult.iScrollMvX;int32_t iScrollMvY = m_sParam.sScrollResult.iScrollMvY;int32_t iRefRowStride = 0, iCurRowStride = 0;uint8_t* pRefY = sLocalParam.pRefY;uint8_t* pCurY = sLocalParam.pCurY;uint8_t* pRefTmp = NULL, *pCurTmp = NULL;int32_t iWidth = sLocalParam.iWidth;int32_t iHeight = sLocalParam.iHeight;iRefRowStride  = sLocalParam.iRefStride << 3;iCurRowStride  = sLocalParam.iCurStride << 3;for (int32_t j = 0; j < sLocalParam.iBlock8x8Height; j++) {pRefTmp = pRefY;pCurTmp = pCurY;for (int32_t i = 0; i < sLocalParam.iBlock8x8Width; i++) {int32_t iBlockPointX = i << 3;int32_t iBlockPointY = j << 3;uint8_t uiBlockIdcTmp = NO_STATIC;int32_t iSad = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmp, sLocalParam.iRefStride);if (iSad == 0) {uiBlockIdcTmp = COLLOCATED_STATIC;} else if (bScrollDetectFlag && (!iScrollMvX || !iScrollMvY) && (iBlockPointX + iScrollMvX >= 0)&& (iBlockPointX + iScrollMvX <= iWidth - 8) &&(iBlockPointY + iScrollMvY >= 0) && (iBlockPointY + iScrollMvY <= iHeight - 8)) {uint8_t* pRefTmpScroll = pRefTmp + iScrollMvY * sLocalParam.iRefStride + iScrollMvX;int32_t iSadScroll = m_pfSad (pCurTmp, sLocalParam.iCurStride, pRefTmpScroll, sLocalParam.iRefStride);if (iSadScroll == 0) {uiBlockIdcTmp = SCROLLED_STATIC;} else {m_sParam.iFrameComplexity += iSad;m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD;}} else {m_sParam.iFrameComplexity += iSad;m_sParam.iMotionBlockNum += iSad > HIGH_MOTION_BLOCK_THRESHOLD;}* (sLocalParam.pStaticBlockIdc) ++ = uiBlockIdcTmp;pRefTmp += 8;pCurTmp += 8;}pRefY += iRefRowStride;pCurY += iCurRowStride;}}
};
  • WelsSampleSad8x8_c函数
int32_t WelsSampleSad8x8_c (uint8_t* pSample1, int32_t iStride1, uint8_t* pSample2, int32_t iStride2) {int32_t iSadSum = 0;int32_t i = 0;uint8_t* pSrc1 = pSample1;uint8_t* pSrc2 = pSample2;for (i = 0; i < 8; i++) {iSadSum += WELS_ABS ((pSrc1[0] - pSrc2[0]));iSadSum += WELS_ABS ((pSrc1[1] - pSrc2[1]));iSadSum += WELS_ABS ((pSrc1[2] - pSrc2[2]));iSadSum += WELS_ABS ((pSrc1[3] - pSrc2[3]));iSadSum += WELS_ABS ((pSrc1[4] - pSrc2[4]));iSadSum += WELS_ABS ((pSrc1[5] - pSrc2[5]));iSadSum += WELS_ABS ((pSrc1[6] - pSrc2[6]));iSadSum += WELS_ABS ((pSrc1[7] - pSrc2[7]));pSrc1 += iStride1;pSrc2 += iStride2;}return iSadSum;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/25266.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux -- 了解 vim

目录 vim Linux 怎么编写代码&#xff1f; 了解 vim 的模式 什么是命令模式&#xff1f; 命令模式下 vim 的快捷键&#xff1a; 光标定位&#xff1a; 复制粘贴&#xff1a; 删除及撤销&#xff1a; 注释代码&#xff1a; 什么是底行模式&#xff1f; ​编辑 ​编辑…

Java:111-SpringMVC的底层原理(中篇)

这里续写上一章博客&#xff08;110章博客&#xff09;&#xff1a; 现在我们来学习一下高级的技术&#xff0c;前面的mvc知识&#xff0c;我们基本可以在67章博客及其后面相关的博客可以学习到&#xff0c;现在开始学习精髓&#xff1a; Spring MVC 高级技术&#xff1a; …

Large-Scale LiDAR Consistent Mapping usingHierarchical LiDAR Bundle Adjustment

1. 代码地址 GitHub - hku-mars/HBA: [RAL 2023] A globally consistent LiDAR map optimization module 2. 摘要 重建精确一致的大规模激光雷达点云地图对于机器人应用至关重要。现有的基于位姿图优化的解决方案&#xff0c;尽管它在时间方面是有效的&#xff0c;但不能直接…

ubuntu使用docker安装openwrt

系统&#xff1a;ubuntu24.04 架构&#xff1a;x86 1. 安装docker 1.1 离线安装 docker下载地址 根据系统版本&#xff0c;依次下载最新的三个关于docker的软件包 container.io&#xff08;注意后缀版本顺序&#xff09;docker-ce-clidocker-ce 然后再ubuntu系统中依次按顺…

【召回第一篇】召回方法综述

各个网站上找的各位大神的优秀回答&#xff0c;记录再此。 首先是石塔西大佬的回答&#xff1a;工业界推荐系统中有哪些召回策略&#xff1f; 万变不离其宗&#xff1a;用统一框架理解向量化召回前言常读我的文章的同学会注意到&#xff0c;我一直强调、推崇&#xff0c;不要…

多种策略提升线上 tensorflow 模型推理速度

前言 本文以最常见的模型 Bi-LSTM-CRF 为例&#xff0c;总结了在实际工作中能有效提升在 CPU/GPU 上的推理速度的若干方法&#xff0c;包括优化模型结构&#xff0c;优化超参数&#xff0c;使用 onnx 框架等。当然如果你有充足的 GPU &#xff0c;结合以上方法提升推理速度的效…

真空衰变,真正的宇宙级灾难,它到底有多可怕?

真空衰变&#xff0c;真正的宇宙级灾难&#xff0c;它到底有多可怕&#xff1f; 真空衰变 真空衰变&#xff08;Vacuum decay&#xff09;是物理学家根据量子场论推测出的一种宇宙中可能会发生的现象&#xff0c;这种现象被称为真正的宇宙级灾难&#xff0c;它到底有多可怕呢…

前端 Vue 操作文件方法(导出下载、图片压缩、文件上传和转换)

一、前言 本文对前端 Vue 项目开发过程中&#xff0c;经常遇到要对文件做一些相关操作&#xff0c;比如&#xff1a;文件导出下载、文件上传、图片压缩、文件转换等一些处理方法进行归纳整理&#xff0c;方便后续查阅和复用。 二、具体内容 1、后端的文件导出接口&#xff0c;…

【报文数据流中的反压处理】

报文数据流中的反压处理 1 带存储体的反压1.1 原理图1.2 Demo 尤其是在NP芯片中&#xff0c;经常涉及到报文的数据流处理&#xff1b;为了防止数据丢失&#xff0c;和各模块的流水处理&#xff1b;因此需要到反压机制&#xff1b; 反压机制目前接触到的有两种&#xff1a;一是基…

【深度学习】目标检测,Faster-RCNN算法训练,使用mmdetection训练

文章目录 资料环境数据测试 资料 https://mmdetection.readthedocs.io/zh-cn/latest/user_guides/config.html 环境 Dockerfile ARG PYTORCH"1.9.0" ARG CUDA"11.1" ARG CUDNN"8"FROM pytorch/pytorch:${PYTORCH}-cuda${CUDA}-cudnn${CUDNN}…

使用 Scapy 库编写 TCP 劫持攻击脚本

一、介绍 TCP劫持攻击&#xff08;TCP Hijacking&#xff09;&#xff0c;也称为会话劫持&#xff0c;是一种攻击方式&#xff0c;攻击者在合法用户与服务器之间的通信过程中插入或劫持数据包&#xff0c;从而控制通信会话。通过TCP劫持&#xff0c;攻击者可以获取敏感信息、执…

mysql 更改数据存储目录

先停止 mysql &#xff1a;sudo systemctl start/stop mysql 新建新的目录&#xff0c; 比如 /mnt/data/systemdata/mysql/mysql_data sudo chown -R mysql:mysql /mnt/data/sysdata/mysql/mysql_data sudo chmod -R 750 /mnt/data/sysdata/mysql/mysql_data 更改mysql.cnf…

2024高考作文-ChatGPT完成答卷,邀请大家来打分

高考&#xff0c;愿你脑洞大开&#xff0c;知识点全都扎根脑海&#xff1b;考试时手感倍儿棒&#xff0c;答题如行云流水&#xff1b;成绩公布时&#xff0c;笑容如春风拂面&#xff0c;心情如阳光普照&#xff01;高考加油&#xff0c;你一定行&#xff01; 新课标I卷 试题内…

“深入探讨Java中的对象拷贝:浅拷贝与深拷贝的差异与应用“

前言&#xff1a;在Java编程中&#xff0c;深拷贝&#xff08;Deep Copy&#xff09;与浅拷贝&#xff08;Shallow Copy&#xff09;是两个非常重要的概念。它们涉及到对象在内存中的复制方式&#xff0c;对于理解对象的引用、内存管理以及数据安全都至关重要。 ✨✨✨这里是秋…

多粒度特征融合(细粒度图像分类)

多粒度特征融合&#xff08;细粒度图像分类&#xff09; 摘要Abstract1. 多粒度特征融合1.1 文献摘要1.2 研究背景1.3 创新点1.4 模型方法1.4.1 Swin-Transformer1.4.2 多粒度特征融合模块1.4.3 自注意力1.4.4 通道注意力1.4.5 图卷积网络1.4.6 基于Vision-Transformer的两阶段…

Rust 实战丨SSE(Server-Sent Events)

&#x1f4cc; SSE&#xff08;Server-Sent Events&#xff09;是一种允许服务器向客户端浏览器推送信息的技术。它是 HTML5 的一部分&#xff0c;专门用于建立一个单向的从服务器到客户端的通信连接。SSE的使用场景非常广泛&#xff0c;包括实时消息推送、实时通知更新等。 S…

数据结构笔记 3 串 数组 广义表

以下了解即可&#xff0c;暂时没发现有什么考点 参考&#xff1a; 【数据结构】——多维数组和广义表_数据结构loc-CSDN博客 相对应的题目&#xff1a; 他这个数组不是从0开始的&#xff0c;是从1开始的&#xff0c;所以为了配合公式要减1 下面这道题又不一样&#xff0c;它是…

【python深度学习】——torch.einsum|torch.bmm

【python深度学习】——torch.einsum|torch.bmm 1. 基本用法与示例2. torch.bmm 1. 基本用法与示例 基本用法: torch.einsum(equation, *operands)equation: 一个字符串&#xff0c;定义了张量操作的模式。 使用逗号来分隔输入张量的索引&#xff0c;然后是一个箭头&#xff…

linux中dd命令以及如何测试读写速度

dd命令详解 dd命令是一个在Unix和类Unix系统中非常常用的命令行工具&#xff0c;它主要用于复制文件和转换文件数据。下面我会详细介绍一些dd命令的常见用法和功能&#xff1a; 基本语法 dd命令的基本语法如下&#xff1a; bash Copy Code dd [option]...主要选项和参数 if…

Data Mining2 复习笔记6 - Optimization Hyperparameter Tuning

6. Optimization & Hyperparameter Tuning Why Hyperparameter Tuning? Many learning algorithms for classification, regression, … Many of those have hyperparameters: k and distance function for k nearest neighbors, splitting and pruning options in decis…