帧边界识别简介

转载至:http://blog.youkuaiyun.com/asddg67/article/details/4017251

H.264 将构成一帧图像所有nalu 的集合称为一个AU,帧边界识别实际上就是识别AU。因为H.264 取消帧级语法,所以无法简单地从码流中获取AU。解码器只有在解码的过

程中,通过某些语法元素的组合才能判断一帧图像是否结束。一般来说,解码器必须在完成一帧新图像的第一个slice_header 语法解码之后,才能知道前一帧图像已经结束。

因此,最严谨的AU 识别步骤如下:

步骤 1 对码流实施“去03 处理”。

步骤 2 解析nalu 语法。

步骤 3 解析slice_header 语法。

步骤 4 综合判断前后两个nalu 以及对应的slice_header 中的若干个语法元素,看是否发生变化。

如果发生变化,则说明这两个nalu 属于不同的帧,否则说明这两个nalu 属于同一帧。

----结束

显然,在解码前完成上述的AU 识别消耗许多CPU 资源,因此不推荐使用AU 方式解码


为了提供一种简单的AU 识别方案,H.264 规定一种类型为09 的nalu,即编码器在每次完成一个AU 编码后,在码流中插入一个类型为09 的nalu,在这个前提下,解码器只需要从码流中搜索类型为09 的nalu 即可获得一个AU。

H.264 并不强制要求编码器插入类型为09 的nalu,因此并非所有的码流都具备这种特征。对于编码器和解码器协同工作的应用场景,建议让编码器插入类型为09 的nalu,这样可以降低解码器识别AU 的代价。

为了降低解码器在解码前识别AU 的代价,本文提出一种高效的AU 识别方法,其主要思路是利用一帧图像的第一个slice_header 中的语法元素first_mb_in_slice 一般等于0 这

个特征(对于包含ASO 或者FMO 特性的码流,这个条件不一定成立)。


typedef struct ParseContext

{
    unsigned int FrameStartFound; 
    unsigned int iFrameLength; 
} ParseContext;

signed int  DecLoadAU(unsigned char* pStream, unsigned int iStreamLen, ParseContext *pc)
 {
        unsigned int i;
        unsigned int state = 0xffffffff;
        if( NULL == pStream )
        {
            return -1;
        }
        for( i = 0; i < iStreamLen; i++)
        {
            /* 查找nal类型为1和5的nal头 */
            if( (state & 0xFFFFFF1F) == 0x101 || (state & 0xFFFFFF1F) == 0x105 )
            {
                if (i >= iStreamLen) /* 到达Buffer尾部,退出查找循环 */
                {
                    break;
                }

              if( pStream[i] & 0x80) /* 查找first_mb_in_slice为0的slice头确定一幅图像的开始 */
                {
                    if(pc->FrameStartFound) /* 查找到下一幅图像的开始就可以确定图像的起始和结束 */
                    {
                        pc->iFrameLength = i - 4;
                        pc->FrameStartFound = 0;
                        state = 0xffffffff;
                        return 0; /* 找到一幅图像的边界返回0 */
                    }
                    else
                    {
                        pc->FrameStartFound = 1;
                    }
                }
            }
            if (i < iStreamLen)
            {
                state = (state << 8) | pStream[i]; /* 从码流Buffer中读入1个字节 */
            }
        }
        pc->FrameStartFound = 0;
        return -1; /* 没有找到AU边界返回-1 */
    }




### 边界识别算法原理 边界识别通常是指检测图像或视频中的物体边缘,这是计算机视觉领域的一个重要组成部分。边界识别能够帮助区分前景对象与背景,在人脸识别和手势识别等领域具有广泛应用。 对于边界识别而言,核心在于通过特定算法定位并提取目标区域的轮廓线。常用的技术包括但不限于Canny边缘检测器、Sobel滤波器以及Laplacian算子等[^1]。 #### Canny边缘检测器 Canny边缘检测是一种多级处理流程,旨在寻找强度变化显著的位置作为潜在边界的指示符。该方法首先应用高斯平滑减少噪声干扰;接着计算梯度幅值和方向用于定位最大变化率所在之处;再者采用非极大抑制技术保留局部峰值响应;最后利用双阈值机制筛选最终输出结果。 ```python import cv2 import numpy as np def canny_edge_detection(image_path): image = cv2.imread(image_path, 0) # 应用高斯模糊去除噪音 blurred_image = cv2.GaussianBlur(image, (5, 5), 0) # 使用Canny算法进行边缘检测 edges = cv2.Canny(blurred_image, threshold1=50, threshold2=150) return edges ``` #### Sobel滤波器 Sobel算子主要用于增强水平或垂直方向上的边缘特征。它基于卷积操作完成对输入信号的空间微分估计,从而突出显示那些灰度急剧转变的地方。此过程有助于后续分析任务更好地理解场景结构特性。 ```python from scipy import ndimage import matplotlib.pyplot as plt def sobel_filter(image_path): image = plt.imread(image_path, format='jpg') gray = rgb2gray(image) # 假设有一个rgb2gray函数 # 定义sobel核 sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]) sobel_y = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]) # 对图像分别沿X轴Y轴做卷积运算 grad_x = ndimage.convolve(gray, sobel_x) grad_y = ndimage.convolve(gray, sobel_y) magnitude = np.sqrt(grad_x ** 2 + grad_y ** 2) return magnitude ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值