H266/VVC 帧内预测中 ISP 技术

news2025/1/12 8:10:39

帧内子划分 ISP

  1. ISP 技术是在 JVET-2002-v3 提案中详细介绍其原理,在 VTM8 中完整展示算法。ISP是线基内预测(LIP)模式的更新版本,它改善了原始方法在编码增益和复杂度之间的权衡,ISP 算法的核心原理就是利用较近的像素点作为参考像素。
    在这里插入图片描述在这里插入图片描述
  2. 帧内子分区(ISP)根据块的大小,将亮度帧内预测块垂直或水平分割成2或4个子分区。例如,ISP的最小块大小是4x8(或8x4)。如果块大小大于4x8(或8x4),那么相应的块被4个子分区分割。
  3. 值得注意的是,M × 128(M ≤ 64)和128 × N(N ≤ 64)的 ISP 块可能会与64 × 64的 VDPU 产生潜在问题。例如,在单树情况下,一个M × 128的CU 包含一个 M x128 的亮度块 TB 和两个M/2 × 64的色度TB。如果CU 使用 ISP,那么亮度TB将被分割成四个M × 32的TB(只有水平分割是可能的),每个块都小于64 × 64。然而,在ISP色度块的当前设计中并没有被分割。因此,两个色度分量的尺寸都会大于32 × 32的块。类似地,使用ISP的128 × N的CU也可能会遇到类似的情况。因此,这两种情况对于64 × 64的 VDPU 来说是个问题。出于这个原因,能够使用ISP的 CU 尺寸被限制在最大64 × 64。图19展示了这两种可能性的例子。所有的子分区都满足至少有16个样本的条件。
    在这里插入图片描述
  4. 在ISP中,不允许 1xN/2xN 子块预测依赖于之前解码的编码块的 1xN/2xN子 块的重建值,这样子块的最小预测宽度就变成了四个样本。例如,一个8xN(N > 4)的编码块,如果使用ISP进行垂直分割编码,将被分割成两个预测区域,每个区域的大小为4xN,并且有四个2xN的变换。此外,一个使用ISP进行垂直分割编码的4xN编码块,将使用完整的4xN块进行预测;四个1xN的变换被使用。尽管允许1xN和2xN的变换尺寸,但断言这些块在4xN区域内的变换可以并行执行。例如,当一个4xN预测区域包含四个1xN变换时,水平方向没有变换;垂直方向的变换可以作为单个4xN变换在垂直方向执行。同样地,当一个4xN预测区域包含两个2xN变换块时,两个2xN块在每个方向(水平和垂直)上的变换操作可以并行进行。因此,处理这些较小的块与处理4x4常规编码的帧内块相比,不会增加延迟。
  5. 对于每个子分区,通过将残差信号加到预测信号上来获得重建样本。这里,残差信号是通过熵解码、逆量化和逆变换等过程生成的。因此,重建样本值可用于生成下一个子分区的预测,每个子分区都会重复处理。此外,要处理的第一个子分区是包含CU左上角样本的子分区,然后继续向下(水平分割)或向右(垂直分割)。因此,用于生成子分区预测信号的参考样本仅位于行的左侧和上方。所有子分区共享相同的帧内模式。
  6. ISP 技术与其他编码工具的交互:
    • 多重参考线(MRL):如果一个块的MRL索引不是0,那么ISP编码模式将被推断为0,因此ISP模式信息不会发送到解码器。
    • 熵编码系数组大小:熵编码子块的大小已经被修改,以便在所有可能的情况下它们都有16个样本,如表3-6所示。请注意,新的大小只影响由ISP产生的块,其中一个维度小于4个样本。在所有其他情况下,系数组保持4x4的尺寸。
      在这里插入图片描述
    • CBF编码:假设至少有一个子分区具有非零的CBF。因此,如果n是子分区的数量,前n-1个子分区产生了零CBF,那么第n个子分区的CBF被推断为1。
    • MPM使用:在ISP模式编码的块中,MPM标志将被推断为1,MPM列表被修改以排除DC模式,并优先考虑ISP水平分割的水平内模式和垂直分割的垂直内模式。
    • 变换大小限制:所有ISP变换,如果长度大于16点,使用DCT-II。
    • PDPC:当CU使用ISP编码模式时,PDPC滤波器不会应用于生成的子分区。
    • MTS标志:如果CU使用ISP编码模式,MTS CU标志将被设置为0,并且不会发送到解码器。因此,编码器不会对每个生成的子分区执行不同可用变换的RD测试。ISP模式的变换选择将根据内模式、处理顺序和使用的块大小固定和选择。因此,不需要信号。例如,让tH和tV分别是为 w×h 子分区选择的水平和垂直变换,其中w是宽度,h是高度。然后根据以下规则选择变换:
      • 如果 w=1或 h=1,则没有水平或垂直变换。
      • 如果 w=2 或 w>32,tH=DCT−II。
      • 如果 h=2 或 h>32,tV=DCT−II。
      • 否则,变换如表3-7所示选择。
        在这里插入图片描述
  7. 在ISP模式下,允许所有67种内模式。如果相应的宽度和高度至少为4个样本,则应用PDPC。此外,内插滤波器选择的条件不再存在,并且在ISP模式下,对于分数位置插值,总是应用Cubic(DCT-IF)滤波器。
  8. 在论文 [ AN INTRA SUBPARTITION CODING MODE FOR VVC ] 中使用 VTM-3.0 官方参考代码中测试 ISP 技术的性能收益如下表:
    在这里插入图片描述
  9. 在 VVenC 编码器中 UnitTools.cpp 文件中canUseISP 函数来判断是否可以使用 ISP 技术。
    在这里插入图片描述
bool CU::canUseISP( const CodingUnit &cu, const ComponentID compID )
{
  const int width     = cu.blocks[compID].width;
  const int height    = cu.blocks[compID].height;
  const int maxTrSize = cu.cs->sps->getMaxTbSize();
  return CU::canUseISP( width, height, maxTrSize );
}

bool CU::canUseISP( const int width, const int height, const int maxTrSize )
{
  bool  notEnoughSamplesToSplit = ( Log2(width) + Log2(height) <= ( MIN_TB_LOG2_SIZEY << 1 ) );
  bool  cuSizeLargerThanMaxTrSize = width > maxTrSize || height > maxTrSize;
  if ( notEnoughSamplesToSplit || cuSizeLargerThanMaxTrSize )
  {
    return false;
  }
  return true;
}
  1. 在 VVenC 编码器中 IntraSearch.cpp 文件中estIntraPredLumaQT 函数中进行 ISP 初始化和遍历模式计算开启 ISP 和不开启 ISP 的代价,选择代价最小预测方式。
    在这里插入图片描述在这里插入图片描述
bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, double bestCost)
{
  CodingStructure       &cs           = *cu.cs;
  const int             width         = partitioner.currArea().lwidth();
  const int             height        = partitioner.currArea().lheight();

  //===== loop over partitions =====

  const TempCtx ctxStart           ( m_CtxCache, m_CABACEstimator->getCtx() );

  // variables for saving fast intra modes scan results across multiple LFNST passes
  double costInterCU = xFindInterCUCost( cu );

  bool validReturn = false;

  //===== determine set of modes to be tested (using prediction signal only) =====
  int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> RdModeList;
  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> HadModeList;
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandCostList;
  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandHadList;

  int numModesForFullRD = g_aucIntraModeNumFast_UseMPM_2D[Log2(width) - MIN_CU_LOG2][Log2(height) - MIN_CU_LOG2];
  if (m_pcEncCfg->m_numIntraModesFullRD > 0)
    numModesForFullRD=m_pcEncCfg->m_numIntraModesFullRD;

#if INTRA_FULL_SEARCH
  numModesForFullRD = numModesAvailable;
#endif
  const SPS& sps = *cu.cs->sps;
  const bool mipAllowed = sps.MIP && cu.lwidth() <= sps.getMaxTbSize() && cu.lheight() <= sps.getMaxTbSize() && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.lumaSize()));
  const int SizeThr     = 8 >> std::max( 0, m_pcEncCfg->m_useFastMIP - 1 );
  const bool testMip    = mipAllowed && ( cu.lwidth() <= ( SizeThr * cu.lheight() ) && cu.lheight() <= ( SizeThr * cu.lwidth() ) ) && ( cu.lwidth() <= MIP_MAX_WIDTH && cu.lheight() <= MIP_MAX_HEIGHT );
  bool testISP = sps.ISP && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize());
  if (testISP)
  {
    int numTotalPartsHor = (int)width >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_VERT_SPLIT));
    int numTotalPartsVer = (int)height >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT));
    m_ispTestedModes[0].init(numTotalPartsHor, numTotalPartsVer, 0);
    // the total number of subpartitions is modified to take into account the cases where LFNST cannot be combined with
    // ISP due to size restrictions
    numTotalPartsHor = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), HOR_INTRA_SUBPARTITIONS) ? numTotalPartsHor : 0;
    numTotalPartsVer = sps.LFNST && CU::canUseLfnstWithISP(cu.Y(), VER_INTRA_SUBPARTITIONS) ? numTotalPartsVer : 0;
    for (int j = 1; j < NUM_LFNST_NUM_PER_SET; j++)
    {
      m_ispTestedModes[j].init(numTotalPartsHor, numTotalPartsVer, 0);
    }
    testISP = m_ispTestedModes[0].numTotalParts[0];
  }
  else
  {
    m_ispTestedModes[0].init(0, 0, 0);
  }

  xEstimateLumaRdModeList(numModesForFullRD, RdModeList, HadModeList, CandCostList, CandHadList, cu, testMip);

  CHECK( (size_t)numModesForFullRD != RdModeList.size(), "Inconsistent state!" );

  // after this point, don't use numModesForFullRD
  if( m_pcEncCfg->m_usePbIntraFast && !cs.slice->isIntra() && RdModeList.size() < numModesAvailable )
  {
    double pbintraRatio = m_pcEncCfg->m_usePbIntraFast == 1 && ( cs.area.lwidth() >= 16 && cs.area.lheight() >= 16 ) ? 1.2 : PBINTRA_RATIO;

    int maxSize = -1;
    ModeInfo bestMipMode;
    int bestMipIdx = -1;
    for( int idx = 0; idx < RdModeList.size(); idx++ )
    {
      if( RdModeList[idx].mipFlg )
      {
        bestMipMode = RdModeList[idx];
        bestMipIdx = idx;
        break;
      }
    }
    const int numHadCand = 3;
    for (int k = numHadCand - 1; k >= 0; k--)
    {
      if (CandHadList.size() < (k + 1) || CandHadList[k] > cs.interHad * pbintraRatio) { maxSize = k; }
    }
    if (maxSize > 0)
    {
      RdModeList.resize(std::min<size_t>(RdModeList.size(), maxSize));
      if( bestMipIdx >= 0 )
      {
        if( RdModeList.size() <= bestMipIdx )
        {
          RdModeList.push_back(bestMipMode);
          m_SortedPelUnitBufs->swap( maxSize, bestMipIdx );
        }
      }
    }
    if (maxSize == 0)
    {
      cs.dist = MAX_DISTORTION;
      cs.interHad = 0;
      return false;
    }
  }

  //===== check modes (using r-d costs) =====
  ModeInfo bestPUMode;

  CodingStructure *csTemp = m_pTempCS;
  CodingStructure *csBest = m_pBestCS;

  csTemp->slice   = csBest->slice   = cs.slice;
  csTemp->picture = csBest->picture = cs.picture;
  csTemp->compactResize( cu );
  csBest->compactResize( cu );
  csTemp->initStructData();
  csBest->initStructData();

  int   bestLfnstIdx  = 0;
  const bool useBDPCM = cs.picture->useBDPCM;
  int   NumBDPCMCand  = (useBDPCM && sps.BDPCM && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType))) ? 2 : 0;
  int   bestbdpcmMode = 0;
  int   bestISP       = 0;
  int   bestMrl       = 0;
  bool  bestMip       = 0;
  int   EndMode       = (int)RdModeList.size();
  bool  useISPlfnst   = testISP && sps.LFNST;
  bool  noLFNST_ts    = false;
  double bestCostIsp[2] = { MAX_DOUBLE, MAX_DOUBLE };
  bool disableMTS = false;
  bool disableLFNST = false;
  bool disableDCT2test = false;
  if (m_pcEncCfg->m_FastIntraTools)
  {
    int speedIntra = 0;
    xSpeedUpIntra(bestCost, EndMode, speedIntra, cu);
    disableMTS = (speedIntra >> 2 ) & 0x1;
    disableLFNST = (speedIntra >> 1) & 0x1;
    disableDCT2test = speedIntra>>3;
    if (disableLFNST)
    {
      noLFNST_ts = true;
      useISPlfnst = false;
    }
    if (speedIntra & 0x1)
    {
      testISP = false;
    }
  }

  for (int mode_cur = 0; mode_cur < EndMode + NumBDPCMCand; mode_cur++)
  {
    int mode = mode_cur;
    if (mode_cur >= EndMode)
    {
      mode = mode_cur - EndMode ? -1 : -2;
      testISP = false;
    }
    // set CU/PU to luma prediction mode
    ModeInfo testMode;
    int noISP = 0;
    int endISP = testISP ? 2 : 0;
    bool noLFNST = false || noLFNST_ts;
    if (mode && useISPlfnst)
    {
      noLFNST |= (bestCostIsp[0] > (bestCostIsp[1] * 1.4));
      if (mode > 2)
      {
        endISP = 0;
        testISP = false;
      }
    }
    if (testISP)
    {
      xSpeedUpISP(1, testISP, mode, noISP, endISP, cu, RdModeList, bestPUMode, bestISP, bestLfnstIdx);
    }
    int startISP = 0;
    if (disableDCT2test && mode && bestISP)
    {
      startISP = endISP ? 1 : 0;
    }
    for (int ispM = startISP; ispM <= endISP; ispM++)
    {
      if (ispM && (ispM == noISP))
      {
        continue;
      }

      if (mode < 0)
      {
        cu.bdpcmM[CH_L] = -mode;
        testMode = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmM[CH_L] == 2 ? VER_IDX : HOR_IDX);
      }
      else
      {
        testMode = RdModeList[mode];
        cu.bdpcmM[CH_L] = 0;
      }

      cu.ispMode = ispM;
      cu.mipFlag = testMode.mipFlg;
      cu.mipTransposedFlag = testMode.mipTrFlg;
      cu.multiRefIdx = testMode.mRefId;
      cu.intraDir[CH_L] = testMode.modeId;
      if (cu.ispMode && xSpeedUpISP(0, testISP, mode, noISP, endISP, cu, RdModeList, bestPUMode, bestISP, 0) )
      {
        continue;
      }
      if (m_pcEncCfg->m_FastIntraTools && (cu.ispMode || sps.LFNST || sps.MTS))
      {
        m_ispTestedModes[0].intraWasTested = true;
      }
      CHECK(cu.mipFlag && cu.multiRefIdx, "Error: combination of MIP and MRL not supported");
      CHECK(cu.multiRefIdx && (cu.intraDir[0] == PLANAR_IDX), "Error: combination of MRL and Planar mode not supported");
      CHECK(cu.ispMode && cu.mipFlag, "Error: combination of ISP and MIP not supported");
      CHECK(cu.ispMode && cu.multiRefIdx, "Error: combination of ISP and MRL not supported");

      // determine residual for partition
      cs.initSubStructure(*csTemp, partitioner.chType, cs.area, true);
      int doISP = (((cu.ispMode == 0) && noLFNST) || (useISPlfnst && mode && cu.ispMode && (bestLfnstIdx == 0)) || disableLFNST) ? -mode : mode;
      xIntraCodingLumaQT(*csTemp, partitioner, m_SortedPelUnitBufs->getBufFromSortedList(mode), bestCost, doISP, disableMTS);

      DTRACE(g_trace_ctx, D_INTRA_COST, "IntraCost T [x=%d,y=%d,w=%d,h=%d] %f (%d,%d,%d,%d,%d,%d) \n", cu.blocks[0].x,
        cu.blocks[0].y, width, height, csTemp->cost, testMode.modeId, testMode.ispMod,
        cu.multiRefIdx, cu.mipFlag, cu.lfnstIdx, cu.mtsFlag);

      if (cu.ispMode && !csTemp->cus[0]->firstTU->cbf[COMP_Y])
      {
        csTemp->cost = MAX_DOUBLE;
        csTemp->costDbOffset = 0;
      }
      if (useISPlfnst)
      {
        int n = (cu.ispMode == 0) ? 0 : 1;
        bestCostIsp[n] = csTemp->cost < bestCostIsp[n] ? csTemp->cost : bestCostIsp[n];
      }

      // check r-d cost
      if (csTemp->cost < csBest->cost)
      {
        validReturn   = true;
        std::swap(csTemp, csBest);
        bestPUMode    = testMode;
        bestLfnstIdx  = csBest->cus[0]->lfnstIdx;
        bestISP       = csBest->cus[0]->ispMode;
        bestMip       = csBest->cus[0]->mipFlag;
        bestMrl       = csBest->cus[0]->multiRefIdx;
        bestbdpcmMode = cu.bdpcmM[CH_L];
        m_ispTestedModes[bestLfnstIdx].bestSplitSoFar = ISPType(bestISP);
        if (csBest->cost < bestCost)
        {
          bestCost = csBest->cost;
        }
        if ((csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] == MTS_SKIP) && ( floorLog2(csBest->getTU(partitioner.chType)->blocks[COMP_Y].area()) >= 6 ))
        {
          noLFNST_ts = 1;
        }
      }

      // reset context models
      m_CABACEstimator->getCtx() = ctxStart;

      csTemp->releaseIntermediateData();

      if (m_pcEncCfg->m_fastLocalDualTreeMode && CU::isConsIntra(cu) && !cu.slice->isIntra() && csBest->cost != MAX_DOUBLE && costInterCU != COST_UNKNOWN && mode >= 0)
      {
        if( (m_pcEncCfg->m_fastLocalDualTreeMode == 2) || (csBest->cost > costInterCU * 1.5))
        {
          //Note: only try one intra mode, which is especially useful to reduce EncT for LDB case (around 4%)
          EndMode = 0;
          break;
        }
      }
    }
  } // Mode loop

  if (m_pcEncCfg->m_FastIntraTools && (sps.ISP|| sps.LFNST || sps.MTS))
  {
    int bestMode = csBest->getTU(partitioner.chType)->mtsIdx[COMP_Y] ? 4 : 0;
    bestMode |= bestLfnstIdx ? 2 : 0;
    bestMode |= bestISP ? 1 : 0;
    m_ispTestedModes[0].bestIntraMode = bestMode;
  }
  cu.ispMode = bestISP;
  if( validReturn )
  {
    cs.useSubStructure( *csBest, partitioner.chType, TREE_D, cu.singleChan( CH_L ), true );
    const ReshapeData& reshapeData = cs.picture->reshapeData;
    if (cs.picHeader->lmcsEnabled && reshapeData.getCTUFlag())
    {
      cs.getRspRecoBuf().copyFrom(csBest->getRspRecoBuf());
    }

    //=== update PU data ====
    cu.lfnstIdx           = bestLfnstIdx;
    cu.mipTransposedFlag  = bestPUMode.mipTrFlg;
    cu.intraDir[CH_L]     = bestPUMode.modeId;
    cu.bdpcmM[CH_L]       = bestbdpcmMode;
    cu.mipFlag            = bestMip;
    cu.multiRefIdx        = bestMrl;
  }
  else
  {
    THROW("fix this");
  }

  csBest->releaseIntermediateData();

  return validReturn;
}

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

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

相关文章

《拉依达的嵌入式\驱动面试宝典》—计算机网络篇(二)

《拉依达的嵌入式\驱动面试宝典》—计算机网络篇(二) 你好,我是拉依达。 感谢所有阅读关注我的同学支持,目前博客累计阅读 27w,关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析(持续更新)-CSDN博客》已经是 Linux驱动 相关内容搜索的推荐首位,感谢大家支持。 《…

【2024年华为OD机试】 (A卷,100分)- 对称美学(Java JS PythonC/C++)

一、问题描述 题目描述 对称就是最大的美学&#xff0c;现有一道关于对称字符串的美学。已知&#xff1a; 第1个字符串&#xff1a;R第2个字符串&#xff1a;BR第3个字符串&#xff1a;RBBR第4个字符串&#xff1a;BRRBRBBR第5个字符串&#xff1a;RBBRBRRBBRRBRBBR 相信你…

c#集成npoi根据excel模板导出excel

NuGet中安装npoi 创建excel模板&#xff0c;替换其中的内容生成新的excel文件。 例子中主要写了这四种情况&#xff1a; 1、替换单个单元格内容&#xff1b; 2、替换横向多个单元格&#xff1b; 3、替换表格&#xff1b; 4、单元格中插入图片&#xff1b; using System.IO; …

【数据库系统概论】第5章 数据库完整性【!触发器】

目录 5.1数据库完整性概述 5.2 实体完整性 5.3 参照完整性 5.4 用户定义的完整性 属性上的约束 1. 列值非空&#xff08;NOT NULL&#xff09; 2. 列值唯一&#xff08;UNIQUE&#xff09; 3. 检查列值是否满足条件&#xff08;CHECK&#xff09; 元组上的约束 5.5 完…

一键部署Netdata系统无需公网IP轻松实现本地服务器的可视化监控

文章目录 前言1.关于Netdata2.本地部署Netdata3.使用Netdata4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定Netdata公网地址 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。…

HBuilderX(uniapp)实现微信小程序获取用户头像、昵称、授权登录、获取用户手机号

前言&#xff1a;微信文档写的零零散散的&#xff0c;网上搜的教程&#xff0c;23年的教程还在教22年改版之前的东西&#xff0c;导致踩坑无数&#xff0c;所以自己写一下文档记录一下&#xff0c;帮助后来者&#xff0c;记录于2024.11.14 一.获取用户头像和昵称 首先阅读微信…

RabbitMQ基础(简单易懂)

什么是RabbitMQ&#xff1f; 它基于AMQP协议&#xff08;Advanced Message Queuing Protocol&#xff09;&#xff0c;一种为应用构建消息队列的标准协议。过程中&#xff0c;它提供了一些重要模块&#xff1a;为消息发送的Producer&#xff08;生产者&#xff09;&#xff0c…

【web靶场】之upload-labs专项训练(基于BUUCTF平台)

前言 该靶场&#xff0c;是通过平台BUUCTF在线评测中的靶场进行的&#xff0c;基于linux搭建的 当然若是想要该靶场&#xff0c;可以采用github上的醒目&#xff0c;点击后面文字即可访问c0ny1/upload-labs: 一个想帮你总结所有类型的上传漏洞的靶场 或者本人分享在网盘中&a…

美摄科技为企业打造专属PC端视频编辑私有化部署方案

美摄科技&#xff0c;作为视频编辑技术的先行者&#xff0c;凭借其在多媒体处理领域的深厚积累&#xff0c;为企业量身打造了PC端视频编辑私有化部署解决方案&#xff0c;旨在帮助企业构建高效、安全、定制化的视频创作平台&#xff0c;赋能企业内容创新&#xff0c;提升品牌影…

Vue3(elementPlus) el-table替换/隐藏行箭头,点击整行展开

element文档链接&#xff1a; https://element-plus.org/zh-CN/component/form.html 一、el-table表格行展开关闭箭头替换成加减号 注&#xff1a;Vue3在样式中修改箭头图标无效&#xff0c;可能我设置不对&#xff0c;欢迎各位来交流指导 转变思路&#xff1a;隐藏箭头&…

【C++入门】详解(中)

目录 &#x1f495;1.函数的重载 &#x1f495;2.引用的定义 &#x1f495;3.引用的一些常见问题 &#x1f495;4.引用——权限的放大/缩小/平移 &#x1f495;5. 不存在的空引用 &#x1f495;6.引用作为函数参数的速度之快&#xff08;代码体现&#xff09; &#x1f4…

【题解】—— LeetCode一周小结53

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结52 30.二叉树中的链表 题目链接&#xff1a;1367. 二叉树中的链…

Vue方法、计算机属性及侦听器

数组变化侦测 假设我们写了一个数组&#xff0c;现在想让该数组中新增一条数据,那么如何去实现呢&#xff1f; <template><h3>数组变化侦听</h3><button click"addListHandler">添加数据</button><ul><li v-for"(item…

TIOBE编程语言排行靠前的编程语言的吉祥物

Python的吉祥物&#xff1a;小蟒蛇 Python语言的吉祥物是一只名叫"Pythonidae"&#xff08;或简称"Py"&#xff09;的小蟒蛇。这个吉祥物由Tobias Kohn设计于2005年&#xff0c;它的形象借鉴了真实的蟒蛇&#xff0c;但加入了一些可爱和友善的特点。小蟒蛇…

Linux (CentOS) 安装 Docker 和 Docker Compose

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

Unity热更新 之 Addressables(2) 本地/远端打包 流程测试

基础篇&#xff1a;Unity热更新 之 Addressables(1) 资源基础加载-CSDN博客 基础方法来源于唐老狮,我也是初学热更这一块&#xff0c;所有不保证步骤完全正确&#xff0c;如有不足还请斧正 目录 0.前提 1.本地打包 1.1.资源放入包 1.2.简化路径名称给出标签(如有需要的话) …

Openstack持久存储-Swift,Cinder,Manila三者之间的区别

总结不易&#xff0c;给个三连吧&#xff01;&#xff01;&#xff01; 补充&#xff1a; 文件共享存储服务Manila 在OpenStack生态系统中&#xff0c;Cinder和Manila分别提供了两种不同类型的存储服务&#xff0c;类似于传统的SAN&#xff08;存储区域网络&#xff09;和NAS&…

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法&#xff0c;以及自动化实时数据采集 mmWave Studio提供的功能完全够用了 不用去纠结用DCA1000低延迟、无GUI传数据 速度最快又保证算力无非就是就是Linux板自己写驱动做串口和UDP 做雷达产品应用也不会采用DCA1000的…

JavaEE之线程池

前面我们了解了多个任务可以通过创建多个线程去处理&#xff0c;达到节约时间的效果&#xff0c;但是每一次的线程创建和销毁也是会消耗计算机资源的&#xff0c;那么我们是否可以将线程进阶一下&#xff0c;让消耗计算机的资源尽可能缩小呢&#xff1f;线程池可以达到此效果&a…

J-LangChain - 复杂智能链流式执行

系列文章索引 J-LangChain 入门 介绍 j-langchain是一个Java版的LangChain开发框架&#xff0c;具有灵活编排和流式执行能力&#xff0c;旨在简化和加速各类大模型应用在Java平台的落地开发。它提供了一组实用的工具和类&#xff0c;使得开发人员能够更轻松地构建类似于LangC…