首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >利用swscale进行图像合成

利用swscale进行图像合成
EN

Stack Overflow用户
提问于 2018-08-11 14:15:31
回答 2查看 590关注 0票数 2

我有一个输入图像A和一个以YUV420格式存储的大小为800x600的图像B,我需要将图像A缩放到100x100大小,并在某个时候将其放置到结果图像B中(x=100,y=100)。为了减少内存和CPU的使用,我将swscale结果直接放入最终的B图像中。

下面是一个代码片段(非常简单):

代码语言:javascript
复制
//here we a creating sws context for scaling into 100x100
sws_ctx = sws_getCachedContext(sws_ctx, frame.hdr.width, frame.hdr.height, AV_PIX_FMT_YUV420P,
                               100, 100, AV_PIX_FMT_YUV420P, SWS_BILINEAR, nullptr, nullptr, nullptr);

接下来,我们创建相应的切片并大步地描述图像A。

代码语言:javascript
复制
    int src_y_plane_sz = frame.hdr.width * frame.hdr.height;
    int src_uv_plane_sz = src_y_plane_sz / 2;
    std::int32_t src_stride[] = {
        frame.hdr.width,
        frame.hdr.width / 2,
        frame.hdr.width / 2,
        0};

    const uint8_t* const src_slice[] = {
        &frame.raw_frame[0],
        &frame.raw_frame[0] + src_y_plane_sz,
        &frame.raw_frame[0] + src_y_plane_sz + src_uv_plane_sz,
        nullptr};

现在,对目标B映像执行相同的操作

代码语言:javascript
复制
    std::int32_t dst_stride[] = {
        current_frame.hdr.width,
        current_frame.hdr.width /2,
        current_frame.hdr.width /2,
        0
    };

    std::int32_t y_plane_sz = current_frame.hdr.width * current_frame.hdr.height;
    std::int32_t uv_plane_sz = y_plane_sz / 2;

    //calculate offset in slices for x=100, y=100 position
    std::int32_t y_offset = current_frame.hdr.width * 100 + 100;

    uint8_t* const dst_slice[] = {
        &current_frame.raw_frame[0] + y_offset,
        &current_frame.raw_frame[0] + y_plane_sz + y_offset / 2,
        &current_frame.raw_frame[0] + y_plane_sz + uv_plane_sz + y_offset / 2,
        nullptr};

毕竟-呼叫swscale

代码语言:javascript
复制
    int ret = sws_scale(sws_ctx, src_slice, src_stride, 0, frame.hdr.height,
                        dst_slice, dst_stride);

使用测试序列后,出现以下问题的结果无效:

  1. Y分量得到了一些填充线
  2. UV组件被错位了--它们比原来的Y组件要低一点。

有没有人在swscale函数上遇到过同样的问题?我对这个FFmpeg库集合非常陌生,所以我对如何正确执行此任务的任何意见都持开放态度。

FFmpeg版本使用3.3

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-13 14:53:00

感谢@VTT指出了可能的问题-我有固定的目标片指针计算如下:

代码语言:javascript
复制
    int dest_x = 200, dest_y = 70;

    //into 100x100 position
    std::int32_t y_offset = current_frame.hdr.width * dest_y + dest_x;
    std::int32_t u_offset = ( current_frame.hdr.width * dest_y )  / 4 + dest_x /2;
    std::int32_t v_offset = u_offset + y_plane_sz / 4;

    uint8_t* const dst_slice[] = {
        &current_frame.raw_frame[0] + y_offset,
        &current_frame.raw_frame[0] + y_plane_sz + u_offset,
        &current_frame.raw_frame[0] + y_plane_sz + v_offset,
        nullptr};

第二个问题是用尺寸因子为8来解决“线伪”问题。

对目标切片指针进行适当位置计算的另一个附加项是,必须根据当前的Y平面对y坐标进行重新调整,因为每前进两个Y步,就只有一个U或V步长。例如(请参阅adjusted_uv_y变量):

代码语言:javascript
复制
std::int32_t adjusted_uv_y = dest_y % 2 == 0 ? dest_y : dest_y - 1;
std::int32_t y_offset = current_frame.hdr.width * dest_y + dest_x;
std::int32_t u_offset = ( current_frame.hdr.width * adjusted_uv_y )  / 4 + dest_x /2;
std::int32_t v_offset = u_offset + y_plane_sz / 4;
票数 1
EN

Stack Overflow用户

发布于 2018-08-11 14:24:48

YUV420格式缩放图像的宽度和高度为2。也就是说,每个色平面比luma平面小4倍:

代码语言:javascript
复制
int src_uv_plane_sz = src_y_plane_sz / 4;

我也不确定计算出的步长值是否正确。典型的跨步。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51800507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档