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等。通过减少时间冗余,帧间预测编码显著提高了视频数据的压缩率,同时保持了视频质量。
帧间预测的核心技术主要包括以下几个方面:
运动估计(Motion Estimation, ME):
- 运动估计是指在参考帧中搜索与当前块最匹配的区域,以确定最佳匹配块的位置。
运动补偿(Motion Compensation, MC):
- 运动补偿使用运动估计得到的运动向量来预测当前块,通过补偿先前图像的抽样点来生成当前图像块的预测值。
宏块(Macroblock, MB)和子宏块(Sub-Macroblock)的树状结构分块:
- H.264 支持多种宏块分割方式,如16x16、16x8、8x16和8x8,以及更细致的子宏块分割,如8x8、8x4、4x8和4x4。
多参考帧预测:
- 特别是在B帧中,可以使用两个方向的参考帧(List0和List1)进行双向预测。
亚像素精度的运动估计:
- 除了整像素精度外,H.264还支持1/2像素和1/4像素的亚像素插值,以提高预测精度。
快速搜索算法:
- 为了减少计算复杂度,使用快速搜索算法来确定最佳匹配块。
运动向量的编码:
- 运动向量的编码通常涉及编码运动向量与预测值的差值(MVD),而不是直接编码运动向量本身。
预测模式的选择:
- H.264定义了多种预测模式,包括直接模式、双向模式、List0和List1模式等。
参考帧管理:
- 管理参考帧以确保解码器能够正确地重建预测图像。
变换/量化编码和熵编码:
- 这些步骤与帧内编码相同或相似,用于进一步压缩预测残差。
帧间预测通过这些技术有效地减少了视频序列中的时间冗余,提高了压缩效率。
openh264 帧间预测编码过程
- 帧间预测过程函数关系图:
- 关键模块说明:
- 通过API 函数
EncodeFrame
完成具体的编码过程,可执行程序封装该函数进行编码;- 通过二维数组g_pWelsSliceCoding[2][2]来完成具体的I 帧、P 帧,以及变化片数和非变化片数编码;
- 在非变化片数帧间编码过程中,在
WelsMdInterMbLoop
函数中循环处理每个宏块;- 在变化片数帧间编码过程中,在
WelsMdInterMbLoopOverDynamicSlice
函数中循环处理每个宏块;pfInterMd
函数指针指向具体的增强层WelsMdInterMbEnhancelayer
或基本层WelsMdInterMb
帧间预测过程;- 在基本层预测过程中,
WelsMdInterSecondaryModesEnc
函数完成二级帧间预测过程编码;- 在增强层预测过程中,
WelsMdSpatialelInterMbIlfmdNoilp
函数完成具体的预测过程编码;
- 帧间预测过程核心函数介绍:
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 编码和解码器,由思科系统开发并维护。它专为实时应用程序如 WebRTC 设计,提供了从基础到高级特性的广泛支持。OpenH264 的编码器支持从 Constrained Baseline Profile 到 5.2 级别,允许任意分辨率的编…...

Linux网络 - HTTP协议
文章目录 前言一、HTTP协议1.urlurl特殊字符 requestrespond 总结 前言 上一章内容我们讲了在应用层制定了我们自己自定义的协议、序列化和反序列化。 协议的制定相对来讲还是比较麻烦的,不过既然应用层的协议制定是必要的,那么肯定已经有许多计算机大佬…...
面试题——Nginx
1.Nginx是什么? 是一个高性能的Web服务器和反向代理服务器,也可以作为静态文件的缓存服务器,也能够进行负载均衡。 2.Nginx的作用? 1.反向代理:将多台服务器代理为一台服务器。客户端不了解底层服务端。 2.负载均衡…...

持续学习的综述: 理论、方法与应用
摘要 为了应对现实世界的动态,智能系统需要在其整个生命周期中增量地获取、更新、积累和利用知识。这种能力被称为持续学习,为人工智能系统自适应发展提供了基础。从一般意义上讲,持续学习明显受到灾难性遗忘的限制,在这种情况下…...
跨域资源共享(CORS)问题与解决方案
跨域资源共享(CORS,Cross-Origin Resource Sharing)是现代web开发中常见且重要的一个概念。它涉及到浏览器的同源策略(Same-Origin Policy),该策略用于防止恶意网站从不同来源窃取数据。然而,在…...

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

不可思议!这款 Python 库竟然能自动生成GUI界面:MagicGUI
目录 什么是MagicGUI? 编辑 MagicGUI的工作原理 安装MagicGUI 创建你的第一个GUI 编辑 其他案例 输入值对话框 大家好,今天我们来聊一聊一个非常有趣且实用的Python库——MagicGUI。这个库可以让你用最少的代码,快速创建图形用户…...

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

离散数学复习
1.关系的介绍和性质 (1)序偶和笛卡尔积 两个元素按照一定的顺序组成的二元组就是序偶,使用尖括号进行表示,尖括号里面的元素一般都是有顺序的; 笛卡尔积就是有两个集合,从第一个集合里面选择一个元素&am…...
华为网络设备高频命令
1.system-view • 用法:在用户视图下执行 system-view 命令。 • 作用:进入系统视图,以便进行配置性的操作。 • 场景:当需要对设备进行系统级的配置时。 2.sysname XXX • 用法:执行 [Huawei]sysname XXX 命令。…...
信友队:南风的收集
C. [202406C]楠枫的收集 文件操作 时间限制: 1000ms 空间限制: 262144KB 输入文件名: 202406C.in 输出文件名: 202406C.out Accepted 100 分 题目描述 一年四季,寒暑交替,楠枫总是会收集每一个季节的树叶,并把它们制作成标本收集起来。当…...
找工作小项目:day16-重构核心库、使用智能指针(3)
day16-重构核心库、使用智能指针(3) 最后将使用这个库的方式进行展示。 1、客户端 在while ((o getopt(argc, argv, optstring)) ! -1)所有的操作都是获取参数的操作,threads 、msgs 和wait 分别指线程数、消息长度以及等待时间。 创建一…...

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

HTML5基础
1 HTML基础概念(难点) WWW(World Wide Web,万维网)是一种建立在 Internet 上的信息资源网络。 WWW 有 3 个基本组成部分,分别是 URL:Universal Resource Locators,统一资源定位器 HT…...
python,ipython 和 jupyter notebook 之间的关系
python,ipython 和 jupyter notebook 之间的关系 文章目录 python,ipython 和 jupyter notebook 之间的关系1. Python2. IPython3. Jupyter Notebook启动 Jupyter Notebook 关系总结 Python、IPython 和 Jupyter Notebook 是相互关联但具有不同功能的工具…...

聊聊DoIP吧(三)-端口号port
DoIP在UDP和TCP建立连接和发送诊断报文的过程中使用的端口定义如下:...

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

针对k8s集群已经加入集群的服务器进行驱逐
例如k8s 已经有很多服务器,现在由于服务器资源过剩,需要剥离一些服务器出来 查找节点名称: kubectl get nodes设置为不可调度: 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道设计模式面试题(二)
上一篇地址:赶紧收藏!2024 年最常见 20道设计模式面试题(一)-CSDN博客 三、解释抽象工厂模式,并给出一个实际应用的例子。 抽象工厂模式是一种创建型设计模式,用于创建一系列相关或依赖对象的接口&#x…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...

C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

多模态大语言模型arxiv论文略读(110)
CoVLA: Comprehensive Vision-Language-Action Dataset for Autonomous Driving ➡️ 论文标题:CoVLA: Comprehensive Vision-Language-Action Dataset for Autonomous Driving ➡️ 论文作者:Hidehisa Arai, Keita Miwa, Kento Sasaki, Yu Yamaguchi, …...

在 Vue 的template中使用 Pug 的完整教程
在 Vue 的template中使用 Pug 的完整教程 引言 什么是 Pug? Pug(原名 Jade)是一种高效的网页模板引擎,通过缩进式语法和简洁的写法减少 HTML 的冗长代码。Pug 省略了尖括号和闭合标签,使用缩进定义结构,…...

SAP学习笔记 - 开发24 - 前端Fiori开发 Filtering(过滤器),Sorting and Grouping(排序和分组)
上一章讲了SAP Fiori开发的表达式绑定,自定义格式化等内容。 SAP学习笔记 - 开发23 - 前端Fiori开发 Expression Binding(表达式绑定),Custom Formatters(自定义格式化)-CSDN博客 本章继续讲SAP Fiori开发…...