【H.264/AVC视频编解码技术详解】十七:帧内预测编码的预测实现方法

本文主要是介绍【H.264/AVC视频编解码技术详解】十七:帧内预测编码的预测实现方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看!

“纸上得来终觉浅,绝知此事要躬行”,只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会!

链接地址:H.264/AVC视频编解码技术详解

GitHub代码地址:点击这里

一、帧内预测模式在码流中的表示

在前面的博文:【H.264/AVC视频编解码技术详解】十二、解析H.264码流的宏块结构(下):H.264帧内编码宏块的预测结构中,我们解析了H.264码流中的宏块结构,并且分析了其中的语法元素mb_pred()。mb_pred()包含了帧内预测宏块的预测数据,其定义为:
在这里插入图片描述

其中,表示帧内预测模式的语法元素有:

  • prev_intra4x4_pred_mode_flag和prev_intra8x8_pred_mode_flag:表示帧内预测模式预测标识。如果该标识位为1,表示帧内预测模式的预测值就是实际的模式,否则就需要另外传递实际的帧内预测模式。
  • rem_intra4x4_pred_mode和rem_intra8x8_pred_modeg:表示额外传递的实际帧内预测模式。
  • intra_chroma_pred_mode:表示色度分量的预测模式,取值范围为[0,3],分别代表DC、水平、垂直和平面模式。

二、计算实际的帧内预测模式

以4×4模式的亮度信号为例,该部分的解析方式定义在标准文档的8.3.1.1节。

1. 计算相邻块的位置等参数

帧内预测模式的计算也利用了相邻块的模式相关性计算,计算所需的相邻块需要的是子块上方和左方的块的信息。

计算相邻块的预测模式首先要得到相邻块的位置参数。

1.1 计算相邻块的位置

计算亮度4×4相邻块的方式在标准文档的6.4.10.4节指定:

该过程的输入数据为当前亮度4×4块在宏块内的索引序号luma4x4BlkIdx;

输出数据为:

  • 相邻块A所属宏块地址mbAddrA:当前宏块或者左方宏块,根据luma4x4BlkIdx的不同选择;
  • 相邻块A的子块索引luma4x4BlkIdxA:左邻域子块在mbAddrA宏块内的索引;
  • 相邻块B所属宏块地址mbAddrB:当前宏块或者上方宏块,根据luma4x4BlkIdx的不同选择;
  • 相邻块B的子块索引luma4x4BlkIdxB:上邻域子块在mbAddrB宏块内的索引;

左方相邻块信息mbAddrA、luma4x4BlkIdxA和右侧相信块信息mbAddrB、luma4x4BlkIdxB的计算方法:通过子块位置的
坐标差值(xD,yD)。
在这里插入图片描述

多数情况下,H.264中的一个block都以4×4像素为大小,宽高相等,因此上图中ABCD四个邻块的坐标差值分别为:

  • 邻块A:(-1, 0)
  • 邻块B:(0, -1)
  • 邻块C:(4, -1)
  • 邻块D:(-1,-1)
1.2 获取相邻块参考像素的位置

当前块的位置可以认为是当前块左上角像素对于整个宏块的相对位置(x,y),该部分在6.4.3中指定。计算中使用了InverseRasterScan函数,该函数是个分段函数,在标准文档中定义为公式(5-7)。

由此,可以得到参考像素对于当前宏块的相对位置:

(xN,yN) = (x + xD, y + yD);
1.3 通过参考像素的位置的相对位置获取相邻块的参数

我们已经可以获取相邻块相对于当前宏块的位置(xN,yN),通过(xN,yN)获取相邻块参数的方法定义与6.4.11.1节(只考虑帧编码情况)。通过(xN,yN)的取值情况,可以判断参考像素所在宏块的位置以及其他信息:

  • xN < 0, yN < 0:参考像素位于当前宏块的左上角,宏块位置为mbAddrD。
  • xN < 0, 0 <= yN < 16:参考像素位于当前宏块左侧,宏块位置为AmbAddrA。
  • 0 <= xN < 16, yN < 0:参考像素位于当前宏块上方,宏块位置为mbAddrB。
  • 0 <= xN < 16, 0 <= yN < 16:参考像素位于当前宏块内部,宏块位置即为当前宏块。
  • xN >= 16, yN < 0:参考像素位于当前宏块右上方,宏块位置为mbAddrC。
  • xN >= 16, 0 <= yN < 16:参考像素位于当前宏块右方,实际上不可获得。
  • yN >=16:参考像素位于当前宏块的下一行,实际上不可获得。

从参考像素相对当前块位置(xN,yN)计算宏块位置,可以计算参考像素在参考宏块中的相对位置(xW,yW)。计算方法为:

xW = (xN + 16) % 16;
yW = (yN + 16) % 16;
1.4 获取指定的相邻块在所在宏块中的索引

如果参考像素所在的宏块实际上不可获得,则整个宏块索引皆定义为不可得,否则计算方式定义在6.4.12.1节中,即对于像素(x,y):

luma4x4BlkIdx = 8 * (y/8) + 4 * (x/8) + 2 * ((y%8)/4) + ((x%8)/4)

2. 推导flag数据dcPredModePredictedFlag

当满足以下条件的任意一种时,dcPredModePredictedFlag的值被设为1。

  • 宏块AmbAddrA不可获得;
  • 宏块AmbAddrB不可获得;
  • 宏块AmbAddrA可获得,但在标识位constrained_intra_pred_flag限定为1的情况下以帧间模式进行编码;
  • 宏块AmbAddrA可获得,但在标识位constrained_intra_pred_flag限定为1的情况下以帧间模式进行编码;

在其他情况下,dcPredModePredictedFlag的值被设为0。

3. 推导出相邻块的帧内预测模式intra4x4PredMode

这一步骤的目的是推导出相邻块A和B的帧内预测模式。而实际上有时候,如某个相邻块不可获得那么其预测模式也会有相应的替代方法。具体来说:

  • 如果dcPredModePredictedFlag被设为1,或者相邻块A或B所在的宏块不是Intra 4×4或8×8模式,那么A或者B的预测模式intra4x4(8x8)PredModeA/B的值设为2;
  • 若不满足前款条件,则继续判断:
    • 若相邻块A或B所在的宏块按照Intra4x4模式编码,那么其预测模式intra4x4(8x8)PredModeA/B设为Intra4x4PredMode[ luma4x4BlkIdxN ];
    • 如果按照Intra8x8模式进行编码,其预测模式设为Intra8x8PredMode[ luma4x4BlkIdxN >> 2 ]。

4. 从相邻块的帧内预测模式得出当前块的预测模式

现在我们已经获得的信息有:

  • 左方相邻块A的预测模式;
  • 上方相邻块B的预测模式;
  • 码流中读取的语法元素prev_intra4x4_pred_mode_flag;

从上述数据中获取当前块的预测模式的方式在文档8.3.1.1中如下表示:

predIntra4x4PredMode = Min( intraMxMPredModeA, intraMxMPredModeB )
if( prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ] )Intra4x4PredMode[ luma4x4BlkIdx ] = predIntra4x4PredMode
elseif( rem_intra4x4_pred_mode[ luma4x4BlkIdx ] < predIntra4x4PredMode )Intra4x4PredMode[ luma4x4BlkIdx ] = rem_intra4x4_pred_mode[ luma4x4BlkIdx ]
elseIntra4x4PredMode[ luma4x4BlkIdx ] = rem_intra4x4_pred_mode[ luma4x4BlkIdx ] + 1
  1. 从左侧和上方相邻块的预测模式中选取较小的一个作为预先定义模式。
  2. 判断码流中读取的标志位prev_intra4x4_pred_mode_flag,如果该标志位为1,则预先定义模式就是当前块的预测模式;
  3. 如果标志位prev_intra4x4_pred_mode_flag为0,则根据码流中解析出的语法元素 rem_intra4x4_pred_mode判断。如果rem_intra4x4_pred_mode的值小于预定义模式的值则选用rem_intra4x4_pred_mode;如果大于等于预定义模式,则当前块的预测模式设为rem_intra4x4_pred_mode + 1。

5. 总结

其实标准文档中定义的繁杂无比的解析方式,简而言之可以分为两步:

  • 获取左侧和上方子块的预测模式,并选择较小的那个作为当前的模式预测值;
  • 码流中指定了要不要用这个预测值。如果用,那么这个预测值就是当前块的帧内预测模式;否则就从后续读取的预测模式中计算。

三、获取预测数据

该部分主要实现的功能是通过参考数据和帧内预测模式,获取当前子块的预测块。此部分定义在标准文档的8.3.1.2节。该步骤通过当前块的预测模式以及相邻块的参考像素值,输出当前块的一个预测块数据。

对于某一个4×4像素块,其参考像素包括13个像素点。如果(x,y)表示参考像素点相对于像素块左上像素的相对位置,则x和y的取值分别为:x=-1, y=(-1, 3);x=(0, 7), y=-1。以图表示如下所示:
在这里插入图片描述

根据当前块在图像中的位置(xO,yO)与参考像素的相对位置,可获取参考像素的绝对位置(xN,yN),计算方式为(xN,yN)=(xO+x, yO+y)。并参考上一章的方法可以获取参考像素所属的宏块地址mbAddrN号及宏块内相对位置(xW,yW)。

获取13个参考像素的像素值,首先判断某个像素值是否有效/可以获得。当下列4个条件满足任意一个,那么该像素便被判定为无效/不可获得:

  • 宏块mbAddrN不可获得;
  • 宏块mbAddrN为帧间预测模式,且标识位constrained_intra_pred_flag为1;
  • 宏块mbAddrN为SI类型,,且标识位constrained_intra_pred_flag为1,且当前宏块不是SI类型;
  • x大于3,且块索引luma4x4BlkIdx为3或11;(这一条说明了什么意思?视频教程中有详细解释)

如果上述条件皆不满足,那么参考像素p(x,y)被判定为有效,即可以用作4x4帧内预测。在宏块编号mbAddrN及块内相对位置(xW,yW)均已获取之后,再由mbAddrN获取宏块在图像中的位置即可获取p(x,y)的像素值。需要注意的一个特殊情况是:若像素p(3,-1)可获得,而p(4,-1)、p(5,-1)、p(6,-1)、p(7,-1)都不可获得,那么p(4,-1)、p(5,-1)、p(6,-1)、p(7,-1)这4个无效点都将替换为p(3,-1)的值参与预测运算。

四、九种帧内预测模式

在获取了13个预测像素点之后,再根据第2节计算出的预测模式,便可以获取相应的预测块数据。该部分在标准文档的8.3.1.2.1到8.3.1.2.9节定义。

模式0:垂直模式

当前块的帧内预测模式为0时,使用垂直模式生成预测块。该模式只有预测像素p(0,-1)~p(3,-1)有效的条件下可用。预测块的计算方法为:

pred4x4L[ x, y ] = p[ x, −1 ], with x, y = 0..3

模式1:水平模式

当前块的帧内预测模式为1时,使用水平模式生成预测块。该模式只有预测像素p(-1,0)~p(-1,3)的条件下可用。预测块的计算方法为:

pred4x4L[ x, y ] = p[ −1, y ], with x,y = 0..3

模式2:DC模式

当前块的帧内预测模式为2时,使用DC模式生成预测块。DC模式下预测块的所有16个像素点取值一致,计算需要根据预测像素有效性分为一下不同情况:

  • 如果上方相邻像素p(0,-1)~p(3,-1)和左方相邻像素p(-1,0)~p(-1,3)这8个点都有效,预测块的计算方法为
pred4x4L[x,y] = (p[0,−1] + p[1,−1] + p[2,−1] + p[3,−1] + p[−1,0] + p[−1,1] + p[−1,2] + p[−1,3] + 4) >> 3
  • 如果上方相邻像素p(0,-1)~p(3,-1)无效,而左方相邻像素p(-1,0)~p(-1,3)有效,预测块的计算方法为
pred4x4L[ x, y ] = ( p[ −1, 0 ] + p[ −1, 1 ] + p[ −1, 2 ] + p[ −1, 3 ] + 2 ) >> 2
  • 如果左方相邻像素p(-1,0)~p(-1,3)无效,而上方相邻像素p(0,-1)~p(3,-1)有效,预测块的计算方法为
pred4x4L[ x, y ] = ( p[ 0, −1 ] + p[ 1, −1 ] + p[ 2, −1 ] + p[ 3, −1 ] + 2 ) >> 2
  • 如果上述8个相邻像素均无效,预测块的计算方法为:
pred4x4L[ x, y ] = ( 1 << ( BitDepthY − 1 ) )

模式3:左下对角线模式

当前块的帧内预测模式为3时,使用左下对角线模式生成预测块。该模式只有预测像素p(0,-1)~p(7,-1)有效的条件下可用。预测块的计算方法为:

  • 当(x,y)=(3,3),即计算一个4×4像素块最右下方的一个点时:
pred4x4L[3,3] = ( p[ 6, −1 ] + 3 * p[ 7, −1 ] + 2 ) >> 2
  • 其他情况:
pred4x4L[ x, y ] = ( p[ x + y, −1 ] + 2 * p[ x + y + 1, −1 ] + p[ x + y + 2, −1 ] + 2 ) >> 2

模式4:右下对角线模式

当前块的帧内预测模式为4时,使用左下对角线模式生成预测块。该模式只有上方预测像素p(0,-1)~p(3,-1)、左方预测像素p(-1,0)~p(-1,3)和左上角对角像素点p(-1,-1)有效的条件下可用。预测块的计算方法为:

  • x > y :

pred4x4L[ x, y ] = ( p[ x − y − 2, −1] + 2 * p[ x − y − 1, −1 ] + p[ x − y, −1 ] + 2 ) >> 2

  • x < y :

pred4x4L[ x, y ] = ( p[ −1, y − x − 2 ] + 2 * p[ −1, y − x − 1 ] + p[ −1, y − x ] + 2 ) >> 2

  • x == y:

pred4x4L[ x, y ] = ( p[ 0, −1 ] + 2 * p[ −1, −1 ] + p[ −1, 0 ] + 2 ) >> 2

模式5:右垂直模式

当前块的帧内预测模式为5时,使用右垂直模式生成预测块。该模式只有上方预测像素p(0,-1)~p(3,-1)、左方预测像素p(-1,0)~p(-1,3)和左上角对角像素点p(-1,-1)有效的条件下可用。预测块的计算方法为:

首先计算中间变量:zVR = 2 * x - y,根据zVR取值

  • 若zVR等于0/2/4/6:
pred4x4L[ x, y ] = ( p[ x − ( y >> 1 ) − 1, −1 ] + p[ x − ( y >> 1 ), −1 ] + 1 ) >> 1
  • 若zVR等于1/3/5:
pred4x4L[ x, y ] = ( p[ x − ( y >> 1 ) − 2, −1] + 2 * p[ x − ( y >> 1 ) − 1, −1 ] + p[ x − ( y >> 1 ), −1 ] + 2 ) >> 2
  • 若zVR等于-1:
pred4x4L[ x, y ] = ( p[ −1, 0 ] + 2 * p[ −1, −1 ] + p[ 0, −1 ] + 2 ) >> 2
  • 其他情况,即zVR等于-2或-3:
pred4x4L[ x, y ] = ( p[ −1, y − 1 ] + 2 * p[ −1, y − 2 ] + p[ −1, y − 3 ] + 2 ) >> 2

模式6:下水平模式

当前块的帧内预测模式为6时,使用下水平模式生成预测块。该模式只有上方预测像素p(0,-1)~p(3,-1)、左方预测像素p(-1,0)~p(-1,3)和左上角对角像素点p(-1,-1)有效的条件下可用。预测块的计算方法为:

首先计算中间变量:zHD = 2 * y - x,根据zHD的取值

  • 若zHD等于0/2/4/6:
pred4x4L[ x, y ] = ( p[ −1, y − ( x >> 1 ) − 1 ] + p[ −1, y − ( x >> 1 ) ] + 1 ) >> 1
  • 若zHD等于1/3/5:
pred4x4L[ x, y ] = ( p[ −1, y − ( x >> 1 ) − 2 ] + 2 * p[ −1, y − ( x >> 1 ) − 1 ] + p[ −1, y − ( x >> 1 ) ] + 2 ) >> 2
  • 若zHD等于-1:
pred4x4L[ x, y ] = ( p[ −1, 0 ] + 2 * p[ −1, −1 ] + p[ 0, −1 ] + 2 ) >> 2
  • 其他情况,即zHD等于-2或-3:
pred4x4L[ x, y ] = ( p[ x − 1, −1 ] + 2 * p[ x − 2, −1 ] + p[ x − 3, −1 ] + 2 ) >> 2

模式7:左垂直模式

当前块的帧内预测模式为7时,使用左垂直模式生成预测块。该模式只有预测像素p(0,-1)~p(7,-1)有效的条件下可用。预测块的计算方法为:

  • 若y等于0或2;
pred4x4L[ x, y ] = ( p[ x + ( y >> 1 ), −1 ] + p[ x + ( y >> 1 ) + 1, −1 ] + 1) >> 1
  • 若y等于1或3:
pred4x4L[ x, y ] = ( p[ x + ( y >> 1 ), −1 ] + 2 * p[ x + ( y >> 1 ) + 1, −1 ] + p[ x + ( y >> 1 ) + 2, −1 ] + 2 ) >> 2

模式8:上水平模式

当前块的帧内预测模式为8时,使用上水平模式生成预测块。该模式只有预测像素p(-1,0)~p(-1,3)的条件下可用。预测块的计算方法为:

首先计算中间变量zHU:zHU = x + 2 * y;

  • 若zHU等于0/2/4:
pred4x4L[ x, y ] = ( p[ −1, y + ( x >> 1 ) ] + p[ −1, y + ( x >> 1 ) + 1 ] + 1 ) >> 1
  • 若zHU等于1或3:
pred4x4L[ x, y ] = ( p[ −1, y + ( x >> 1 ) ] + 2 * p[ −1, y + ( x >> 1 ) + 1 ] + p[ −1, y + ( x >> 1 ) + 2 ] + 2 ) >> 2
  • 若zHU等于5:
pred4x4L[ x, y ] = ( p[ −1, 2 ] + 3 * p[ −1, 3 ] + 2 ) >> 2
  • 其他情况,即zHU大于5:
pred4x4L[ x, y ] = p[ −1, 3 ]

五、亮度分量16×16模式的帧内预测方法

针对16×16模式亮度分量的帧内预测方法,定义于标准文档的8.3.3节。对于16×16模式的亮度块,共计需要33个参考像素点,分别为当前宏块的左侧16个点、上方16个点和左上角的一个像素点。类似于4×4模式,这33个参考像素相对于当前块相对位置为:

  • p(-1, -1):左上角对角像素;
  • p(-1,0)~p(-1,15):左侧相邻像素;
  • p(0,-1)~p(15,-1):上方相邻像素;

获取这33个预测像素点的方法也类似于4×4模式预测像素的获取,主要步骤如获取所在宏块的地址、所在宏块左上角像素的地址、参考像素点相对于整个宏块的地址等。

整个16×16块的预测模式不需要专门推导,因为在宏块模式中就已经指定了。共定义4种预测模式:

模式0:垂直模式

只有预测像素p(0,-1)~p(15,-1)有效时才可以使用,计算方法为:

predL[ x, y ] = p[ x, −1 ], with x, y = 0..15

模式1:水平模式

只有预测像素p(-1,0)~p(-1,15)有效时才可以使用,计算方法为:

predL[ x, y ] = p[ −1, y ], with x, y = 0..15

模式2:DC模式

16×16模式的DC预测模式同4×4模式的DC预测方法类似,判断左侧16个像素和上方16个像素的有效性,将其中有效部分的均值作为整个预测块的像素值。

模式3:平面模式

平面模式是相对于其他模式的一种比较独特的预测模式,只有在上述33个预测像素点均有效时才可以使用。计算方法为:

predL[ x, y ] = Clip1Y( ( a + b * ( x − 7 ) + c * ( y − 7 ) + 16 ) >> 5 ), with x, y = 0..15

上式中的a/b/c为中间变量,计算方式为:

a = 16 * ( p[ −1, 15 ] + p[ 15, −1 ] )
b = ( 5 * H + 32 ) >> 6
c = ( 5 * V + 32 ) >> 6

六、色度分量的帧内预测模式

色度信息的帧内预测在标准文档的8.3.4节。其原理与亮度分量的预测模式基本一致。

这篇关于【H.264/AVC视频编解码技术详解】十七:帧内预测编码的预测实现方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/415376

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo