当前位置: 首页 > news >正文

openh264 帧间预测编码过程源码分析

openh264

OpenH264 是一个开源的 H.264 编码和解码器,由思科系统开发并维护。它专为实时应用程序如 WebRTC 设计,提供了从基础到高级特性的广泛支持。OpenH264 的编码器支持从 Constrained Baseline Profile 到 5.2 级别,允许任意分辨率的编码,不限于 16x16 的倍数,并且具有自适应量化或恒定量化的速率控制、多切片选项、多线程自动用于多切片等特性。此外,它还支持高达 4 层的时序可伸缩性、单一输入的 4 种空间分辨率的 Spatial Simulcast、长期参考帧(LTR)、内存管理控制操作(MMCO)等功能。

帧间预测编码

视频帧间预测编码(Inter-frame prediction coding)是视频压缩技术中的一种关键方法,主要用于减少视频序列中时间维度上的冗余。这种编码方式依赖于视频帧之间的空间相关性,通过预测和补偿来减少数据量,从而实现高效的视频压缩。

帧间预测编码是视频编码中非常有效的技术,广泛应用于各种视频编码标准,如H.264/AVC、H.265/HEVC、VP9和AV1等。通过减少时间冗余,帧间预测编码显著提高了视频数据的压缩率,同时保持了视频质量。

帧间预测的核心技术主要包括以下几个方面:

  1. 运动估计(Motion Estimation, ME):

    • 运动估计是指在参考帧中搜索与当前块最匹配的区域,以确定最佳匹配块的位置。
  2. 运动补偿(Motion Compensation, MC):

    • 运动补偿使用运动估计得到的运动向量来预测当前块,通过补偿先前图像的抽样点来生成当前图像块的预测值。
  3. 宏块(Macroblock, MB)和子宏块(Sub-Macroblock)的树状结构分块:

    • H.264 支持多种宏块分割方式,如16x16、16x8、8x16和8x8,以及更细致的子宏块分割,如8x8、8x4、4x8和4x4。
  4. 多参考帧预测:

    • 特别是在B帧中,可以使用两个方向的参考帧(List0和List1)进行双向预测。
  5. 亚像素精度的运动估计:

    • 除了整像素精度外,H.264还支持1/2像素和1/4像素的亚像素插值,以提高预测精度。
  6. 快速搜索算法:

    • 为了减少计算复杂度,使用快速搜索算法来确定最佳匹配块。
  7. 运动向量的编码:

    • 运动向量的编码通常涉及编码运动向量与预测值的差值(MVD),而不是直接编码运动向量本身。
  8. 预测模式的选择:

    • H.264定义了多种预测模式,包括直接模式、双向模式、List0和List1模式等。
  9. 参考帧管理:

    • 管理参考帧以确保解码器能够正确地重建预测图像。
  10. 变换/量化编码和熵编码:

    • 这些步骤与帧内编码相同或相似,用于进一步压缩预测残差。

帧间预测通过这些技术有效地减少了视频序列中的时间冗余,提高了压缩效率。

openh264 帧间预测编码过程

  1. 帧间预测过程函数关系图
    在这里插入图片描述
  2. 关键模块说明
  • 通过API 函数EncodeFrame完成具体的编码过程,可执行程序封装该函数进行编码;
  • 通过二维数组g_pWelsSliceCoding[2][2]来完成具体的I 帧、P 帧,以及变化片数和非变化片数编码;
  • 在非变化片数帧间编码过程中,在WelsMdInterMbLoop函数中循环处理每个宏块;
  • 在变化片数帧间编码过程中,在 WelsMdInterMbLoopOverDynamicSlice函数中循环处理每个宏块;
  • pfInterMd函数指针指向具体的增强层WelsMdInterMbEnhancelayer或基本层WelsMdInterMb帧间预测过程;
  • 在基本层预测过程中,WelsMdInterSecondaryModesEnc函数完成二级帧间预测过程编码;
  • 在增强层预测过程中,WelsMdSpatialelInterMbIlfmdNoilp函数完成具体的预测过程编码;
  1. 帧间预测过程核心函数介绍
  • WelsMdInterMbLoopOverDynamicSlice 函数
  • 用于动态切片的宏块编码过程,循环处理每个 MB;
// Only for inter dynamic slicing
int32_t WelsMdInterMbLoopOverDynamicSlice (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd,const int32_t kiSliceFirstMbXY) {SWelsMD* pMd          = (SWelsMD*)pWelsMd;SBitStringAux* pBs    = pSlice->pSliceBsa;SDqLayer* pCurLayer   = pEncCtx->pCurDqLayer;SSliceCtx* pSliceCtx  = &pCurLayer->sSliceEncCtx;SMbCache* pMbCache    = &pSlice->sMbCacheInfo;SMB* pMbList          = pCurLayer->sMbDataP;SMB* pCurMb           = NULL;int32_t iNumMbCoded   = 0;const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;int32_t iNextMbIdx = kiSliceFirstMbXY;int32_t iCurMbIdx = -1;const int32_t kiMvdInterTableStride = pEncCtx->iMvdCostTableStride;uint16_t* pMvdCostTable = &pEncCtx->pMvdCostTable[pEncCtx->iMvdCostTableSize];const int32_t kiSliceIdx = pSlice->iSliceIdx;const int32_t kiPartitionId = (kiSliceIdx % pEncCtx->iActiveThreadsNum);const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;int32_t iEncReturn = ENC_RETURN_SUCCESS;SDynamicSlicingStack sDss;if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {WelsInitSliceCabac (pEncCtx, pSlice);sDss.iStartPos = sDss.iCurrentPos = 0;sDss.pRestoreBuffer = pEncCtx->pDynamicBsBuffer[kiPartitionId];} else {sDss.iStartPos = BsGetBitsPos (pBs);}pSlice->iMbSkipRun = 0;for (;;) {//DYNAMIC_SLICING_ONE_THREAD - MultiD//stack pBs pointerpEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, pSlice->iMbSkipRun);//point to current pMbiCurMbIdx = iNextMbIdx;pCurMb = &pMbList[ iCurMbIdx ];//step(1): set QP for the current MBpEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);// if already reaches the largest number of slices, set QPs to the upper boundif (pSlice->bDynamicSlicingSliceSizeCtrlFlag) {//a clearer logic may be://if there is no need from size control from the pSlice size, the QP will be decided by RC; else it will be set to the max QP//    however, there are some parameter updating in the rc_mb_init() function, so it cannot be skipped?pCurMb->uiLumaQp = pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].iMaxQp;pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];}//step (2). save some vale for future use, initial pWelsMdWelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);WelsMdInterInit (pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);TRY_REENCODING:WelsInitInterMDStruc (pCurMb, pMvdCostTable, kiMvdInterTableStride, pMd);pEncCtx->pFuncList->pfInterMd (pEncCtx, pMd, pSlice, pCurMb, pMbCache);//mb_qp//step (4): save from the MD process from future useWelsMdInterSaveSadAndRefMbType ((pCurLayer->pDecPic->uiRefMbType), pMbCache, pCurMb, pMd);pEncCtx->pFuncList->pfMdBackgroundInfoUpdate (pCurLayer, pCurMb, pMbCache->bCollocatedPredFlag,pEncCtx->pRefPic->iPictureType);//step (5): update cacheUpdateNonZeroCountCache (pCurMb, pMbCache);//step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skippediEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND  && (pCurMb->uiLumaQp < 50)) {pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);goto TRY_REENCODING;}if (ENC_RETURN_SUCCESS != iEncReturn)return iEncReturn;//DYNAMIC_SLICING_ONE_THREAD - MultiDsDss.iCurrentPos = pEncCtx->pFuncList->pfGetBsPosition (pSlice);if (DynSlcJudgeSliceBoundaryStepBack (pEncCtx, pSlice, pSliceCtx, pCurMb, &sDss)) {pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx -1; // update LastCodedMbIdxOfPartition, need to -1 due to stepping back++ pCurLayer->NumSliceCodedOfPartition[kiPartitionId];break;}//step (7): reconstruct current MBpCurMb->uiSliceIdc = kiSliceIdx;OutputPMbWithoutConstructCsRsNoCopy (pEncCtx, pCurLayer, pSlice, pCurMb);#if defined(MB_TYPES_CHECK)WelsCountMbType (pEncCtx->sPerInfo.iMbCount, P_SLICE, pCurMb);
#endif//MB_TYPES_CHECK//step (8): update status and other parameterspEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, pMd->iCostLuma, pSlice);/*judge if all pMb in cur pSlice has been encoded*/++ iNumMbCoded;iNextMbIdx = WelsGetNextMbOfSlice (pCurLayer, iCurMbIdx);//whether all of MB in current pSlice encoded or notif (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {pCurLayer->LastCodedMbIdxOfPartition[kiPartitionId] = iCurMbIdx;++ pCurLayer->NumSliceCodedOfPartition[kiPartitionId];break;}}if (pSlice->iMbSkipRun) {BsWriteUE (pBs, pSlice->iMbSkipRun);}return iEncReturn;
}}//namespace WelsEnc
  • WelsMdInterMbLoop函数
  • 用于固定切片的宏块编码过程,循环处理每个 MB;
// for inter non-dynamic pSlice
int32_t WelsMdInterMbLoop (sWelsEncCtx* pEncCtx, SSlice* pSlice, void* pWelsMd, const int32_t kiSliceFirstMbXY) {SWelsMD* pMd          = (SWelsMD*)pWelsMd;SBitStringAux* pBs    = pSlice->pSliceBsa;SDqLayer* pCurLayer   = pEncCtx->pCurDqLayer;SMbCache* pMbCache    = &pSlice->sMbCacheInfo;SMB* pMbList          = pCurLayer->sMbDataP;SMB* pCurMb           = NULL;int32_t iNumMbCoded   = 0;int32_t iNextMbIdx    = kiSliceFirstMbXY;int32_t iCurMbIdx     = -1;const int32_t kiTotalNumMb = pCurLayer->iMbWidth * pCurLayer->iMbHeight;const int32_t kiMvdInterTableStride = pEncCtx->iMvdCostTableStride;uint16_t* pMvdCostTable = &pEncCtx->pMvdCostTable[pEncCtx->iMvdCostTableSize];const int32_t kiSliceIdx = pSlice->iSliceIdx;const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;int32_t iEncReturn = ENC_RETURN_SUCCESS;SDynamicSlicingStack sDss;if (pEncCtx->pSvcParam->iEntropyCodingModeFlag) {WelsInitSliceCabac (pEncCtx, pSlice);sDss.pRestoreBuffer = NULL;sDss.iStartPos = sDss.iCurrentPos = 0;}pSlice->iMbSkipRun = 0;for (;;) {if (!pEncCtx->pSvcParam->iEntropyCodingModeFlag)pEncCtx->pFuncList->pfStashMBStatus (&sDss, pSlice, pSlice->iMbSkipRun);//point to current pMbiCurMbIdx = iNextMbIdx;pCurMb = &pMbList[ iCurMbIdx ];//step(1): set QP for the current MBpEncCtx->pFuncList->pfRc.pfWelsRcMbInit (pEncCtx, pCurMb, pSlice);//step (2). save some vale for future use, initial pWelsMdWelsMdIntraInit (pEncCtx, pCurMb, pMbCache, kiSliceFirstMbXY);WelsMdInterInit (pEncCtx, pSlice, pCurMb, kiSliceFirstMbXY);TRY_REENCODING:WelsInitInterMDStruc (pCurMb, pMvdCostTable, kiMvdInterTableStride, pMd);pEncCtx->pFuncList->pfInterMd (pEncCtx, pMd, pSlice, pCurMb, pMbCache);//mb_qp//step (4): save from the MD process from future useWelsMdInterSaveSadAndRefMbType ((pCurLayer->pDecPic->uiRefMbType), pMbCache, pCurMb, pMd);pEncCtx->pFuncList->pfMdBackgroundInfoUpdate (pCurLayer, pCurMb, pMbCache->bCollocatedPredFlag,pEncCtx->pRefPic->iPictureType);//step (5): update cacheUpdateNonZeroCountCache (pCurMb, pMbCache);//step (6): begin to write bit stream; if the pSlice size is controlled, the writing may be skippediEncReturn = pEncCtx->pFuncList->pfWelsSpatialWriteMbSyn (pEncCtx, pSlice, pCurMb);if (!pEncCtx->pSvcParam->iEntropyCodingModeFlag) {if (iEncReturn == ENC_RETURN_VLCOVERFLOWFOUND && (pCurMb->uiLumaQp < 50)) {pSlice->iMbSkipRun = pEncCtx->pFuncList->pfStashPopMBStatus (&sDss, pSlice);UpdateQpForOverflow (pCurMb, kuiChromaQpIndexOffset);goto TRY_REENCODING;}}if (ENC_RETURN_SUCCESS != iEncReturn)return iEncReturn;//step (7): reconstruct current MBpCurMb->uiSliceIdc = kiSliceIdx;OutputPMbWithoutConstructCsRsNoCopy (pEncCtx, pCurLayer, pSlice, pCurMb);#if defined(MB_TYPES_CHECK)WelsCountMbType (pEncCtx->sPerInfo.iMbCount, P_SLICE, pCurMb);
#endif//MB_TYPES_CHECK//step (8): update status and other parameterspEncCtx->pFuncList->pfRc.pfWelsRcMbInfoUpdate (pEncCtx, pCurMb, pMd->iCostLuma, pSlice);/*judge if all pMb in cur pSlice has been encoded*/++ iNumMbCoded;iNextMbIdx = WelsGetNextMbOfSlice (pCurLayer, iCurMbIdx);//whether all of MB in current pSlice encoded or notif (iNextMbIdx == -1 || iNextMbIdx >= kiTotalNumMb || iNumMbCoded >= kiTotalNumMb) {break;}}if (pSlice->iMbSkipRun) {BsWriteUE (pBs, pSlice->iMbSkipRun);}return iEncReturn;
}
  • WelsMdInterMb函数
  • 基本层的预测编码的核心实现函数,主要用模式决策等过程;
void WelsMdInterMb (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb, SMbCache* pUnused) {SDqLayer* pCurDqLayer             = pEncCtx->pCurDqLayer;SMbCache* pMbCache                = &pSlice->sMbCacheInfo;const uint32_t kuiNeighborAvail   = pCurMb->uiNeighborAvail;const int32_t kiMbWidth           = pCurDqLayer->iMbWidth;const  SMB* top_mb                = pCurMb - kiMbWidth;const bool bMbLeftAvailPskip      = ((kuiNeighborAvail & LEFT_MB_POS) ? IS_SKIP ((pCurMb - 1)->uiMbType) : false);const bool bMbTopAvailPskip       = ((kuiNeighborAvail & TOP_MB_POS) ? IS_SKIP (top_mb->uiMbType) : false);const bool bMbTopLeftAvailPskip   = ((kuiNeighborAvail & TOPLEFT_MB_POS) ? IS_SKIP ((top_mb - 1)->uiMbType) : false);const bool bMbTopRightAvailPskip = ((kuiNeighborAvail & TOPRIGHT_MB_POS) ? IS_SKIP ((top_mb + 1)->uiMbType) : false);bool bTrySkip = bMbLeftAvailPskip || bMbTopAvailPskip || bMbTopLeftAvailPskip || bMbTopRightAvailPskip;bool bKeepSkip = bMbLeftAvailPskip && bMbTopAvailPskip && bMbTopRightAvailPskip;bool bSkip = false;//try BGD skipif (pEncCtx->pFuncList->pfInterMdBackgroundDecision (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache, &bKeepSkip)) {return;}//try static or scrolled Pskipif (pEncCtx->pFuncList->pfSCDPSkipDecision (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache)) {return;}//step 1: try SKIPbSkip = WelsMdInterJudgePskip (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache, bTrySkip);if (bSkip) {if (bKeepSkip) {WelsMdInterDecidedPskip (pEncCtx,  pSlice,  pCurMb, pMbCache);return;}} else {PredictSad (pMbCache->sMvComponents.iRefIndexCache, pMbCache->iSadCost, 0, &pWelsMd->iSadPredMb);//step 2: P_16x16pWelsMd->iCostLuma = WelsMdP16x16 (pEncCtx->pFuncList, pCurDqLayer, pWelsMd, pSlice, pCurMb);pCurMb->uiMbType = MB_TYPE_16x16;}WelsMdInterSecondaryModesEnc (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache, bSkip);
}
  • WelsMdInterSecondaryModesEnc函数
  • 基本层帧间二级模式的编码实现函数,主要用与判断出了 skip 和 p16x16 块类型之外的模式决策;
void WelsMdInterSecondaryModesEnc (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb,SMbCache* pMbCache, const bool bSkip) {//step 2: Intraconst bool kbTrySkip = pEncCtx->pFuncList->pfFirstIntraMode (pEncCtx, pWelsMd, pCurMb, pMbCache);if (kbTrySkip)return;if (bSkip) {WelsMdInterDecidedPskip (pEncCtx,  pSlice,  pCurMb, pMbCache);} else {//Step 3: SubP16 MDpEncCtx->pFuncList->pfSetScrollingMv (pEncCtx->pVaa, pWelsMd); //SCCpEncCtx->pFuncList->pfInterFineMd (pEncCtx, pWelsMd, pSlice, pCurMb, pWelsMd->iCostLuma);//refinement for inter typeWelsMdInterMbRefinement (pEncCtx, pWelsMd, pCurMb, pMbCache);//step 7: invoke encodingWelsMdInterEncode (pEncCtx, pSlice, pCurMb, pMbCache);//step 8: double check PskipWelsMdInterDoubleCheckPskip (pCurMb, pMbCache);}
}
  • WelsMdSpatialelInterMbIlfmdNoilp函数
  • 增强层的预测编码的核心实现函数,主要用模式决策等过程;
//
// MD for enhancement layers
//
void WelsMdSpatialelInterMbIlfmdNoilp (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SSlice* pSlice,SMB* pCurMb, const Mb_Type kuiRefMbType) {SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;SMbCache* pMbCache = &pSlice->sMbCacheInfo;const uint32_t kuiNeighborAvail = pCurMb->uiNeighborAvail;const int32_t kiMbWidth = pCurDqLayer->iMbWidth;const  SMB* kpTopMb = pCurMb - kiMbWidth;const bool kbMbLeftAvailPskip = ((kuiNeighborAvail & LEFT_MB_POS) ? IS_SKIP ((pCurMb - 1)->uiMbType) : false);const bool kbMbTopAvailPskip  = ((kuiNeighborAvail & TOP_MB_POS) ? IS_SKIP (kpTopMb->uiMbType) : false);const bool kbMbTopLeftAvailPskip  = ((kuiNeighborAvail & TOPLEFT_MB_POS) ? IS_SKIP ((kpTopMb - 1)->uiMbType) : false);const bool kbMbTopRightAvailPskip = ((kuiNeighborAvail & TOPRIGHT_MB_POS) ? IS_SKIP ((kpTopMb + 1)->uiMbType) : false);bool bTrySkip  = kbMbLeftAvailPskip | kbMbTopAvailPskip | kbMbTopLeftAvailPskip | kbMbTopRightAvailPskip;bool bKeepSkip = kbMbLeftAvailPskip & kbMbTopAvailPskip & kbMbTopRightAvailPskip;bool bSkip = false;if (pEncCtx->pFuncList->pfInterMdBackgroundDecision (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache, &bKeepSkip)) {return;}//step 1: try SKIPbSkip = WelsMdInterJudgePskip (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache, bTrySkip);if (bSkip && bKeepSkip) {WelsMdInterDecidedPskip (pEncCtx,  pSlice,  pCurMb, pMbCache);return;}if (! IS_SVC_INTRA (kuiRefMbType)) {if (!bSkip) {PredictSad (pMbCache->sMvComponents.iRefIndexCache, pMbCache->iSadCost, 0, &pWelsMd->iSadPredMb);//step 2: P_16x16pWelsMd->iCostLuma = WelsMdP16x16 (pEncCtx->pFuncList, pCurDqLayer, pWelsMd, pSlice, pCurMb);pCurMb->uiMbType = MB_TYPE_16x16;}WelsMdInterSecondaryModesEnc (pEncCtx, pWelsMd, pSlice, pCurMb, pMbCache, bSkip);} else { //BLMODE == SVC_INTRA//initial prediction memory for I_16x16const int32_t kiCostI16x16 = WelsMdI16x16 (pEncCtx->pFuncList, pEncCtx->pCurDqLayer, pMbCache, pWelsMd->iLambda);if (bSkip && (pWelsMd->iCostLuma <= kiCostI16x16)) {WelsMdInterDecidedPskip (pEncCtx,  pSlice,  pCurMb, pMbCache);} else {pWelsMd->iCostLuma = kiCostI16x16;pCurMb->uiMbType = MB_TYPE_INTRA16x16;WelsMdIntraSecondaryModesEnc (pEncCtx, pWelsMd, pCurMb, pMbCache);}}
}

相关文章:

openh264 帧间预测编码过程源码分析

openh264 OpenH264 是一个开源的 H.264 编码和解码器&#xff0c;由思科系统开发并维护。它专为实时应用程序如 WebRTC 设计&#xff0c;提供了从基础到高级特性的广泛支持。OpenH264 的编码器支持从 Constrained Baseline Profile 到 5.2 级别&#xff0c;允许任意分辨率的编…...

Linux网络 - HTTP协议

文章目录 前言一、HTTP协议1.urlurl特殊字符 requestrespond 总结 前言 上一章内容我们讲了在应用层制定了我们自己自定义的协议、序列化和反序列化。 协议的制定相对来讲还是比较麻烦的&#xff0c;不过既然应用层的协议制定是必要的&#xff0c;那么肯定已经有许多计算机大佬…...

面试题——Nginx

1.Nginx是什么&#xff1f; 是一个高性能的Web服务器和反向代理服务器&#xff0c;也可以作为静态文件的缓存服务器&#xff0c;也能够进行负载均衡。 2.Nginx的作用&#xff1f; 1.反向代理&#xff1a;将多台服务器代理为一台服务器。客户端不了解底层服务端。 2.负载均衡…...

持续学习的综述: 理论、方法与应用

摘要 为了应对现实世界的动态&#xff0c;智能系统需要在其整个生命周期中增量地获取、更新、积累和利用知识。这种能力被称为持续学习&#xff0c;为人工智能系统自适应发展提供了基础。从一般意义上讲&#xff0c;持续学习明显受到灾难性遗忘的限制&#xff0c;在这种情况下…...

跨域资源共享(CORS)问题与解决方案

跨域资源共享&#xff08;CORS&#xff0c;Cross-Origin Resource Sharing&#xff09;是现代web开发中常见且重要的一个概念。它涉及到浏览器的同源策略&#xff08;Same-Origin Policy&#xff09;&#xff0c;该策略用于防止恶意网站从不同来源窃取数据。然而&#xff0c;在…...

实用软件分享-----一款免费的人工智能替换face的神器

专栏介绍:本专栏主要分享一些实用的软件(Po Jie版); 声明1:软件不保证时效性;只能保证在写本文时,该软件是可用的;不保证后续时间该软件能一直正常运行;不保证没有bug;如果软件不可用了,我知道后会第一时间在题目上注明(已失效)。介意者请勿订阅。 声明2:本专栏的…...

不可思议!这款 Python 库竟然能自动生成GUI界面:MagicGUI

目录 什么是MagicGUI&#xff1f; ​编辑 MagicGUI的工作原理 安装MagicGUI 创建你的第一个GUI ​编辑 其他案例 输入值对话框 大家好&#xff0c;今天我们来聊一聊一个非常有趣且实用的Python库——MagicGUI。这个库可以让你用最少的代码&#xff0c;快速创建图形用户…...

论文发表CN期刊《高考》是什么级别的刊物?

论文发表CN期刊《高考》是什么级别的刊物&#xff1f; 《高考》是由吉林省长春出版社主管并主办的省级教育类期刊&#xff0c;期刊以科教兴国战略为服务宗旨&#xff0c;专门反映和探索国内外教育教学和科研实践的最新成果。该期刊致力于为广大教育工作者提供一个高质量的学术…...

离散数学复习

1.关系的介绍和性质 &#xff08;1&#xff09;序偶和笛卡尔积 两个元素按照一定的顺序组成的二元组就是序偶&#xff0c;使用尖括号进行表示&#xff0c;尖括号里面的元素一般都是有顺序的&#xff1b; 笛卡尔积就是有两个集合&#xff0c;从第一个集合里面选择一个元素&am…...

华为网络设备高频命令

1.system-view • 用法&#xff1a;在用户视图下执行 system-view 命令。 • 作用&#xff1a;进入系统视图&#xff0c;以便进行配置性的操作。 • 场景&#xff1a;当需要对设备进行系统级的配置时。 2.sysname XXX • 用法&#xff1a;执行 [Huawei]sysname XXX 命令。…...

信友队:南风的收集

C. [202406C]楠枫的收集 文件操作 时间限制: 1000ms 空间限制: 262144KB 输入文件名: 202406C.in 输出文件名: 202406C.out Accepted 100 分 题目描述 一年四季&#xff0c;寒暑交替&#xff0c;楠枫总是会收集每一个季节的树叶&#xff0c;并把它们制作成标本收集起来。当…...

找工作小项目:day16-重构核心库、使用智能指针(3)

day16-重构核心库、使用智能指针&#xff08;3&#xff09; 最后将使用这个库的方式进行展示。 1、客户端 在while ((o getopt(argc, argv, optstring)) ! -1)所有的操作都是获取参数的操作&#xff0c;threads 、msgs 和wait 分别指线程数、消息长度以及等待时间。 创建一…...

软考中级|软件设计师-知识点整理

目录 计算机网络概论 计算机系统基础知识 中央处理单元 数据表示 校验码 计算机体系结构 计算机体系结构的发展 存储系统 输入/输出技术 安全性、可靠性与系统性能评测基础知识 加密技术和认证技术 计算机可靠性 程序设计语言基础知识 程序设计语言概述 程序设计…...

HTML5基础

1 HTML基础概念&#xff08;难点&#xff09; WWW&#xff08;World Wide Web&#xff0c;万维网&#xff09;是一种建立在 Internet 上的信息资源网络。 WWW 有 3 个基本组成部分&#xff0c;分别是 URL&#xff1a;Universal Resource Locators&#xff0c;统一资源定位器 HT…...

python,ipython 和 jupyter notebook 之间的关系

python&#xff0c;ipython 和 jupyter notebook 之间的关系 文章目录 python&#xff0c;ipython 和 jupyter notebook 之间的关系1. Python2. IPython3. Jupyter Notebook启动 Jupyter Notebook 关系总结 Python、IPython 和 Jupyter Notebook 是相互关联但具有不同功能的工具…...

聊聊DoIP吧(三)-端口号port

DoIP在UDP和TCP建立连接和发送诊断报文的过程中使用的端口定义如下&#xff1a;...

【将xml文件转yolov5训练数据txt标签文件】连classes.txt都可以生成

将xml文件转yolov5训练数据txt标签文件 前言一、代码解析 二、使用方法总结 前言 找遍全网&#xff0c;我觉得写得最详细的就是这个博文⇨将xml文件转yolov5训练数据txt标签文件 虽然我还是没有跑成功。那个正则表达式我不会改QWQ&#xff0c;但是不妨碍我会训练ai。 最终成功…...

针对k8s集群已经加入集群的服务器进行驱逐

例如k8s 已经有很多服务器&#xff0c;现在由于服务器资源过剩&#xff0c;需要剥离一些服务器出来 查找节点名称&#xff1a; kubectl get nodes设置为不可调度&#xff1a; kubectl cordon k8s-node13恢复可调度 kubectl uncordon k8s-node13在驱逐之前先把需要剥离驱逐的节…...

go 1.22 增强 http.ServerMux 路由能力

之前 server func main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Println("Received request:", r.URL.Path)fmt.Fprintf(w, "Hello, client! You requested: %s\n", r.URL.Path)})log.Println("Serv…...

赶紧收藏!2024 年最常见 20道设计模式面试题(二)

上一篇地址&#xff1a;赶紧收藏&#xff01;2024 年最常见 20道设计模式面试题&#xff08;一&#xff09;-CSDN博客 三、解释抽象工厂模式&#xff0c;并给出一个实际应用的例子。 抽象工厂模式是一种创建型设计模式&#xff0c;用于创建一系列相关或依赖对象的接口&#x…...

Java面向对象设计 - Java泛型约束

Java面向对象设计 - Java泛型约束 无限通配符 通配符类型由问号表示&#xff0c;如<&#xff1f;> 。 对于通用类型&#xff0c;通配符类型是对象类型用于原始类型。 我们可以将任何已知类型的泛型分配为通配符类型。 这里是示例代码: // MyBag of String type M…...

什么是内存泄漏?如何避免内存泄漏?

**内存泄漏&#xff08;Memory Leak&#xff09;**是指在程序运行过程中&#xff0c;已经动态分配的堆内存由于某种原因程序未释放或无法释放&#xff0c;造成系统内存的浪费&#xff0c;导致程序运行速度减慢甚至系统崩溃等严重后果。内存泄漏具有隐蔽性、积累性的特征&#x…...

元组(tuple)(Python)

文章目录 一、定义二、常用操作 一、定义 tuple ("张三", "李四", "王二")二、常用操作 分类关键字/函数/方法说明查询元组[索引]根据索引取值&#xff0c;索引不存在会报错len(元组)元组长度&#xff08;元素个数&#xff09;值 in 元组&…...

【C++进阶学习】第二弹——继承(下)——挖掘继承深处的奥秘

继承&#xff08;上&#xff09;&#xff1a;【C进阶学习】第一弹——继承&#xff08;上&#xff09;——探索代码复用的乐趣-CSDN博客 前言&#xff1a; 在前面我们已经讲了继承的基础知识&#xff0c;让大家了解了一下继承是什么&#xff0c;但那些都不是重点&#xff0c;今…...

LangChain-ChatGLM本地搭建|报错合集(win10)

安装过程 1. 创建虚拟环境 conda create -n langchain-chatglm python3.10 conda activate langchain-chatglm2. 部署 langchain-ChatGLM git clone https://github.com/imClumsyPanda/langchain-ChatGLMpip3 install -r requirements.txt pip3 install -U gradio pip3 inst…...

IP地址简介

一、IP地址 Internet Protocol Address&#xff0c;即网络层协议地址&#xff0c;是IP的缩写。 二、IP地址的作用 为什么不直接使用MAC&#xff0c;又加了一个IP地址呢&#xff1f; 事实上底层传输&#xff0c;最终使用的肯定是MAC地址&#xff0c;但是由于在以前&#x…...

谈吐的艺术

被人表扬&#xff0c;该怎么回应 你越是说自己其实没那么好&#xff0c; 对方出于客气&#xff0c; 就越是要证明你其实比你说的好得多。 O可能遇到的问题 每当工作和学习上做出点成绩&#xff0c;有人夸奖我的时候&#xff0c;我都会觉得很尴尬。因为不谦虚会得罪人&#xff…...

Linux 和 分区

文章目录 流程挂载设备文件名 Linux 下各分区的含义家目录 流程 在windows中&#xff0c;一个硬盘要使用只需要分区、格式化之后就可以使用了 在linux中&#xff0c;除了分区和格式化之外&#xff0c;还需要一个叫挂载的操作 挂载 挂载&#xff0c;就相当于windows环境下的写…...

⭐ ▶《强化学习的数学原理》(2024春)_西湖大学赵世钰 Ch3 贝尔曼最优公式 【压缩映射定理】

PPT 截取必要信息。 课程网站做习题。总体 MOOC 过一遍 1、视频 学堂在线 习题 2、过 电子书&#xff0c;补充 【下载&#xff1a;本章 PDF 电子书 GitHub 界面链接】 [又看了一遍视频] 3、总体 MOOC 过一遍 习题 学堂在线 课程页面链接 中国大学MOOC 课程页面链接 B 站 视频链…...

Pikachu上的CSRF以及NSSCTF上的[NISACTF 2022]bingdundun~、 [SWPUCTF 2022 新生赛]xff

目录 一、CSRF CSRF(get) login CSRF(post) CSRF Token 二、CSRF的相关知识点 &#xff08;1&#xff09;什么是CSRF&#xff1f; &#xff08;2&#xff09;工作原理 &#xff08;3&#xff09;CSRF漏洞形成的条件 1、用户要在登录状态&#xff08;即浏览器保存了该…...

企业网站seo数据/营销型网站分为哪几种

2019独角兽企业重金招聘Python工程师标准>>> 邹建锋&#xff1a;手机游戏系列化运营模式探讨 国内移动市场在爆发式的增长&#xff0c;移动终端在大规模的普及&#xff0c;用户越来越习惯在手机上玩游戏&#xff0c;那么什么样的游戏才能赚钱&#xff1f;该文档…...

wordpress改域名后500/网络营销的特征和功能

typedef struct bthnode { ElemType data; struct bthnode *lchild,*rchild; int ltag,rtag; }BthNode; 若ltag0,表示左指针指向左孩子&#xff0c;ltag1,表示左指针指向前趋节点 若rtag0,表示左指针指向左孩子&#xff0c;rtag1,表示左指针指向前趋节点...

网页设计实验报告结果/优化大师win10

本文中概述的一些准则可以被客观地评价;其他的&#xff0c;则是有场景的、上下文环境的或主观的。 最重要的一点&#xff0c;是保持一致性。 一致性的代码更容易维护&#xff0c;更容易优化&#xff0c;需要更少的学习成本&#xff0c;并且随着新约定的出现或bug类的修复&…...

怎么创建网站平台赚钱/网络营销专业是做什么的

目录 一、方法的概念及使用 1、什么是方法(method) 2、方法定义 3、方法调用的执行过程 4、实参和形参的关系 二、方法重载 1、为什么需要方法重载 2、方法重载概念 3、方法签名 三、递归 1、递归的概念 2、递归执行过程分析 3、递归练习 一、方法的概念及使用 1、…...

wordpress 大神/seo搜索优化 指数

原文链接&#xff1a;http://jalammar.github.io/visual-numpy/创建数组我们可以创建一个NumPy数组(也就是强大的ndarray)&#xff0c;方法是传递一个python列表并使用np.array() 。在本例中&#xff0c;python创建了我们可以在这里看到的数组:通常情况下&#xff0c;我们希望N…...

怎么看一个网站是由哪个公司做的/网站建设 网站制作

转载于:https://www.cnblogs.com/vaon/p/8367190.html...