【论文#码率控制】ADAPTIVE RATE CONTROL FOR H.264

目录

  • 摘要
  • 1.前言
  • 2.基本知识
  • 2.1 蛋鸡悖论
    • 2.2 基本单元的定义
    • 2.3 线性MAD预测模型
  • 3.GOP级码率控制
    • 3.1 总比特数
    • 3.2 初始化量化参数
  • 4.帧级码率控制
    • 4.1 非存储图像的量化参数
    • 4.2 存储图像的目标比特
  • 5.基本单元级码率控制
  • 6.实验结果
  • 7.结论

《ADAPTIVE RATE CONTROL FOR H.264》
Author: Z.G. Li; F. Pan; K.P. Lim; X. Lin; S. Rahardja
Published in: 2004 International Conference on Image Processing, 2004. ICIP '04.
Date of Conference: 24-27 October 2004
Date Added to IEEE Xplore: 18 April 2005
Print ISBN:0-7803-8554-3
Print ISSN: 1522-4880
DOI: 10.1109/ICIP.2004.1419405
Publisher: IEEE
Conference Location: Singapore

摘要

本文提出了一种针对H.264的码率控制方案,通过引入基本单元和线性预测模型的概念。基本单元可以是宏块(MB)、切片或帧。它可以用于在整体编码效率和比特波动之间取得平衡。线性模型用于解决H.264码率控制中存在的“先有鸡还是先有蛋”的困境。本文研究了恒定比特率(CBR)和可变比特率(VBR)两种情况。我们的方案已被H.264采纳

1.前言

码率控制用于根据指定的比特率和当前帧的统计信息(如每个宏块(MB)的MAD和头部比特数)来计算当前帧的量化参数。H.264的码率控制比MPEG-2和TMN 8更复杂,因为在MPEG-2和TMN 8中,当前帧的统计信息是可用的,而在H.264的码率控制中则不可用[1, 2]。这是因为在H.264中,量化参数不仅涉及码率控制,还涉及率失真优化(RDO),而在MPEG-2、MPEG-4和H.263中,量化参数仅涉及码率控制。当在H.264中实现码率控制时,存在一个典型的“蛋鸡悖论”的困境:为了对一个宏块执行RDO,首先需要使用当前帧的统计信息来确定该宏块的量化参数。然而,当前帧的统计信息只有在执行RDO之后才可用。

一种直观的方法是通过前一帧中对应位置的宏块(MB)的统计信息来预测当前帧中每个宏块的统计信息。然而,这种方法在宏块级别存在一些问题。例如,假设当前帧中的一个宏块是I宏块(Intra-MB),而前一帧中对应位置的宏块是P宏块(Inter-MB)。为了解决这个问题,我们引入了“基本单元”的概念,基本单元可以是宏块(MB)、切片或帧。同一基本单元中的所有宏块共享一个共同的量化参数。基本单元的选择取决于编码图片缓冲区(CPB)的大小。然后,通过引入线性模型来预测当前存储图片中剩余基本单元的MAD值,利用前一存储图片中对应位置的基本单元的实际MAD值,提出了一个自适应基本单元层的码率控制方案,用于H.264。这解决了上述的“先有鸡还是先有蛋”的困境。通过线性模型和基本单元的概念,我们的方案详细描述如下:利用流体流量模型和线性跟踪理论,结合帧率、当前缓冲区占用、目标缓冲区水平和可用信道带宽,计算当前帧的目标比特数。目标比特数进一步由考虑假设参考解码器(HRD)得出的两个值进行限制。当前帧的剩余比特数根据预测的MAD值分配给剩余的基本单元。使用二次率失真(R-D)模型计算相应的量化参数,然后用于对当前基本单元中的每个宏块执行RDO。与使用固定量化参数的H.264编码器相比,我们的方案可以将平均PSNR提高多达0.78dB。在正常测试条件下,对于所有H.264测试序列,改进的平均PSNR为0.43dB。我们的方案已被H.264采纳。

PS:
(1) 蛋鸡悖论问题,为了执行RDO,需要统计信息确定量化参数,但统计信息只有在执行一遍RDO之后才可用
(2) 基本单元可以是宏块,slice或者是frame,同一个基本单元中的所有宏块使用同一个量化参数
(3) 引入线性模型来预测当前图片中剩余基本单元的MAD值,依据是前一帧图片对应位置的基本单元实际MAD值
(4) 目标比特数由HRD限制,当前帧剩余比特数由预测MAD值分配给剩余的基本单元
(5) 相对于CQP模式,性能增益为0.78dB;相对于常规环境,增益为0.43dB

2.基本知识

2.1 蛋鸡悖论

H.264码率控制相关的宏块(MB)编码过程如下[31]:当前帧的统计信息 → 码率控制 → 量化参数 → RDO → 当前帧的统计信息 → 熵编码。

显然,在实施码率控制时存在一个“先有鸡还是先有蛋”的困境。正因为如此,H.264的码率控制比TM 5、Q2和TMN 8更困难。为了研究H.264的码率控制,我们需要找到一种方法来估计当前帧的统计信息。除此之外,我们还需要确定共享一个量化参数的连续宏块的数量。

2.2 基本单元的定义

假设一帧由 N m b p i c N_{mbpic} Nmbpic 个宏块(MBs)组成。定义一个基本单元为一组连续的宏块,其中包含 N m b u n i t N_{mbunit} Nmbunit个宏块, N m b u n i t N_{mbunit} Nmbunit N m b p i c N_{mbpic} Nmbpic的一个部分[14]。用 N u n i t N_{unit} Nunit表示一帧中基本单元的总数,计算公式为
N u n i t s = N m b p i c / N m b u n i t N_{units}=N_{mbpic}/N_{mbunit} Nunits=Nmbpic/Nmbunit
PS:
(1) 类似于HEVC标准中量化组(quantization group,QG)
(2) 这里描述的基本单元对码率控制的功能,类似于x264中的行级码控,但x264中每个mb的qp可以不同,使用每一行的平均qp来控制

2.3 线性MAD预测模型

假设第j幅图像是一个存储的图像,且两个存储图像之间连续的非存储图像的数量为L。提出了以下线性模型(1)来解决“先有鸡还是先有蛋”的困境[14]。

σ ~ l , i ( j ) = a 1 ∗ σ l , i ( j − L + 1 ) + a 2 ( 1 ) \tilde{\sigma}_{l, i}(j)=a_1 * \sigma_{l, i}(j - L + 1) + a_2 (1) σ~l,i(j)=a1σl,i(jL+1)+a2(1)

其中 σ ~ l , i ( j ) \tilde{\sigma}_{l, i}(j) σ~l,i(j) 是第i个GOP中当前存储图像的第l个基本单元的预测MAD值。 σ l , i ( j − L + 1 ) \sigma_{l, i}(j - L + 1) σl,i(jL+1)是前一个存储图像的第i个基本单元的实际MAD值。 a 1 a_1 a1 a 2 a_2 a2是预测模型的两个系数。初始值 a 1 a_1 a1设为1, a 2 a_2 a2设为0。它们在编码每个基本单元后进行更新。

注释 1: 应该指出, σ ~ l , i ( j ) \tilde{\sigma}_{l, i}(j) σ~l,i(j) 是预测的参考值。参考值有许多其他选择。例如,可以在执行RDO之前,对当前图像中的所有宏块(MBs)进行16×16基于的运动估计和运动补偿。我们也可以使用前一帧中最可能的模式进行运动估计和补偿,以获得粗略的信息。所得的MAD也可以用作参考值。为了简化,我们选择\sigma_{l, i}(j - L + 1) 作为参考值。头部比特数也可以通过这种方式获得。同样,预测模型也有许多种,为了简化,我们选择了线性模型。

PS:
(1) 存储图像表示Intra帧、P帧这样会被存储在内存中,用于参考的帧;而B帧这样不会被用于参考的帧称之为非存储图像
(2) 将基本单元假设为mb易于理解,当前mb的MAD值与参考mb的MAD值用线性关系来描述

3.GOP级码率控制

在这个层级,计算分配给每个GOP的总比特数,并设置每个GOP的初始量化参数。

3.1 总比特数

分配给第i个GOP的初始比特数(第一个帧,即IDR帧)按如下方式计算
B i ( 1 ) = R i ( 1 ) f N i + B i − 1 ( N i − 1 ) ( 2 ) B_{i}(1)=\frac{R_{i}(1)}{f}N_{i} + B_{i-1}(N_{i-1}) (2) Bi(1)=fRi(1)Ni+Bi1(Ni1)(2)
其中 R i ( j ) R_{i}(j) Ri(j) 是可用的信道带宽,可以是恒定的或时变的, N i − 1 N_{i-1} Ni1表示第(i−1)个GOP中的总帧数,f 是预定义的帧率,由于信道带宽可能随时改变, B i B_{i} Bi的更新方式为
B i ( j ) = B i ( j − 1 ) − b i ( j − 1 ) + R i ( j ) − R i ( j − 1 ) f ( N i − j + 1 ) ; j = 2 , 3 , . . . , N i B_i(j)=B_{i}(j-1)-b_{i}(j-1)+\frac{R_{i}(j)-R_{i}(j-1)}{f}(N_{i}-j+1); j=2,3,...,N_{i} Bi(j)=Bi(j1)bi(j1)+fRi(j)Ri(j1)(Nij+1);j=2,3,...,Ni
其中, b i ( j − 1 ) b_i(j-1) bi(j1)表示第i个GOP当中的第j帧实际编码比特

PS:
(1) 针对于公式(2),假设i=1,即第一个GOP,有 B 1 ( 1 ) = R 1 ( 1 ) f N 1 B_{1}(1)=\frac{R_{1}(1)}{f}N_{1} B1(1)=fR1(1)N1,其中 R 1 ( 1 ) f \frac{R_{1}(1)}{f} fR1(1)表示单帧消耗比特数, N 1 N_{1} N1表示GOP一共有多少帧,二者的乘积表示GOP1的初始比特数。因此, B 1 ( 1 ) B_{1}(1) B1(1)表示GOP1总共需要分配多少比特
(2) 针对于 B i B_{i} Bi的更新方式,假设i=1,j=2,即GOP1的第二帧,有 B 1 ( 2 ) = B 1 ( 1 ) − b 1 ( 1 ) + R 1 ( 2 ) − R 1 ( 1 ) f ( N 1 − 1 ) B_{1}(2)=B_{1}(1)-b_{1}(1)+\frac{R_{1}(2)-R_{1}(1)}{f}(N_{1}-1) B1(2)=B1(1)b1(1)+fR1(2)R1(1)(N11),将前面计算的 B 1 ( 1 ) B_{1}(1) B1(1)带入展开,得到 B 1 ( 2 ) = R 1 ( 1 ) f − b 1 ( 1 ) + R 1 ( 2 ) f ( N 1 − 1 ) B_{1}(2)=\frac{R_{1}(1)}{f}-b_{1}(1)+\frac{R_{1}(2)}{f}(N_{1}-1) B1(2)=fR1(1)b1(1)+fR1(2)(N11),其中 R 1 ( 1 ) f − b 1 ( 1 ) \frac{R_{1}(1)}{f}-b_{1}(1) fR1(1)b1(1)表示预期第一帧编码比特数减去实际比特数, R 1 ( 2 ) f ( N 1 − 1 ) \frac{R_{1}(2)}{f}(N_{1}-1) fR1(2)(N11)表示按照当前带宽进行计算,当前GOP的后续所有帧的预期编码比特数。因此, B 1 ( 2 ) B_{1}(2) B1(2)表示的是GOP1,从第二帧开始计算一直到GOP1结束的所有帧比特数,后续的计算如 B 1 ( 3 ) B_{1}(3) B1(3) B 1 ( 4 ) B_{1}(4) B1(4)类似
(3) 针对于公式(2),假设i=2,即GOP2,有 B 2 ( 1 ) = R 2 ( 1 ) f N 2 + B 1 ( N 1 ) B_{2}(1)=\frac{R_{2}(1)}{f}N_{2}+B_{1}(N_{1}) B2(1)=fR2(1)N2+B1(N1)。根据前面的理解, B 1 ( N 1 ) B_{1}(N_{1}) B1(N1)表示的是GOP1,从第 N 1 N_{1} N1帧开始计算一直到第一个GOP结束的所有帧的比特数,而GOP1只有 N 1 N_{1} N1帧,所以这里的 B 1 ( N 1 ) B_{1}(N_{1}) B1(N1)可以理解为第一个GOP当中预期的编码比特数与实际编码比特数的差异。 R 2 ( 1 ) f N 2 \frac{R_{2}(1)}{f}N_{2} fR2(1)N2表示的是以当前带宽计算,帧数为 N 2 N_{2} N2总共需要消耗的比特数。因此, B 2 ( 1 ) B_{2}(1) B2(1)表示的是在GOP1实际编码情况的基础之上,GOP2预期使用多少比特
(4) B i − 1 ( N i − 1 ) B_{i-1}(N_{i-1}) Bi1(Ni1)也被称为虚拟缓冲区(Virtual Buffer),描述了预期编码比特与实际编码比特的差异程度,并以此来调整码率控制。虚拟缓冲区在x264中就是VBV,实现细节上有出入

3.2 初始化量化参数

在本文中,第i个GOP中的初始量化参数 Q P i ( 1 ) QP_{i}(1) QPi(1)是基于可用信道带宽和GOP长度预定义的。IDR图像和GOP的第一个存储图像由 Q P i ( 1 ) QP_{i}(1) QPi(1)编码,其他的 Q P i ( 1 ) QP_{i}(1) QPi(1)的计算方式为
Q P i ( 1 ) = m a x { m i n { S u m P Q P ( i − 1 ) N p ( i − 1 ) − m i n { 2 , N i − 1 15 } , Q P i − 1 ( 1 ) + 2 } , Q P i − 1 ( 1 ) − 2 } QP_{i}(1) =max\{min\{\frac{Sum_{PQP}(i-1)}{N_p(i-1)} - min\{2, \frac{N_{i-1}}{15}\}, QP_{i-1}(1)+2\}, QP_{i-1}(1)-2\} QPi(1)=max{min{Np(i1)SumPQP(i1)min{2,15Ni1},QPi1(1)+2},QPi1(1)2}
其中 N p ( i − 1 ) N_{p}(i-1) Np(i1)是第(i−1) 个GOP中存储图像的总数, S u m P Q P ( i − 1 ) Sum_{PQP}(i-1) SumPQP(i1)是第(i−1) 个GOP中所有存储图像的量化参数之和。 Q P i ( 1 ) QP_{i}(1) QPi(1)进一步通过以下方式进行调整:
Q P i ( 1 ) = Q P i ( 1 ) − 1 ; i f Q P i ( 1 ) > Q P i − 1 ( N i − 1 − L ) − 2 QP_{i}(1)=QP_{i}(1)-1; if QP_{i}(1) > QP_{i-1}(N_{i-1}-L)-2 QPi(1)=QPi(1)1;ifQPi(1)>QPi1(Ni1L)2
其中 Q P i − 1 ( N i − 1 − L ) QP_{i-1}(N_{i-1}-L) QPi1(Ni1L)是第(i−1) 个GOP中最后一个存储图像的量化参数。显然, Q P i ( 1 ) QP_{i}(1) QPi(1)既适应于GOP的长度,也适应于可用的信道带宽

PS:
(1) 对于IDR帧和第一个P帧,根据bpp的大小确定qp,bpp的计算方式为 b p p = ( b i t r a t e / f r a m e r a t e ) ∗ N p i x e l bpp=(bitrate / framerate) * N_{pixel} bpp=(bitrate/framerate)Npixel,即每个像素平均使用的比特数,依据bpp确定qp的方式如下
q p = { 35 b p p ≤ L 1 25 b p p ≤ L 2 20 b p p ≤ L 3 10 o t h e r w i s e qp=\left\{ \begin{array}{rcl} 35 & & {bpp \leq L1} \\ 25 & & {bpp \leq L2} \\ 20 & & {bpp \leq L3} \\ 10 & & {otherwise} \end{array} \right. qp= 35252010bppL1bppL2bppL3otherwise
其中,L1,L2和L3由视频的宽度计算。对于QCIF视频(176x144)推荐L1 = 0.1,L2 = 0.3,L3 = 0.6;对于CIF视频(352x288)推荐L1 = 0.2,L2 = 0.6,L3 = 1.2;其他情况L1 = 0.6,L2 = 1.4,L3 = 2.4 (参考H264编码-码率控制原理以及JM代码分析)
(2) 其他GOP中初始QP的计算方式可以拆分来理解。
  (a) m i n { 2 , N i − 1 15 } min\{2, \frac{N_{i-1}}{15}\} min{2,15Ni1}表示一个基于GOP内帧数量的调控因子,如果帧数量大于30,则调控因子为2,否则为 N i − 1 15 \frac{N_{i-1}}{15} 15Ni1
  (b) m i n { S u m P Q P ( i − 1 ) N p ( i − 1 ) − m i n { 2 , N i − 1 15 } , Q P i − 1 ( 1 ) + 2 } min\{\frac{Sum_{PQP}(i-1)}{N_{p}(i-1)}-min\{2, \frac{N_{i-1}}{15}\},QP_{i-1}(1)+2\} min{Np(i1)SumPQP(i1)min{2,15Ni1},QPi1(1)+2},其中的 S u m P Q P ( i − 1 ) N p ( i − 1 ) \frac{Sum_{PQP}(i-1)}{N_{p}(i-1)} Np(i1)SumPQP(i1)表示前一个GOP中PQP的平均值。除去调控因子的考虑,这里表示的含义是,前一个GOP中PQP的均值和前一个GOP的初始QP,取二者中小的一个
  (c) m a x { X , Q P i − 1 + 2 } max\{X, QP_{i-1}+2\} max{X,QPi1+2},其中X表示(b)中计算的结果
  (d) 综上所述,其他GOP中初始QP的计算方式将前一个GOP的初始QP和平均实际编码QP进行对比,增加一些调控因子,确定初始QP。这里更像是一个加上调控因子的clip3操作
(3) 如果经过上面的计算之后,当前GOP初始QP值大于前一个GOP最后一个P帧QP - 2,再将当前GOP初始QP减小1,进行微调

4.帧级码率控制

在这一层,计算了非存储图像的量化参数和存储图像的目标比特。

4.1 非存储图像的量化参数

非存储图片的量化参数通过线性插值方法得到,如下所示:

假设第j帧和(j+L+ 1)帧是存储的图片,相邻的两个存储图片 Q P i ( j ) QP_{i}(j) QPi(j) Q P i ( 1 ) QP_{i}(1) QPi(1)的量化参数分别为。根据以下两种情况给出第k (1<= k <= L)张非存储图片的量化参数:

(1) 情况1 当L=1 时,两个存储图像之间只有一幅非存储图像。量化参数由以下公式计算:
Q P i ( j + 1 ) = { Q P i ( j ) + Q P i ( j + 2 ) + 2 2 Q P i ( j ) ≠ Q P i ( j + 2 ) Q P i ( j ) + 2 O t h e r w i s e QP_{i}(j+1)=\left\{ \begin{array}{rcl} \frac{QP_{i}(j) + QP_{i}(j+2)+2}{2} & & {QP_{i}(j) \neq QP_{i}(j+2)}\\ QP_{i}(j)+2 & & {Otherwise}\\ \end{array} \right. QPi(j+1)={2QPi(j)+QPi(j+2)+2QPi(j)+2QPi(j)=QPi(j+2)Otherwise

(2) 情况2 当L>1 时,两个存储图像之间有多幅非存储图像。量化参数由以下公式计算:
Q P i ( j + k ) = Q P i ( j ) + α + m a x { − 2 ( k − 1 ) , m i n { ( Q P i ( j + L + 1 ) − Q P i ( j ) ) ( k − 1 ) L − 1 , 2 ( k − 1 ) } } QP_{i}(j+k)=QP_{i}(j)+\alpha+max\{-2(k-1), \\ min\{\frac{(QP_{i}(j+L+1)-QP_{i}(j))(k-1)}{L-1}, 2(k-1)\}\} QPi(j+k)=QPi(j)+α+max{2(k1),min{L1(QPi(j+L+1)QPi(j))(k1),2(k1)}}
其中 α \alpha α是第一个非存储图像的量化参数与 Q P i ( j ) QP_{i}(j) QPi(j) 之间的差值,计算公式为
α = { − 3 Q P i ( j + L + 1 ) − Q P i ( j ) ≤ − 2 L − 3 − 2 Q P i ( j + L + 1 ) − Q P i ( j ) = − 2 L − 2 − 1 Q P i ( j + L + 1 ) − Q P i ( j ) = − 2 L − 1 0 Q P i ( j + L + 1 ) − Q P i ( j ) = − 2 L 1 Q P i ( j + L + 1 ) − Q P i ( j ) = − 2 L + 1 2 O t h e r w i s e \alpha=\left\{ \begin{array}{rcl} -3 & & {QP_{i}(j+L+1) - QP_{i}(j) \leq -2L-3}\\ -2 & & {QP_{i}(j+L+1) - QP_{i}(j) = -2L-2}\\ -1 & & {QP_{i}(j+L+1) - QP_{i}(j) = -2L-1}\\ 0 & & {QP_{i}(j+L+1) - QP_{i}(j) = -2L}\\ 1 & & {QP_{i}(j+L+1) - QP_{i}(j) = -2L+1}\\ 2 & & {Otherwise}\\ \end{array} \right. α= 321012QPi(j+L+1)QPi(j)2L3QPi(j+L+1)QPi(j)=2L2QPi(j+L+1)QPi(j)=2L1QPi(j+L+1)QPi(j)=2LQPi(j+L+1)QPi(j)=2L+1Otherwise

PS:
(1) 非存储图像通常指的是B帧这种不会被其他帧用于参考的图像
(2) 如果L=1,假设当前编码序列为 … P B P …,直接取两个P帧QP的均值
(3) 如果L>1,假设当前编码序列为 … P B B B P …,将计算公式分解
 (a) m i n { ( Q P i ( j + L + 1 ) − Q P i ( j ) ) ( k − 1 ) L − 1 , 2 ( k − 1 ) } min\{\frac{(QP_{i}(j+L+1)-QP_{i}(j))(k-1)}{L-1}, 2(k-1)\} min{L1(QPi(j+L+1)QPi(j))(k1),2(k1)}中的 ( Q P i ( j + L + 1 ) − Q P i ( j ) ) ( k − 1 ) L − 1 \frac{(QP_{i}(j+L+1)-QP_{i}(j))(k-1)}{L-1} L1(QPi(j+L+1)QPi(j))(k1)表示第k个B帧,以第j个P帧和第j+L+1个P帧的距离为权重计算的QP调整因子
 (b) m a x { − 2 ( k − 1 ) , X } max\{-2(k-1), X\} max{2(k1),X},其中X表示(a)中计算的结果。(a)和(b)中的步骤是对QP调整权重因子进行clip操作
 (c) 第k个B帧的QP,以第j个P帧的QP作为基础( Q P i ( j ) QP_{i}(j) QPi(j)),加上偏移量( α \alpha α和QP调整因子)获得
 (d) α \alpha α的数值与两个P帧之间的距离有关,经验性参数

4.2 存储图像的目标比特

分配给当前存储图像的比特数应根据当前缓冲区占用情况和图像复杂度进行调整,如下所示:

(1) 步骤1 为当前GOP中的每个存储图像预定义一个目标缓冲区水平。
假设第j幅图像是一个存储图像。该图像的目标缓冲区水平由以下方式确定
S i ( j ) = S i ( j − L − 1 ) − S i ( 2 ) − V s 8 N p ( i ) − 1 + W ‾ p , i ( j − L − 1 ) ( L + 1 ) R i ( j ) f ( W ‾ p , i ( j − L − 1 ) + W ‾ b , i ( j − 1 ) L ) − R i ( j ) f S_{i}(j)=S_{i}(j-L-1)-\frac{S_i(2)-\frac{V_s}{8}}{N_{p}(i)-1}+\\ \frac{\overline{W}_{p,i}(j-L-1)(L+1)R_{i}(j)}{f(\overline{W}_{p,i}(j-L-1)+\overline{W}_{b,i}(j-1)L)}-\frac{R_{i}(j)}{f} Si(j)=Si(jL1)Np(i)1Si(2)8Vs+f(Wp,i(jL1)+Wb,i(j1)L)Wp,i(jL1)(L+1)Ri(j)fRi(j)

其中 S i ( 2 ) S_{i}(2) Si(2)在编码第i个GOP中的第一个存储图像 (即IDR帧) 后重置为 V i ( 2 ) V_{i}(2) Vi(2) V s V_s Vs 是缓冲区大小, W ‾ p , i ( j − L − 1 ) \overline{W}_{p,i}(j-L-1) Wp,i(jL1) 是已编码存储图像的平均复杂度权重 (涵盖过去所有可用于计算的帧集合而非单帧) W ‾ b , i ( j − 1 ) \overline{W}_{b,i}(j-1) Wb,i(j1)是已编码非存储图像的复杂度权重[4]。

PS:
(1) 存储图像通常指的是Intra帧以及P帧,因为它们会被用于参考,所以会存储在内存中
(2) 假设当前编码序列为 … P B B B P B B B P …,其中第一个P帧的索引为j-L-1,第二个P帧的索引为j,第三个P帧的索引为j+l+1。在步骤1中,为当前存储图像计算一个缓冲区,将计算的公式进行拆分
  (a) S i ( j ) S_{i}(j) Si(j)表示当前P帧在编码之后的目标缓冲区的比特数
  (b) S i ( j − L − 1 ) S_{i}(j-L-1) Si(jL1)表示前一个P帧在编码之后的目标缓冲区的比特数
  (c) S i ( 2 ) − V s 8 N p ( i ) − 1 \frac{S_i(2)-\frac{V_s}{8}}{N_{p}(i)-1} Np(i)1Si(2)8Vs中的 S i ( 2 ) S_{i}(2) Si(2)可以改写成 V i ( 2 ) V_{i}(2) Vi(2),表示第一个存储图像(通常是IDR帧)编码之后buffer中的实际比特数。分子部分表示编码当前帧之后,buffer中的比特数,buffer的实际比特数减去1/8,这是因为在计算复杂度时,当前帧的权重系数为1/8,前面一系列帧的平均复杂度的权重系数为7/8。随后,除以当前GOP中P帧数量减去1。因此,(c)表示了编码当前帧之后实际比特数的多少,或者理解为水池出水量。
  (d) W ‾ p , i ( j − L − 1 ) ( L + 1 ) R i ( j ) f ( W ‾ p , i ( j − L − 1 ) + W ‾ b , i ( j − 1 ) L ) − R i ( j ) f \frac{\overline{W}_{p,i}(j-L-1)(L+1)R_{i}(j)}{f(\overline{W}_{p,i}(j-L-1)+\overline{W}_{b,i}(j-1)L)}-\frac{R_{i}(j)}{f} f(Wp,i(jL1)+Wb,i(j1)L)Wp,i(jL1)(L+1)Ri(j)fRi(j)包含了B帧对当前P帧的影响,将公式中的 W ‾ p , i ( j − L − 1 ) \overline{W}_{p,i}(j-L-1) Wp,i(jL1) W ‾ b , i ( j − L − 1 ) \overline{W}_{b,i}(j-L-1) Wb,i(jL1)简记为 W p W_{p} Wp W b W_{b} Wb,公式变形为 ( W p ( L + 1 ) W p + W b L − 1 ) ∗ R i ( j ) f (\frac{W_{p}(L+1)}{W_{p}+W_{b}L}-1) * \frac{R_{i}(j)}{f} (Wp+WbLWp(L+1)1)fRi(j)。变形后的公式可以理解为,前一个P帧和前一个B帧分别赋予一个权重,对当前target buffer进行调控,这个权重由距离决定。在变式中,分子中的权重为L+1,表明仅考虑前一个P帧的复杂度对当前P帧的影响;在分母中,P帧复杂度权重为1,B帧复杂度为L,强调了更接近当前帧的B帧的复杂度。如果 W p W_p Wp大于 W b W_b Wb,则(d)这一项大于0,此时前一个P帧对应的平均复杂度偏高,表明target buffer应该增大一点,以适应较高的复杂度;反之,如果B帧对应的平均复杂度偏高,表明P帧的影响程度较小,target buffer应该减小一点。从这里来看,这个公式中主要的影响因子还是前一个P帧。另外,如果编码序列中没有B帧,则没有(d)这一项

(2) 步骤2 计算当前存储图像的目标比特数。
第i个GOP中的第j幅存储图像的目标比特数根据目标缓冲区水平、帧率、可用信道带宽和实际缓冲区占用情况确定,如下所示:
T ~ i ( j ) = R i ( j ) f + γ ( S i ( j ) − V i ( j ) ) \widetilde{T}_{i}(j)=\frac{R_{i}(j)}{f}+\gamma(S_{i}(j)-V_{i}(j)) T i(j)=fRi(j)+γ(Si(j)Vi(j))

其中 V i ( j ) V_{i}(j) Vi(j)是编码第i个GOP中的第(j−1) 幅存储图像后的实际缓冲区占用情况, γ \gamma γ是一个常数,当没有非存储图像时其典型值为0.5,否则为0.25。

同时,在计算目标比特时,还应考虑剩余比特的数量
T ^ i ( j ) = W p , i ( j − L − 1 ) B i ( j ) W p , i ( j − L − 1 ) N p , r + W b , i ( j − 1 ) N b , r \hat{T}_{i}(j)=\frac{W_{p,i}(j-L-1)B_{i}(j)}{W_{p,i}(j-L-1)N_{p,r}+W_{b,i}(j-1)N_{b,r}} T^i(j)=Wp,i(jL1)Np,r+Wb,i(j1)Nb,rWp,i(jL1)Bi(j)

其中 N p , r N_{p,r} Np,r N b , r N_{b,r} Nb,r分别是剩余存储图像和剩余非存储图像的数量。

目标比特是 T ~ i ( j ) \widetilde{T}_{i}(j) T i(j) T ~ i ( j ) \widetilde{T}_{i}(j) T i(j)的加权组合,如下所示
T i ( j ) = β T ^ i ( j ) + ( 1 − β ) T ~ i ( j ) ( 3 ) T_{i}(j)=\beta\hat{T}_{i}(j)+(1-\beta)\widetilde{T}_{i}(j) (3) Ti(j)=βT^i(j)+(1β)T i(j)(3)

其中p是一个常数,当没有非存储图像时其典型值为0.5,否则为0.9。从公式(3)可以看出,通过选择较小的p可以实现严格的缓冲区节。

为了保持编码帧的质量,目标比特数 T i ( j ) T_i(j) Ti(j) 被限制在:
T i ( j ) = m a x { T i ( j ) , m h r d , i ( j − L − 1 ) + R i ( j ) 4 f } ( 4 ) T_{i}(j)=max\{T_{i}(j), m_{hrd,i}(j-L-1)+\frac{R_{i}(j)}{4f}\}(4) Ti(j)=max{Ti(j),mhrd,i(jL1)+4fRi(j)}(4)
其中 m h r d , i ( j − L − 1 ) m_{hrd,i}(j-L-1) mhrd,i(jL1)是用于前一个存储图像的头部和运动矢量的位数。

为了符合HRD(假设参考解码器)的要求,目标比特数进一步被限制为:
T i ( j ) = m i n { m a x { Z i ( j ) , T i ( j ) , U i ( j ) } } ( 5 ) T_{i}(j)=min\{max\{Z_{i}(j), T_{i}(j), U_{i}(j)\}\}(5) Ti(j)=min{max{Zi(j),Ti(j),Ui(j)}}(5)
其中 Z i ( j ) Z_i(j) Zi(j) U i ( j ) U_i(j) Ui(j) 是根据HRD(假设参考解码器)的要求推导出来的[3]

PS:
(1) 在步骤2中,实现的功能是,基于前面的目标缓冲区大小来调整目标比特数
(2) 计算目标比特数时,分为两种情况考虑
  (a) 基于目标缓冲区水平、帧率、可用信道带宽和实际缓冲区占用情况确定,将公式拆解
   (a1) R i ( j ) f \frac{R_{i}(j)}{f} fRi(j)表示预期编码比特数,由信道带宽和帧率决定
   (a2) γ ( S i ( j ) − V i ( j ) ) \gamma(S_{i}(j)-V_{i}(j)) γ(Si(j)Vi(j))表示目标缓冲区大小和实际缓冲区大小的差异
   (a3) 结合(a1)和(a2),这种情况下的目标比特数为预期编码比特数加上缓冲区差异值的调整
  (b) 基于剩余比特的数量确定
   (b1) 将公式中的 W p , i ( j − L − 1 ) W_{p,i}(j-L-1) Wp,i(jL1) W b , i ( j − 1 ) W_{b,i}(j-1) Wb,i(j1) W p W_{p} Wp W b W_{b} Wb代替,可以改写为 T ^ i ( j ) = W p , i B i ( j ) W p , i N p , r + W b , i N b , r \hat{T}_{i}(j)=\frac{W_{p,i}B_{i}(j)}{W_{p,i}N_{p,r}+W_{b,i}N_{b,r}} T^i(j)=Wp,iNp,r+Wb,iNb,rWp,iBi(j),其中 B i ( j ) B_{i}(j) Bi(j)为剩余比特数,这里表示的含义是当前P帧的目标比特,等于P帧累积复杂度,除以帧类型及对应复杂度乘积。如果没有B帧,则当前公式变形为 B i ( j ) ∗ 1 N p , r B_{i}(j) * \frac{1}{N_{p,r}} Bi(j)Np,r1,即当前P帧的目标比特,等于剩余比特数除以剩余P帧的数量

5.基本单元级码率控制

基本单元级别的码率控制选择存储图像中所有基本单元的量化参数值,使得生成的比特数总和接近帧的目标比特数 T i ( j ) T_i(j) Ti(j)。以下是对该方法的逐步描述:

(1) 步骤1: 使用前一个存储图像中对应位置的基本单元的实际MAD值,通过模型(1)预测当前存储图像中剩余基本单元的MAD值

(2) 步骤2: 计算当前基本单元的纹理比特数 b ^ l , i ( j ) \hat{b}_{l,i}(j) b^l,i(j)。此步骤由以下三个子步骤组成:
 (2.1) 步骤2.1 计算当前基本单元的目标比特数。设 T r , i ( j ) T_{r,i}(j) Tr,i(j) 表示当前存储图像中剩余基本单元的剩余比特数,且 T r , i ( j ) T_{r,i}(j) Tr,i(j) 的初始值为 T i ( j ) T_i(j) Ti(j)。第l个基本单元的目标比特数由以下公式给出

b ~ l , i ( j ) = T r , i ( j ) σ ~ l , i 2 ( j ) Σ k = l N u n i t σ ~ k , i 2 ( j ) \widetilde{b}_{l,i}(j)=T_{r,i}(j)\frac{\widetilde{\sigma}^2_{l,i}(j)}{\Sigma^{N_{unit}}_{k=l}\widetilde{\sigma}^2_{k,i}(j)} b l,i(j)=Tr,i(j)Σk=lNunitσ k,i2(j)σ l,i2(j)

 (2.2) 步骤2.2 计算所有已编码基本单元生成的头部比特数的平均值:
m ~ h d r , l = m ~ h d r , l − 1 ( 1 − 1 l ) + m ^ h d r , i l \widetilde{m}_{hdr,l}=\widetilde{m}_{hdr,l-1}(1-\frac{1}{l})+\frac{\hat{m}_{hdr,i}}{l} m hdr,l=m hdr,l1(1l1)+lm^hdr,i

m h d r , l = m ~ h d r , l l N u n i t + m h d r , 1 ( 1 − l N u n i t ) m_{hdr,l}=\widetilde{m}_{hdr,l}\frac{l}{N_{unit}}+m_{hdr,1}(1-\frac{l}{N_{unit}}) mhdr,l=m hdr,lNunitl+mhdr,1(1Nunitl)

其中 m ^ h d r , i \hat{m}_{hdr,i} m^hdr,i是当前存储图像中第l 个基本单元实际生成的头部比特数, m h d r , 1 m_{hdr,1} mhdr,1是从前一帧的所有基本单元中估计的值。

 (2.3) 计算纹理比特数 b ^ l , i ( j ) \hat{b}_{l,i}(j) b^l,i(j)
b ^ l , i ( j ) = b ~ l , i ( j ) − m h d r , l \hat{b}_{l,i}(j)=\widetilde{b}_{l,i}(j)-m_{hdr,l} b^l,i(j)=b l,i(j)mhdr,l

为了保证每个基本单元的质量, b ^ l , i ( j ) \hat{b}_{l,i}(j) b^l,i(j)随后还会除以 R i ( j ) / ( 4 f N u n i t ) R_{i}(j)/(4fN_{unit}) Ri(j)/(4fNunit)

PS:
(1) 将总比特数分为纹理比特数和头部比特数,总比特数由步骤(2.1)给出,头部比特数由步骤(2.2)给出,纹理比特数由步骤(2.3)给出
(2) 在步骤(2.2)中, m h d r , l m_{hdr,l} mhdr,l表示第l个基本单元的头部比特数,其由两部分组成:
 (a) 基于帧内预测思想,利用当前帧前一个已编码单元,即第l-1个基本单元的头部比特数来获取。其中第l-1个基本单元的头部比特数权重为 ( 1 − 1 l ) (1-\frac{1}{l}) (1l1),第l个基本单元实际生成的头部比特数占比为\frac{1}{l}
 (b) 基于帧间预测思想,利用前一帧的所有已编码单元的平均值,即 m h d r , 1 m_{hdr,1} mhdr,1
 (c) 计算第l个基本单元的头部比特数时,基于帧内思想获得的比特数权重为 l N u n i t \frac{l}{N_{unit}} Nunitl,基于帧间思想获得的比特权重为 1 − l N u n i t 1-\frac{l}{N_{unit}} 1Nunitl。举例来说,假设 l = 50 l=50 l=50 N u n i t = 120 N_{unit}=120 Nunit=120,即处于整帧的前半部分编码,则帧间的权重较大,这是因为帧间部分使用的是前一帧中所有的已编码单元,这样可参考的信息更多;反之,假设 l = 100 l=100 l=100 N u n i t = 120 N_{unit}=120 Nunit=120,即处于整帧的后半部分编码,则帧内的权重较大,这是因为当前帧已经编码了很多单元,帧内可使用的信息足够多,其权重应该更大
(3) 最后,在获取了目标纹理比特数之后,还会做一个rounding

(3) 步骤3: 使用二次R-D模型[3]计算当前基本单元的量化参数。我们需要考虑以下三种情况:
情况1:当前存储图像中的第一个基本单元
Q P l , i ( j ) = Q P ^ i ( j − L − 1 ) QP_{l,i}(j)=\hat{QP}_{i}(j-L-1) QPl,i(j)=QP^i(jL1)
其中 Q P ^ i ( j − L − 1 ) \hat{QP}_{i}(j−L−1) QP^i(jL1) 是前一个存储图像中所有基本单元的量化参数的平均值。

情况2:当 T r , i < 0 T_{r,i}<0 Tr,i<0 时,当前基本单元的量化参数应大于前一个基本单元的量化参数,以使生成的比特数总和接近 T i ( j ) T_{i}(j) Ti(j)
Q P l , i = Q P l − 1 , i ( j ) + X b u QP_{l,i}=QP_{l-1,i}(j)+X_{bu} QPl,i=QPl1,i(j)+Xbu
其中, X b u X_{bu} Xbu是两个连续基本单元的量化参数的变化范围。

为了保持视觉质量的平滑性,量化参数进一步被限制为:
Q P l , i ( j ) = m a x { 0 , Q P ‾ i ( j − L − 1 ) − Y f r , m i n { 51 , Q P ‾ i ( j − L − 1 ) + Y f r , Q P l , i ( j ) } } QP_{l,i}(j)=max\{0,\overline{QP}_{i}(j-L-1)-Y_{fr}, min\{51, \overline{QP}_{i}(j-L-1)+Y_{fr}, QP_{l,i}(j)\}\} QPl,i(j)=max{0,QPi(jL1)Yfr,min{51,QPi(jL1)+Yfr,QPl,i(j)}}
其中, Y f r Y_{fr} Yfr是量化参数的进一步变化范围

情况3:否则,我们首先使用二次模型[3]和情况2中给出的限制来计算一个量化参数 Q P l , i ( j ) QP_{l,i}(j) QPl,i(j)

(4) 步骤4:对当前基本单元中的所有宏块(MBs)执行RDO。

(5) 步骤5:更新剩余比特数 T r , i ( j ) T_{r,i}(j) Tr,i(j),并更新头部MAD预测模型和二次R-D模型的参数。

(6) 步骤6:编码当前存储图像后,更新 Q P ^ i ( j ) \hat{QP}_{i}(j) QP^i(j)

PS:
(1) 在步骤3当中,使用的二次RD模型如下,这是一个提案中的公式(Z. G. Li, W. Gao, Feng Pan, S. W. Ma. K. P. Lim, G. N.Feng, X. Lm, R. Susanto, Y. Lu and H. Q. Lu. “Adaptive rate control with HRD consideration”. In 8th meeting:Geneva, 23-27, May, 2003, JVT-H014)
T a r g e t _ b i t s = c 1 ∗ M A D Q S t e p + c 2 ∗ M A D Q S t e p ∗ Q S t e p Target\_bits=c_1 * \frac{MAD}{QStep}+c_2 * \frac{MAD}{QStep * QStep} Target_bits=c1QStepMAD+c2QStepQStepMAD
公式描述了量化步长、目标比特和MAD之间的对应关系。延续前面的步骤,这里可以根据前面获得的目标比特来计算QStep,根据QStep和QP的对应表,获得QP
(2) 在确定QP时,分为三种情况
 (a) 如果是第一个基本单元,其QP由前一帧中所有基本编码单元的QP均值来确定
 (b) 如果剩余目标比特小于0,则会适当增大QP。调整的依据是前后量化参数变化的范围
 (c) 如果不属于前面两种情况,则先根据二次RD模型获得一个初始QP,随后添加情况2中的平滑性限制
(3) 在后续的步骤4,5,6中,根据前面计算出来的QP执行RDO过程,更新一系列参数

6.实验结果

我们将具有我们码率控制的H.264编码器的编码效率与具有固定量化参数的H.264编码器的编码效率进行了比较。这种类型的比较是由H.264的临时工作组根据[15]推荐的,实验设置在[4]中给出。表1列出了(Y, PSNR)的实验结果。结果显示,与使用固定量化参数的H.264编码器相比,我们的方案可以将平均PSNR提高多达0.78dB。在正常测试条件下,对于H.264测试序列,改进的平均PSNR为0.43dB。
在这里插入图片描述

7.结论

本文通过引入基本单元的概念和线性绝对差(MAD)预测模型,提出了一种自适应的H.264码率控制方案。对于H.264推荐的所有测试序列,整体平均PSNR改进为0.43dB。Remark 1中提供了一种替代方法,这将在我们未来的研究中进行探讨。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

考研编程:10.11 回文数 水仙花 生成一定范围内的随机数 求二叉树宽度

回文数 #include <stdio.h>int main(){int a,b,c0,sum;scanf("%d",&a);ba;while(b!0){c b%10 c*10;b b/10;}if(ca){printf("yes");}return 0; } 水仙花 #include <stdio.h> #include <math.h> int main(){int a,b,c0,sum;scan…

网络协议原理

文章目录 TCP通信原理TCP与UDP的对比应用层应用层协议 --- tcp协议定制直接传递对象自定义协议现在要解决的问题业务处理 json的使用使用json进行序列化和反序列化操作 总结 TCP通信原理 tcp是面向字节流的 同时他也是面向连接的 所以TCP的服务器编写代码如图所示: 客户端的编…

C语言:在Visual Studio中使用C语言scanf输入%s出现的栈溢出问题

学了C之后就很少使用C语言了&#xff0c;今天帮同学解答C语言问题&#xff0c;遇到了一个我以前没有遇到过的问题。 一、问题描述 先看以下代码&#xff1a; #include<stdio.h> int main() {char str[100] { 0 };scanf_s("%s", str);printf("%s",…

探索极简计算的新边界:从Uxn虚拟机看未来编程生态

越来越多的开发者追求复杂度和功能性的极致,然而,有一个小众的编程社区选择了截然不同的道路——极简主义。Uxn虚拟机便是这一思潮的代表之一。它通过简洁的指令集和有限的硬件资源模拟,试图打造一种可以在多种设备上运行的便携性编程环境。 与主流的重型操作系统和复杂…

Redis面试题——第四篇

1. Redis主从复制的常见拓扑结构有哪些 一主多从&#xff1a;这是最基本的拓扑结构&#xff0c;包含一个主节点和多个从节点&#xff0c;所有写操作都在主节点上执行&#xff0c;而读操作可以在从节点上进行&#xff0c;以提高读取速度和负载均衡。 树状主从结构&#xff1a;从…

模拟电路设计期末速成总结

模拟电路设计期末速成总结 模拟电路设计是电子工程和电气工程专业中的一门重要基础课&#xff0c;主要研究连续时间信号&#xff08;模拟信号&#xff09;的处理和应用。期末复习时&#xff0c;针对这门课可以分为以下几个关键内容进行速成总结。 一、基本概念与元件 模拟信号…

C++设计模式——代理模式

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言代理模式的定义代理模式的具体实现 引言 我们经常听到代理服务器「代理服务器是一个中间服务器&#xff0c;能够接收客户端的请求&#xff0c;并代表客户端向服务器发起请求&#xff0c;然后将服…

经典文献阅读之--RGBD GS-ICP SLAM(结合ICP和3D GS构建最快的稠密SLAM)

0. 简介 同时定位与地图构建&#xff08;SLAM&#xff09;的密集表示在机器人技术、虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;应用中扮演了关键角色。在密集表示SLAM的最新进展中&#xff0c;利用神经场景表示和3D高斯表示以实现高保真的空间表…

Mycat引领MySQL分布式部署新纪元:性能与扩展性的双重飞跃

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 目录 前言&#…

使用OneAPI+Ollama+Dify搭建一个兼容OpenAI的API发布及AI应用开发系统(三)Dify的安装及配置

在GitHub中的AI工作流短代码平台中&#xff0c;Dify获星一直名列前茅&#xff0c;目前已达48K星&#xff0c;其工作稳定性也是非常的高&#xff0c;在这里我们介绍一下Dify的安装。 由于Dify的结构非常的复杂&#xff0c;我们这里介绍Docker的方式进行安装&#xff0c;硬件的最…

Nvidia Jetson Orin平台部署CenterPoint模型

最近尝试将CenterPoint模型部署到Orin平台,网络上教程很多,也很杂乱,于是便整理一版自用。 主要根据NVIDIA Lidar AI Solution进行复现。并在此基础上进行补充 Orin平台: python:3.8 CUDA:11.4 torch:1.14.0 torchvision:0.15.1 TensorRT: 8.5.2.1 在Compile &&a…

Java并发编程实战 08 | 彻底理解Shutdown Hook

钩子线程&#xff08;Hook Thread&#xff09;简介 在一个 Java 应用程序即将退出时&#xff08;比如通过正常执行完成或通过用户关闭应用程序&#xff09;&#xff0c;通常需要进行一些清理操作&#xff0c;例如&#xff1a; 释放资源&#xff08;如文件句柄、网络连接&…

解锁C++继承的奥秘:从基础到精妙实践(下)

文章目录 前言&#x1f950;五、多继承&#xff0c;菱形继承和菱形虚拟继承&#x1f9c0;5.1 多继承&#x1f9c0;5.2 菱形继承&#x1f9c0;5.3 虚拟继承&#xff08;解决菱形继承问题&#xff09;5.3.1 虚拟继承的语法&#xff1a;5.3.2 虚拟继承示例&#xff1a; &#x1f9…

大舍传媒-海外媒体发稿:为您打造全球品牌影响力

大舍传媒-海外媒体发稿&#xff1a;为您打造全球品牌影响力 在当今全球化的商业环境中&#xff0c;企业若想在激烈的市场竞争中脱颖而出&#xff0c;拓展全球市场&#xff0c;提升品牌影响力至关重要。大舍传媒的海外媒体发稿服务&#xff0c;正是您实现这一目标的得力助手。 …

面对服务器掉包的时刻困扰,如何更好的解决

在数字化时代&#xff0c;服务器的稳定运行是企业业务连续性的基石。然而&#xff0c;服务器“掉包”现象&#xff0c;即数据包在传输过程中丢失或未能正确到达目的地的情况&#xff0c;却时常成为IT运维人员头疼的问题。它不仅影响用户体验&#xff0c;还可能导致数据不一致、…

【AI 新观察】“转人工!转人工!”——智能客服痛点与破局之路

在当今数字化时代&#xff0c;智能客服在电商等众多领域被广泛应用&#xff0c;然而&#xff0c;一句又一句“转人工&#xff01;转人工&#xff01;”却常常暴露出智能客服存在的痛点。一、智能客服之痛 1. 理解偏差引不满 智能客服在理解客户问题时&#xff0c;常常出现偏差…

mybatisPlus对于pgSQL中UUID和UUID[]类型的交互

在PGSQL中&#xff0c;有的类型是UUID和UUID[]这种类型&#xff0c;在mybatis和这些类型交互的时候需要手动设置类型处理器才可以&#xff0c;这里记录一下类型处理器的设置 /*** UUID类型处理器*/ public class UUIDTypeHandler extends BaseTypeHandler<UUID> {/*** 获…

Golang | Leetcode Golang题解之第478题在圆内随机生成点

题目&#xff1a; 题解&#xff1a; type Solution struct {radius, xCenter, yCenter float64 }func Constructor(radius, xCenter, yCenter float64) Solution {return Solution{radius, xCenter, yCenter} }func (s *Solution) RandPoint() []float64 {r : math.Sqrt(rand.…

热更新解决方案2 —— Lua语法相关知识点

概述 开发环境搭建 Lua语法 1.第一个Lua程序 2.变量 print("******变量*******"); --lua当中的简单变量类型 -- nil number string boolean -- lua 中所有的变量声明 都不需要声明变量类型 它会自动的判断类型 -- 类似C# 中的var --lua中的一个变量 可以随便赋值 ——…

Product1M 深度理解 PPT

系列论文研读目录 文章目录 系列论文研读目录 模态内检索&#xff1a;是指在同一模态&#xff08;例如&#xff0c;图像、文本或音频&#xff09;中进行的检索任务。它通常涉及在同一类型的数据中查找相关项。比如下面图像只能查询图像&#xff0c;文本只能查询文本&#xff0c…