具体实施方式
针对上述现有技术存在的缺陷,本发明实施例提出了一种基于多子图的编解码方案。在编码过程中,将全景图分割成多个子图(如图1所示,全景图被分割成0~7共8个子图),并对各子图分别进行编码。在对全景图中的子图进行编码的过程中,对于该子图的边界宏块,若存在边界邻域子图且该边界邻域子图已经编码完毕,则利用该边界邻域子图的编码结果对当前编码子图的边界宏块进行运动估计和补偿,以替代现有技术中采用通过边界扩展进行运动估计和补偿的方式;若当前编码子图不存在边界邻域子图(如图1中的深色区域为全景图的扩展边界部分),或者虽然存在边界邻域子图但该边界邻域子图还未编码完毕,则仍通过边界扩展方式进行运动估计和补偿。同理,在解码过程中,对每个子图分别进行解码。在对全景图中的子图进行解码的过程中,对于该子图的边界宏块,若存在边界邻域子图且该邻域子图已经解码完毕,则利用该边界邻域子图的解码结果对当前解码子图的边界宏块进行运动估计和补偿,以替代现有技术中采用通过边界扩展进行运动估计和补偿的方式;若当前解码子图不存在边界邻域子图,或者虽然存在边界邻域子图但该边界邻域子图还未解码完毕,则仍通过边界扩展方式进行运动估计和补偿。可以看出,本发明实施例通过利用已经编/解码的子图边界,充分利用相关性来提升编/解码效率。
下面结合附图对本发明实施例进行详细描述。
参见图2,为本发明实施例提供的基于多子图的视频编码流程总体示意图,如图所示,当需要对全景图进行编码时,该流程可包括:
步骤201,将全景图分割为N(N>1)个子图,并为各子图设置编码顺序。
在实施时,可分别为全景图中的各子图定义一个编码顺序标识view_id,以便用来表示各子图在编码过程和解码过程中的先后处理顺序,其中,本发明实施例将顺序定义中的首个编码图像称为基准图像(anchor image)。该顺序将 直接影响到各子图边界的运动估计和运动补偿的边界预测依赖关系。该顺序可依据实际应用情况进行定义。比如可根据视频图像场景进行定义,通常将中间部分的子图定义为基准图像,具体的,当在子图结构为单排结构时,将位于中间的子图定义为基准图像,在子图结构为双排结构时,将上排中间位置的子图定义为基准图像,在子图结构为多排结构时,将中间排的中间位置的子图定义为基准图像。
各子图的位置可使用空间坐标表示。本发明实施例所使用的坐标系,其原点为视频图像的左上角,并以子图为单位,横向方向向右为正方向,纵向方向向下为正方向。
步骤202,按照设置的编码顺序分别对各子图进行编码,在编码过程中需要参考临近宏块对当前编码宏块进行运动估计和运动补偿。其中,对于当前编码的子图,在对子图边界宏块进行运动估计和补偿时,若存在边界邻域子图(即边界相邻的子图)并且该边界邻域子图已经编码完成,则利用该边界邻域子图的编码结果对当前编码子图的边界宏块进行运动估计和补偿;若不存在边界邻域子图,或者虽然存在边界邻域子图,但该边界邻域子图未编码完成,则仍采用现有方式对当前编码子图的边界宏块进行运动估计和补偿,如通过边界扩展重构图像的方式进行运动估计和补偿。
在实施时,对编码顺序中的首个子图进行编码时,由于其它子图都还没有编码,故该首个子图的边界采用常规的边界扩展算法进行扩展。对非首个子图进行编码时,如果其中某个边界存在边界邻域子图且该边界邻域子图已经编码完毕,则在对当前编码子图的边界宏块进行编码时,无需进行边界扩展,而是参考该已编码完成的边界邻域子图的边界宏块进行运动估计和补偿。
步骤203,将各子图的编码顺序信息和各子图的边界预测依赖关系信息添加到编码后的码流中。
在实施时,为了保证解码端能够在解码前获取到各子图的解码顺序和边界预测依赖关系,可将各子图的编码顺序信息和各子图的位置信息添加到首个编 码子图的码流负荷之前。这样,解码端可在接收到首个子图的码流后,获取其中携带的各子图的编码顺序信息和各子图在视频图像中的位置信息,并进而可以计算得出各子图的边界预测依赖关系,即各子图的边界宏块是否是根据边界邻域子图的编码数据得到的,以及哪些边界根据哪些边界邻域子图的编码数据得到的。进一步的,还可以将用来对当前子图的边界宏块进行运动估计和补偿的边界邻域子图数量信息,以及这些边界邻域子图相对于当前子图的方向信息添加到当前子图编码后的码流负荷之前。这样,解码端在收到相应子图的码流后,就可以直接从码流前部获取到该子图的边界预测依赖关系,省去了计算子图边界预测依赖关系的处理过程,进一步提高了解码效率。
对应于图2所示的视频编码流程,其视频解码流程可如图3所示,包括:
步骤301,接收待解码视频图像的各子图的码流,获取其中携带的各子图的编码顺序信息和各子图的边界预测依赖关系信息。
步骤302,按照各子图的编码顺序分别对给子图进行解码,在解码过程中需要参考临近宏块对当前编码宏块进行运动估计和运动补偿。其中,对于当前解码子图,在对子图边界宏块进行运动估计和补偿时,若存在边界邻域子图(即与当前子图有边界预测依赖关系的子图)并且该边界邻域子图已经解码完成,则利用该边界邻域子图的解码结果对当前解码子图的边界进行运动估计和补偿;若不存在边界邻域子图,或者存在边界邻域子图但该边界邻域子图未解码完成,则仍采用现有方式对当前解码子图的边界宏块进行运动估计和补偿,如通过边界扩展重构图像。
在实施时,与图2所示编码过程对应,当对编码顺序中的首个子图进行解码时,由于其它子图都还没有解码,故该首个子图的边界采用常规的边界扩展算法进行扩展。对非首个子图进行解码时,如果其中某个边界存在邻域子图(即与当前子图有边界预测依赖关系的子图)且该邻域子图已经解码完毕,则在对当前解码子图的边界宏块进行解码时,无需进行边界扩展,而是参考该已解码完成的边界邻域子图的边界宏块进行运动估计和补偿。
步骤303,根据各子图在视频图像中的位置信息,对解码后的各子图进行拼接,从而拼接得到完整的视频图像。
以上图2所示流程可通过前端编码器实现,图3所示流程可通过解码器实现。如当视频监控客户端请求实时调阅视频监控数据时,前端编码器将按照图2所示流程编码处理后的视频监控数据发送给解码器进行解码。其中,编码器在将编码后的视频监控数据发送给解码器时,由于某些子图的码流是根据其边界邻域子图的码流编码得到的,因此为了保证正常解码,最好按照各子图编码的先后顺序,将各子图的码流发送给解码器。
在对子图进行运动估计和补偿时,采用常规的边界扩展算法的一种具体实现是:将该子图内的部分图像数据(如宏块)复制后作为边界的外围扩展部分,并以这些复制图像数据作为参考数据对该子图边界宏块进行运动估计和补偿。本发明实施例中,在对当前子图进行编码时,如果该子图的某个边界邻域子图已经编码完成,则解码该已编码完成的子图的编码码流并重构得到相应边界的宏块,然后以重构得到的该边界宏块作为当前子图边界的扩展,对当前子图进行运动估计和补偿。解码过程与编码过程类似。
通过上述现有技术与本发明实施例的对比可见,一方面,本发明实施例利用全景图中的各子图的邻域子图存在性,由邻域子图边界宏块取代当前子图的扩展边界进行运动估计和运动补偿,提高了编码效率,降低编码器设计复杂度。另一方面,由邻域子图边界宏块进行运动估计和运动补偿,相比于采用边界扩展方式进行运动估计和运动补偿,所得到的编码结果更接近于真实图像,因而图像失真度会有所下降。
由于各个子图独立编码,只涉及到子图边界内存的同步问题,因此相比于现有技术中的方案一,复杂度大大简化。又由于本发明实施例充分利用了相邻子图像边界的空间相关性,因此相比于现有技术中的方案二,提高了编码效率。
下面结合图4所示的子图划分方式,分别对图2和图3所示的视频编解码流程进行详细描述。
如图4所示,待编码的全景图被分割为6个子图,各子图的坐标如图所示。各子图设置有编码顺序标识view_id,view_id的取值从0开始并按照编码顺序从前到后依次递增。其中,基准图像(view_id=0)的空间坐标为(1,1)。
在编码过程中,按照view_id递增的顺序分别对相应子图进行编码。其中:
在对view_id=0的首个子图编码时,由于其它子图都还没有编码,故该首个子图的边界采用常规的边界扩展算法进行扩展,如图5中的(A)所示;
在对view_id=1的第二个子图像编码时,由于只有其下方子图(view_id=0)已经编码完毕,因而下方边界不用进行扩展,运动估计和运动补偿时直接参考下方view_id=0的子图的上边界宏块编码结果。其中,左边、右边边界的相邻子图还未编码,需要进行边界扩展。上方边界为全景图边界,也需要进行边界扩展,如图5中的(B)所示;
在对view_id=2的第三个子图编码时,由于只有右边子图(view_id=0)已经编码完成,因而运动估计和运动补偿时直接参考右侧view_id=0的子图的左边界宏块编码结果。上方边界的相邻子图还未编码,需要进行边界扩展,其左边界和下边界为全景图边界,也需要进行边界扩展,如图5中的(C)所示;
在对view_id=3的第四个子图编码时,由于只有左边子图(view_id=0)已经编码完成,因而运动估计和运动补偿时直接参考view_id=0的子图的右边界宏块编码结果。其上方边界的相邻子图还未编码,需要进行边界扩展。右边界和下边界为全景图边界,也需要进行边界扩展,如图5中的(D)所示;
在对view_id=4的第五个子图编码时,其下方边界的相邻子图(view_id=2)和右方边界的相邻子图(view_id=1)均已经编码完成,因而不需要边界扩展。其上边界和左边界为全景图边界,需要进行边界扩展,如图5中的(E)所示;
在对view_id=5的第六个子图编码时,由于其左方边界的相邻子图(view_id=1)和下方边界的相邻子图(view_id=3)均已解码重构,不需要边界扩展。右边界和上边界为全景图边界,需要进行边界扩展,如图5中的(F)所示。
在解码过程中,按照view_id递增的顺序分别对相应子图进行解码。其中:
在对view_id=0的首个子图解码时,由于其它子图都还没有解码重构,故其边界采用常规的边界扩展算法进行扩展,如图5中的(A)所示;
在对view_id=1的第二个子图解码时,由于只有其下方子图(view_id=0)已经解码完毕,因而下方边界不用进行扩展,运动估计和运动补偿时直接参考下方view_id=0的子图解码重构图像。其中,左边、右边边界的相邻子图还未解码,需要进行边界扩展。上方边界为全景图边界,也需要进行边界扩展,如图5中的(B)所示;
在对view_id=2的第三个子图解码时,由于只有右边子图(view_id=0)存在重构图像,运动估计和运动补偿时直接参考下方子图(view_id=0)的左侧边界宏块的解码重构结果。上方边界的相邻子图(view_id=4)还未解码重构,需要进行边界扩展,其左边界和下边界为全景图边界,需要进行边界扩展,如图5中的(C)所示;
在对view_id=3的第四个子图解码时,由于只有左边子图(view_id=0)已经解码重构,因而运动估计和运动补偿时直接参考view_id=0的子图的右边界宏块编码结果。其上方边界的相邻子图(view_id=5)还未解码重构,因而需要边界扩展。右边界和下边界为全景图边界,也需要进行边界扩展,如图5中的(D)所示;
在对view_id=4的第五个子图解码时,由于其下方边界的相邻子图(view_id=2)和右方边界的相邻子图(view_id=1)均已经解码重构,不需要边界扩展。其上边界和左边界为全景图边界,需要进行边界扩展,如图5中的(E)所示;
在对view_id=5的第六个子图解码时,由于其左方边界的相邻子图(view_id=1)和下方边界的相邻子图(view_id=3)均已解码重构,不需要边界扩展。右边界和上边界为全景图边界,需要进行边界扩展,如图5中的(F)所示。
本发明实施例可通过定义新的码流语法或者扩展现有协议,以实现子图的编码顺序和边界预测相关信息的传输,即在码流中携带各子图的编码顺序和边界预测依赖信息。
以视频编解码采用H.264协议为例,为了使用子图边界相关性,取消边界扩展操作,本发明实施例对H.264码流语法进行了扩展。在兼容H.264标准的前提下,本发明实施例扩展出一种H.264标准未定义的NAL(Network Abstraction Layer,网络提取层)单元(NAL Unit,NALU)来标识这种边界预测的相关性。具体的,通过使用H.264标准未定义的一种NALU,封装内容为bound_dependency_rbsp,来传输全景图中当前子图依赖的邻域子图边界的存在性及其属性。
该NALU头部的语法元素取值可参考ITU-T H.264,其中:
forbidden_zero_bit取值0(H.264规范中规定了这一位必须为0);
nal_ref_idc取值为1(该参数取值可参照现有H.264规范中的规定);
nal_unit_type取值为29,该值为H.264标准未定义值(Unspecified)。为了避免和标准中已经定义值和保留值冲突,可取标准中未定义区间([24,31])内的值。
本发明实施例定义的bound_dependency_rbsp内容可如表1所示。其中,bound_dependency_rbsp内部封装的是子图的边界预测相关信息的内容bound_dependency_data(),具体格式可如表2所示。rbsp_trailing_bits()定义、C的定义、Descriptor的具体含义可参考ITU-T H.264。
表1、bound_dependency_rbsp语法
bound_dependency_rbsp(){
|
C |
Descriptor |
bound_dependency_data()
|
0 |
|
rbsp_trailing_bits()
|
0 |
|
} |
|
|
表2、bound_dependency_data语法
bound_dependency_data(){ |
C |
Descriptor |
pano_view_seq_param_set_flag
|
0 |
u(1) |
pic_view_param_set_flag
|
0 |
u(1) |
if(pano_view_seq_param_set_flag==1){ |
|
|
pano_view_width_mbs_minus1
|
0 |
ue(v) |
pano_view_height_mbs_minus1
|
0 |
ue(v) |
pano_num_view_minus1
|
0 |
ue(v) |
for(i=0;i<pano_num_view_minus1+1;i++){ |
|
|
pic_view_id[i]
|
0 |
ue(v) |
pic_view_x[i]
|
0 |
ue(v) |
pic_view_y[i]
|
0 |
ue(v) |
pic_view_width_4x4blks_minus1[i]
|
0 |
ue(v) |
pic_view_height_4x4blks_minus1[i]
|
0 |
ue(v) |
} |
|
|
anchor_x
|
0 |
ue(v) |
anchor_y
|
0 |
ue(v) |
} |
|
|
if(pic_view_param_set_flag==1){ |
|
|
cur_pic_view_id
|
2 |
ue(v) |
num_dependency
|
2 |
ue(v) |
for(i=0;i<num_dependency;i++){ |
|
|
dependency_direction[i]
|
2 |
ue(v) |
} |
|
|
} |
|
|
} |
|
|
以下为bound_dependency_data()中的各个语法元素的具体语义:
pano_view_seq_param_set_flag:1比特标记位。1:标记存在全景图像序列层参数集。0:不存在序列层参数集。建议将SPS(序列的参数集)和PPS(图像的参数集)之后的nal_unit_type值为29的NALU的pano_view_seq_param_set_flag设置为1。
pic_view_param_set_flag:1比特标记位。1:标记存在全景子图像层参数。建议将每个子图slice前的nal_unit_type值为29的NALU的pic_view_param_set_flag设置为1。
pano_view_width_mbs_minus1:全景图像以宏块为单位的宽度减1。即:
全景图像宏块宽度=panoramic_view_width_mbs_minus1+1。
pano_view_height_mbs_minus1:全景图像以宏块为单位的高度减1。即:
全景图像宏块高度=pano_view_height_mbs_minus1+1。
pano_num_view_minus1:num_view_minus1加1等于全景图像包含的子图像数目。即:全景图像子图像数目=pano_num_view_minus1+1。
pano_num_view_minus1最小取值0,最大值为31。
pic_view_id[i]:全景图中的第i个子图的view_id。
pic_view_x[i]:全景图中的第i个子图的以子图为单位的在全景图中的横坐标。左上角子图横坐标为0,向右为正方向。如图4所示。
pic_view_y[i]:全景图中的第i个子图的以子图为单位的在全景图中的纵坐标。左上角子图纵坐标为0,向下为正方向。如图4所示,图中全景图包含6个子图,坐标分别为(0,0)、(1,0)、(2,0)、(0,1)、(1,1)、(2,1)。
pic_view_width_4x4blks_minus1[i]:全景图中第i个子图亮度平面以4x4块为单位的宽度。
pic_view_height_4x4blks_minus1[i]:全景图中第i个子图亮度平面以4x4块为单位的高度。
anchor_x、anchor_y:全景图像中作为基准图像的子图在全景图中的横坐标和纵坐标。基准图像的view_id=0。在全景图像中基准图像始终是首个编码图像,即编码时基准图像的邻域宏块是不存在的,其边界宏块在进行运动估计前需要进行上下左右边界扩展操作,不能参考边界邻域子图进行运动估计。
cur_pic_view_id:当前子图的view_id。其中,view_id既可以用来标识子图,又可以用来标识子图的编码顺序。view_id越小,标识其优先级越高,即编码(解码)顺序越早。基准图像的view_id=0。
num_dependency:当前子图边界宏块运动估计和运动补偿依赖的边界子图数目。当子图某个边界不存在依赖子图时,如该子图边界同时为全景边界时,边界宏块运动补偿时需要进行边界扩展。当前子图依赖的子图在当前子图编码(解码)前已经编码(解码)完毕。
dependency_direction[i]:当前子图边界宏块运动估计和运动补偿依赖的第i个子图相对当前子图的方向。方向定义可如图6所示,其中,cur_pic为当前子图,0表示当前子图的左邻(即左侧边界的邻域子图),1表示当前子图的右邻,2表示当前子图的下邻,3表示当前子图的上邻。
包含bound_dependency_rbsp的NALU应出现在cur_view_id的子图像slice前面(多slice时,应出现在首个子图slice前面),并与slice的NALU相邻。这样解码器可以首先解码bound_dependency_rbsp的NALU,得到当前子图边界依赖关系,然后进行解码。
在实施时,可构造pano_view_seq_param_set_flag=1的NALU,并将其放在IDR(Instantaneous Decoding Refresh,即时解码刷新)/I帧图像的码流负荷前面,以及,构造pic_view_param_set_flag=1的NALU,并将其放在每个子图的码流负荷前面,从而传输这种边界依赖性。
基于相同的技术构思,本发明实施例还提供了一种编码器和解码器,可分别应用于上述流程。
参见图7,为本发明实施例提供的编码器的结构示意图,该编码器可包括:
分割模块701,用于将视频图像分割为至少2个子图;
设置模块702,用于为各子图设置编码顺序;
编码模块703,用于按照设置的编码顺序分别对各子图进行编码;其中,对于当前子图,若存在边界邻域子图并且该边界邻域子图已经完成编码,则利用该边界邻域子图的编码结果对当前子图的相应边界的宏块进行运动估计和运动补偿;以及,将各子图的编码顺序信息和各子图在所述视频图像中的位置信息添加到编码后的码流中。进一步的,在对当前子图进行编码时,若当前子图有边界不存在边界邻域子图,编码器703通过扩展当前子图的相应边界宏块进行运动估计和运动补偿。
进一步的,编码模块703可将各子图的编码顺序信息和各子图在所述视频图像中的位置信息添加到首个编码子图的码流负荷之前。进一步的,编码模块 703还可将用来对当前子图的边界宏块进行运动估计和运动补偿的边界邻域子图数量信息,以及所述边界邻域子图相对于当前子图的方向信息添加到当前子图编码后的码流负荷之前。
上述编码器还可包括传输模块704,用于在编码模块703按照设置的编码顺序分别对各子图进行编码之后,按照设置的编码顺序分别将各子图编码后的码流发送给解码端。
参见图8,为本发明实施例提供的解码器的结构示意图,该解码器可包括:
获取模块801,用于获取待解码视频图像的各子图的码流,以及码流中携带的各子图的编码顺序信息和各子图的边界预测依赖关系信息;
解码模块802,用于按照设置的编码顺序分别对各子图进行解码;其中,在对当前子图进行解码时,若存在与当前子图有边界预测依赖关系的边界邻域子图并且该边界邻域子图已经完成解码,则利用该边界邻域子图的解码结果对当前子图的相应边界的宏块进行运动估计和运动补偿;进一步的,在对当前子图进行解码时,若当前子图有边界不存在边界邻域子图,则解码模块802通过扩展当前子图的相应边界宏块进行运动估计和运动补偿
拼接模块803,用于根据各子图在所述视频图像中的位置信息,对解码后的各子图进行拼接。
进一步的,获取模块801可通过以下两种方式获取各子图的编码顺序信息和各子图的边界预测依赖关系信息:
方式一:可从首个子图的码流负荷之前的部分获取各子图的编码顺序信息和各子图在所述视频图像中的位置信息;根据各子图的编码顺序信息和各子图在所述视频图像中的位置信息,确定各子图的边界预测依赖关系。
方式二:可从首个子图的码流负荷之前的部分获取各子图的编码顺序信息和各子图在所述视频图像中的位置信息;从当前子图的码流负荷之前的部分获取用来对当前子图的边界宏块进行运动估计和运动补偿的边界邻域子图数量信息,以及所述边界邻域子图相对于当前子图的方向信息。
综上所述,本发明实施例中通过定义全景图中各个子图的空间坐标,以及定义一种编码顺序,来定义全景图中各个子图的边界依赖关系。当某一子图的某个边界存在已经解码重构子图时,该边界不再需要进行边界扩展,即可进行运动估计和运动补偿。当某个边界的相邻子图还未解码重构,或者该边界同时为全景图边界时,该边界需要进行边界扩展,然后进行运动估计和运动补偿。由于该方案各个子图编码时,只需要进行图像内存同步和码流顺序固定,不再需要各个子图编码器内部进行同步,简化了前端全景图编码器设计。使用本发明实施例,在使用多个芯片同步编码任意大尺寸的超高清全景图像时,可充分利用各个子图边界相关性,使用邻域子图代替扩展边界,进行运动估计和运动补偿,从而提升编码效率,降低前端编码器设计复杂度。
通过以上的实施方式的描述,本领域的技术人员可以清楚地了解到本发明可借助软件加必需的通用硬件平台的方式来实现,当然也可以通过硬件,但很多情况下前者是更佳的实施方式。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台终端设备(可以是手机,个人计算机,服务器,或者网络设备等)执行本发明各个实施例所述的方法。
以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视本发明的保护范围。