H264编码器实现-帧内预测之像素值预测

前言

本文所介绍的像素值预测,是指在帧内预测总体流程中的预测块每个像素值的推导过程。当我们已知向量像素的重建值的时候,我们就可以对当前预测块进行像素值预测。该过程得到的结果将与源像素值相减得到残差,为后续变换量化提供数据来源。

温馨提示:本文所讲的内容都有对应的可执行代码,读者可以结合代码理解文章内容。

预测模式

对亮度像素而言,4×4 亮度子块有9 种可选预测模式,适用于带有大量细节的图像编码。16×16 亮度块有4种预测模式,适用于平坦区域图像编码。对于色度像素,只有8x8色度块,其预测也有4 种预测模式,类似于16×16 亮度块预测模式。

4x4亮度块预测

上文说到4x4亮度块有9种预测模式,不同模式预测的角度不同,下面是各个预测模式的描述:

模式名称描述
模式0由A、B、C、D 垂直推出相应像素值
模式1由I、J、K、L 水平推出相应像素值
模式2由A~D 及I~L 平均值推出所有像素值
模式3由45°方向像素内插得出相应像素值
模式4由45°方向像素内插得出相应像素值
模式5由26.6°方向像素值内插得出相应像素值
模式6由26.6°方向像素值内插得出相应像素值
模式7由26.6° 方向像素值内插得出相应像素值
模式8由26.6° 方向像素值内插得出相应像素值

各预测模式
当前块预测
这里对各个预测模式做个解释:
(1)预测模式0(vertical):当前块的十六个像素值由其上方A、B、C、D四个像素值决定,即a=e=i=m=A,b=f=j=n=B,c=g=k=o=C,d=h=l=p=D
模式0
(2)预测模式1(horizontal):当前块的十六个像素值由其左方I、J、K、L四个像素值决定,即a=b=c=d=I,e=f=g=h=J,i=j=k=l=K,m=n=o=p=L。
模式1
(3)预测模式2(DC):十六个像素值完全相等,等于ABCDIJKL这八个像素的平均值。
模式3
(4)预测模式3(diagnal down-left):左下45度方向上的像素相等,由相邻块像素加权平均得到。
即a==(A+2B+C+2)/4,b=e=(B+2C+D)/4,c=f=i=(C+2D+E+2)/4,d=g=j=m=(D+2E+F+2)/4,h=k=n=(E+2F+G+2)/4,l=o=(F+2G+H+2)/4,p=(G+2H+H+2)/4=(G+3H+2)/4。
模式4
(5)预测模式4(diag down-right):右下45度方向上的像素相等,由相邻块像素加权平均得到。
即a=f=k=p=(I+2M+A+2)/4,e=f=o=(J+2I+M)/4,i=n=(K+2J+I+2)/4,m=(L+2K+J+2)/4,b=g=l=(B+2A+M+2)/4,c=h=(C+2B+A+2)/4,d=(D+2C+B+2)/4。
模式4
(6)预测模式5(vertical right):

include <stdio.h>
#include <stdlib.h>
#include <string.h>#define BLK_WIDTH 4 //当前块宽度
#define BLK_HIGHT 4 //当前块高度
#define BLOCK_SIZE 4
#define BLOCK_SHIFT 2// Predictor array index definitions
#define P_X (PredPel[0])
#define P_A (PredPel[1])
#define P_B (PredPel[2])
#define P_C (PredPel[3])
#define P_D (PredPel[4])
#define P_E (PredPel[5])
#define P_F (PredPel[6])
#define P_G (PredPel[7])
#define P_H (PredPel[8])
#define P_I (PredPel[9])
#define P_J (PredPel[10])
#define P_K (PredPel[11])
#define P_L (PredPel[12])typedef unsigned char imgpel;enum {VERT_PRED            = 0,HOR_PRED             = 1,DC_PRED              = 2,DIAG_DOWN_LEFT_PRED  = 3,DIAG_DOWN_RIGHT_PRED = 4,VERT_RIGHT_PRED      = 5,HOR_DOWN_PRED        = 6,VERT_LEFT_PRED       = 7,HOR_UP_PRED          = 8
} I4x4PredModes;
/*!************************************************************************* \brief*    Vertical 4x4 Prediction*************************************************************************/
static inline void get_i4x4_vertical(imgpel **cur_pred, imgpel *PredPel)
{memcpy(cur_pred[0], &PredPel[1], BLOCK_SIZE * sizeof(imgpel));memcpy(cur_pred[1], &PredPel[1], BLOCK_SIZE * sizeof(imgpel));memcpy(cur_pred[2], &PredPel[1], BLOCK_SIZE * sizeof(imgpel));memcpy(cur_pred[3], &PredPel[1], BLOCK_SIZE * sizeof(imgpel));
}
/*!************************************************************************* \brief*    Horizontal 4x4 Prediction*************************************************************************/
static inline void get_i4x4_horizontal(imgpel **cur_pred, imgpel *PredPel)
{int i;for (i=0; i < BLOCK_SIZE; i++){cur_pred[i][0]  =cur_pred[i][1]  =cur_pred[i][2]  =cur_pred[i][3]  = (imgpel) (&P_I)[i];}
}/*!************************************************************************* \brief*    DC 4x4 Prediction*************************************************************************/
static inline void get_i4x4_dc(imgpel **cur_pred, imgpel *PredPel, int left_available, int up_available)
{int i, j, s0 = 0;if (up_available && left_available){// no edges0 = (P_A + P_B + P_C + P_D + P_I + P_J + P_K + P_L + 4) >> (BLOCK_SHIFT + 1);}else if (!up_available && left_available){// upper edges0 = (P_I + P_J + P_K + P_L + 2) >> BLOCK_SHIFT;;}else if (up_available && !left_available){// left edges0 = (P_A + P_B + P_C + P_D + 2) >> BLOCK_SHIFT;}else //if (!up_available && !left_available){// top left corner, nothing to predict froms0 = P_A; // P_A already set to p_Vid->dc_pred_value;}for (j=0; j < BLOCK_SIZE; j++){for (i=0; i < BLOCK_SIZE; i++)cur_pred[j][i] = (imgpel) s0;}
}void get_intrapred_4x4(imgpel *PredPel, imgpel ***curr_mpr_4x4, int i4x4_mode,  int left_available, int up_available)
{switch (i4x4_mode){case VERT_PRED :get_i4x4_vertical(curr_mpr_4x4[VERT_PRED], PredPel);break;case HOR_PRED :get_i4x4_horizontal(curr_mpr_4x4[HOR_PRED], PredPel);break;case DC_PRED :get_i4x4_dc(curr_mpr_4x4[DC_PRED], PredPel, left_available, up_available);break;case DIAG_DOWN_LEFT_PRED :get_i4x4_downleft(curr_mpr_4x4[DIAG_DOWN_LEFT_PRED], PredPel);break;case DIAG_DOWN_RIGHT_PRED :get_i4x4_downright(curr_mpr_4x4[DIAG_DOWN_RIGHT_PRED], PredPel);break;case VERT_RIGHT_PRED :get_i4x4_vertright(curr_mpr_4x4[VERT_RIGHT_PRED], PredPel);break;case HOR_DOWN_PRED :get_i4x4_hordown(curr_mpr_4x4[HOR_DOWN_PRED], PredPel);break;case VERT_LEFT_PRED :get_i4x4_vertleft(curr_mpr_4x4[VERT_LEFT_PRED], PredPel);break;case HOR_UP_PRED :get_i4x4_horup(curr_mpr_4x4[HOR_UP_PRED], PredPel);break;default:printf("invalid prediction mode \n");break;}
}

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

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

相关文章

Godot入门 04平台设计

新建创景&#xff0c;添加AnimatableBody2D节点。 添加Sprite2D节点 拖动图片 剪裁图片&#xff0c;吸附模式&#xff1a;像素吸附 添加CollisionShape2D&#xff0c;设置实际形状为矩形 重命名AnimatableBody2D节点为Platform&#xff0c;保存场景&#xff0c;拖动platform场景…

C#初级——条件判断语句、循环语句和运算符

条件判断语句 简单的条件判断语句&#xff0c;if()里面进行条件判断&#xff0c;如果条件判断正确就执行语句块1&#xff0c;如果不符合就执行语句块2。 if (条件判断) { 语句块1 } else { 语句块2 } int age 18;if (age < 18){Console.WriteLine("未…

深入理解 Java 虚拟机第三版(周志明)

这次社招选的这本作为 JVM 资料查阅&#xff0c;记录一些重点 1. 虚拟机历史 Sun Classic VM &#xff1a;已退休 HotSpot VM&#xff1a;主流虚拟机&#xff0c;热点代码探测技术 Mobile / Embedded VM &#xff1a;移动端、嵌入式使用的虚拟机 2.2 运行时数据区域 程序计…

软件测试20个基础面试题及答案

什么是软件测试&#xff1f; 答案&#xff1a;软件测试是指在预定的环境中运行程序&#xff0c;为了发现软件存在的错误、缺陷以及其他不符合要求的行为的过程。 软件测试的目的是什么&#xff1f; 答案&#xff1a;软件测试的主要目的是保证软件的质量&#xff0c;并尽可能…

“消费增值风暴:百万业绩背后的创新电商模式“

今日&#xff0c;我怀着无比激动的心情&#xff0c;向您揭示一个激励人心的成长篇章。我们的战略伙伴在短短一个月内&#xff0c;业绩如火箭般攀升&#xff0c;成功跨越百万销售额大关&#xff0c;同时&#xff0c;其用户活跃度居高不下&#xff0c;日均在线用户数稳稳占据8至1…

[Unity] ShaderGraph实现镜头加速线/残血效果 URP

效果如下所示&#xff1a;残血状态时&#xff0c;画面会压暗角&#xff0c;并出现速度线营造紧迫感。 使用到的素材如下&#xff0c;换别的当然也可以。[这是张白色的png放射图&#xff0c;并非皇帝的新图hhh] 这个效果的实现逻辑&#xff0c;其实就是利用time向圆心做透明度的…

HAL库源码移植与使用之低功耗模式

低功耗特性对用电池供电的产品&#xff1a; 更小电池体积&#xff08;降低了大小和成本&#xff09; 延长电池寿命 电磁干扰更小&#xff0c;提高无线通信质量 电源设计更简单&#xff0c;无需过多考虑散热问题 电源供电区分为&#xff1a; 分为VDD供电区…

友思特应用 | 硅片上的光影贴合:UV-LED曝光系统在晶圆边缘曝光中的高效应用

导读 晶圆边缘曝光是帮助减少晶圆涂布过程中多余的光刻胶对电子器件影响的重要步骤。友思特 ALE/1 和 ALE/3 UV-LED 高性能点光源&#xff0c;作为唯一可用于宽带晶圆边缘曝光的 i、h 和 g 线的 LED 解决方案&#xff0c;可高效实现WEE系统设计和曝光需求。 晶圆边缘曝光及处…

分布式相关理论详解

目录 1.绪论 2.什么是分布式系统&#xff0c;和集群的区别 3.CAP理论 3.1 什么是CAP理论 3.2 一致性 3.2.1 计算机的一致性说明 1.事务中的一致性 2.并发场景下的一致性 3.分布式场景下的一致性 3.2.2 一致性分类 3.2.3 强一致性 1.线性一致性 a) 定义 a) Raft算法…

通过ATS软件抓取ios手机日志方法记录

1.ios手机下载描述符文件&#xff0c;用于过检测 下载网址&#xff1a;https://developer.apple.com/bug-reporting/profiles-and-logs/?nameB 点击这个下载&#xff0c;之后在手机通用-VPN与设备管理里面找到刚才下载的描述文件然后安装&#xff1b; 2024.6月后注意会提示描…

springcloud RocketMQ 客户端是怎么走到消费业务逻辑的 - debug step by step

springcloud RocketMQ &#xff0c;一个mq消息发送后&#xff0c;客户端是怎么一步步拿到消息去消费的&#xff1f;我们要从代码层面探究这个问题。 找的流程图&#xff0c;有待考究。 以下我们开始debug&#xff1a; 拉取数据的线程&#xff1a; PullMessageService.java 本…

Linux构建远程YUM仓库与NFS共享存储服务

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

YOLOX+PyQt5交通路口智能监测平台设计与实现

1.概述 交通要道的路口上人车穿行&#xff0c;特别是上下班早高峰&#xff0c;且时常发生交通事故。因此对交通路口的车流量和人流量的监测必不可少。 2.检测模型 使用的检测模型为YOLOX模型&#xff0c;模型权重为训练VOC数据集得来&#xff0c;其中包括了二十个类别&#…

Vue3二次封装axios

官网: https://www.axios-http.cn/docs/interceptors steps1: 安装 npm install axios -ssteps2: /src/api/request.js 文件 >>> 拦截器 import axios from axios // 如果没用element-plus就不引入 import { ElMessage } from element-plusconst service axios.cre…

【区块链+绿色低碳】基于区块链的双碳能源纳管平台 | FISCO BCOS应用案例

在双碳战略的指导下&#xff0c;南京区块链产业应用协会牵头研发的双碳能源纳管平台&#xff0c;依托区块链、人工智能、云计算、 物联网、大数据、工业互联网与边缘计算等技术&#xff0c;对绿电追溯、需求侧响应、能源微网、源网荷储、隔墙用电、 碳排放权认证、额度计量、预…

循环队列的实现【C语言】

用数组实现循环队列 题目&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09; 分析 循环队列&#xff0c;队列满则不能再插入数据&#xff0c;队列为空则不能再出数据。 多开一个空间方便区分队列为空和队列为满的情况。 如果要存K个数据只开K个空间&a…

【在排序数组中查找元素的第一个和最后一个位置】python刷题记录

R2-分治 有点easy的感觉&#xff0c;感觉能用哈希表 class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:nlen(nums)dictdefaultdict(list)#初始赋值哈希表&#xff0c;记录出现次数for num in nums:if not dict[num]:dict[num]1else:dict[…

【C++】C++应用案例-翻转数组

翻转数组&#xff0c;就是要把数组中元素的顺序全部反过来。比如一个数组{1,2,3,4,5,6,7,8}&#xff0c;翻转之后就是{8,7,6,5,4,3,2,1}。 &#xff08;1&#xff09;另外创建数组&#xff0c;反向填入元素 数组是将元素按照顺序依次存放的&#xff0c;长度固定。所以如果想要…

基因组挖掘指导天然药物分子的发现-文献精读34

基因组挖掘指导天然药物分子的发现 摘要 天然产物是临床药物的主要来源&#xff0c;也是新药研发过程中先导化合物结构设计和优化的灵感源泉。但传统策略天然药源分子的发现却遭遇了瓶颈&#xff0c;新颖天然产物的数量逐渐无法满足现代药物开发的需求和应对全球多药耐药的威胁…

【每日刷题】Day86

【每日刷题】Day86 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 2. 数组中出现次数超过一半的数字_牛客题霸…