图像视频旋转裁剪缩放操作说明
如果你遇到视频图像拉伸、变形,此文能告诉你原因。
在整个引擎的流程中,主要在三处会对图像做一些处理:
采集端,即从摄像头出来的时候;
编码端,视频源在进入编码器的时候;
显示端,即本地显示的时候或者对方解码后显示的时候。
在这三处发生的处理大概是三种操作:a.旋转;b.裁剪;c.缩放。
采集端只可能发生操作 a.旋转;
编码端和显示端行为类似,可能发 生操作 b.裁剪和 c.缩放。
采集端出来的图像可能带有旋转信息。旋转操作不损失图像内容, 只是方向变化。
如下图,640x480的图像顺时针旋转90度后变成480x640,图像大小并没有变化。图像旋转的角度并没有固定,但根据摄像头的物理信息,旋转角度只能是90度的倍数。
1.png
编码端和显示端行为类似,下面以编码端为例描述发生在这里的操作。
对编码端而言,它的输入是某个分辨率的图像/视频。这些分辨率可能多种多样,我们以宽高比来划分分辨率种类。例如
16:9 的图像/视频可能有1280x720,640x360,320x180,160x90等等不同的实际分辨率;
4:3 的图像/视频可能有 1280x960,640x480, 320x240 等等不同的实际分辨率。
当编码器要求的分辨率和送入它的分辨率不同的时候,就要求对输入的图像/视频做处理。编码端的图像操作可以分别两步:裁剪,缩放。
第一步,裁剪。
裁剪是在原图上截取一部分,能满足目标分辨率的宽高比,同时尽可能多的保留原图像内容。注意,对于不同的分辨率宽高比,为了方便比较,我们可以把它们“归一化”表达。例如宽高比 16:9,4:3,16:10,17:10 以及 5:3,可以统一表达成 16:9, 16:12,,16:10,,16:9.4 以及 16:9.8。
假设输入的宽高比是 16:10,那么所有可能的输出宽高比,除了 16:10 以外可以分成两类,第一类 是 16:9,16:9.4 和 16:9.8;第二类是 16:12。假如输出宽高比也是 16:10,那么原图像不需要任何处理。假如输出宽高比是第一类,
以 16:9 为例,下图展示了其裁剪过程,图像上下会有部分内容被剪掉。
2.png
假如输出宽高比是第二类,以 16:12 为例,下图展示了其裁剪过程, 图像左右会有部分内容被剪掉。
3.png
第二步,缩放。
经过第一步裁剪得到的图像,其宽高比已经和目标分辨率的宽高比匹配。在此基础上,如果实际分辨率大小也一样则不需要缩放;如果实际分辨率大小不同则需要放大或者缩小。下图 “缩放 A”以 16:9 的宽高比为例,展示了目标分辨率比输入分辨率小 的时候所需要的缩小处理。
4.png
下图“缩放 B” 以 16:9 的宽高比为例,展示了目标分辨率比输入分辨率大的时候所需要的放大处理。
5.png
综上,对于编码器而言,假如其输入的分辨率为 640x360 而编码器想要的分辨率为 640x480。这时,首先需要按照 4:3 的宽高比把 640x360 图像裁剪成 480x360,再将 480x360 图像放大 1.33 倍至 640x480。 显示端作为一个独立的单元,其行为和编码器类似,如果显示窗口的分辨率和解码后送过来的视频分辨率不一致,也需要经过上述裁剪和缩放的处理。
如果是手机的摄像头,拍出来的视频是90度(或者270度)旋转的。先确定是否需要设置 PreRotation:如果没有涉及到 RTMP 推流, PreRotation=false;否则 PreRotation=true。然后确定编码分辨率: 如果 PreRotation==true,设置成 480x640;否则设置成 640x480。
如果是 PC/Mac,拍出来的视频是0度的。PreRotation设置为false, 编码分辨率设置为640x480是最佳的。
6.png
7.png