ffmpeg抠图

news/2024/7/10 22:12:16 标签: ffmpeg, colorkey, chromakey, 抠图, 透明

1.不用png,用AVFrame
2.合流
3.图片抠图透明 (1.)mp4扣yuv图,(2)用1.把一张yuv标记为透明然后av_hwframe_transfer_data到GPU (3)用抠图算法函数对yuv进行处理 (4)
qsv的h264_qsv只支持nv12和qsv,但qsv本身并不限制像素格式,比如在qsv里可以用vpp_qsv=format输出各种像素格式。因此以上第二种方法可能可行。
av_hwframe_transfer_data转换不了可能是硬件帧函数配置的像素格式出的问题。

ffmpeg -y   -i TJTV.png -vf  colorkey=0x0000FF:0.5:0.0    -c:v png t.png

0x0000FF:六位每两位分别表示红绿蓝,因此它是对rgb像素进行透明标记。
0.5表示蓝色的范围容差值,范围为0.01-1,数值越大,容错越大。
0.0是alpha通道的阀值,为0表示完全透明,实测这个值作用不明显。
对于TJTV.png,可以看到它的编码和封装方式都是png,它的像素格式为rgba。

Stream #0:0: Video: png, rgba(pc), 280x279 [SAR 2835:2835 DAR
280:279], 25 fps, 25 tbr, 25 tbn

这个命令只能对rgb的像素格式进行透明标记,但是对yuv得不能,会导致花屏。只有argb、rgba等带透明度格式的像素格式才能进行抠图透明标记。
透明的原理是对rgb数据逐个像素处理,修改rgb值,达到对特定的像素进行透明标记。
透明的原理是对rgb或yuv增加第四个Alpha通道,这个通道的值由一个byte表示,不同的值表示透明程度不同,Alpha的值与其他yuv、rgb值作用来改变灰阶度来达到透明效果。
chromakeycolorkey的区别,官网给了这四个例子

ffmpeg -i input.png -vf colorkey=green out.png
ffmpeg -i background.png -i video.mp4 -filter_complex "[1:v]colorkey=0x3BBD1E:0.3:0.2[ckout];[0:v][ckout]overlay[out]" -map "[out]" output.flv
ffmpeg -i input.png -vf chromakey=green out.png
ffmpeg -f lavfi -i color=c=black:s=1280x720 -i video.mp4 -shortest -filter_complex "[1:v]chromakey=0x70de77:0.1:0.2[ckout];[0:v][ckout]overlay[out]" -map "[out]" output.mkv

clolorkey是对yuv数据进行处理,但它的三个参数值依然和colorkey同样的用法。对yuv进行透明标记后,如果再次编码,那么标记就会失效。同时如果对rtb图像进行标记后,如果转为yuv,则标记同样失效并且花屏。
以下是去除绿色背景。

在这里插入图片描述


ffmpeg -h filter=colorkey

Filter colorkey
  Turns a certain color into transparency. Operates on RGB colors.
    slice threading supported
    Inputs:
       #0: default (video)
    Outputs:
       #0: default (video)
colorkey AVOptions:
   color             <color>      ..FV.....T. set the colorkey key color (default "black")
   similarity        <float>      ..FV.....T. set the colorkey similarity value (from 1e-05 to 1) (default 0.01)
   blend             <float>      ..FV.....T. set the colorkey key blend value (from 0 to 1) (default 0)
ffmpeg -h filter=chromakey

Filter chromakey
  Turns a certain color into transparency. Operates on YUV colors.
    slice threading supported
    Inputs:
       #0: default (video)
    Outputs:
       #0: default (video)
chromakey AVOptions:
   color             <color>      ..FV.....T. set the chromakey key color (default "black")
   similarity        <float>      ..FV.....T. set the chromakey similarity value (from 1e-05 to 1) (default 0.01)
   blend             <float>      ..FV.....T. set the chromakey key blend value (from 0 to 1) (default 0)
   yuv               <boolean>    ..FV.....T. color parameter is in yuv instead of rgb (default false)

第四个参数默认为false,也就是前面传递的是grb信号值,如果为true的话,颜色传递的信号已经是YUV而不是RGB。像"green"或"red"这样的字面颜色不再有意义了。 这可以用于将精确的YUV值作为十六进制数传递。

附录:
1.ffmpeg滤镜chromakey针对yuv处理,将对应像素点标记透明

typedef struct ColorkeyContext {
    const AVClass *class;
 
    /* color offsets rgba */
    int co[4];
 
    uint8_t colorkey_rgba[4];
    float similarity;
    float blend;
} ColorkeyContext;
 
static uint8_t do_chromakey_pixel(ChromakeyContext *ctx, uint8_t u[9], uint8_t v[9])
{
    double diff = 0.0;
    int du, dv, i;

    for (i = 0; i < 9; ++i) {
        du = (int)u[i] - ctx->chromakey_uv[0];
        dv = (int)v[i] - ctx->chromakey_uv[1];

        diff += sqrt((du * du + dv * dv) / (255.0 * 255.0 * 2));
    }

    diff /= 9.0;

    if (ctx->blend > 0.0001) {
        return av_clipd((diff - ctx->similarity) / ctx->blend, 0.0, 1.0) * 255.0;
    } else {
        return (diff > ctx->similarity) ? 255 : 0;
    }
}
static int do_chromakey_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs)
{
    AVFrame *frame = arg;

    const int slice_start = (frame->height * jobnr) / nb_jobs;
    const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;

    ChromakeyContext *ctx = avctx->priv;

    int x, y, xo, yo;
    uint8_t u[9], v[9];

    memset(u, ctx->chromakey_uv[0], sizeof(u));
    memset(v, ctx->chromakey_uv[1], sizeof(v));

    for (y = slice_start; y < slice_end; ++y) 
    {
        for (x = 0; x < frame->width; ++x) 
        {
            for (yo = 0; yo < 3; ++yo) 
            {
                for (xo = 0; xo < 3; ++xo) 
                {
                    get_pixel_uv(frame, ctx->hsub_log2, ctx->vsub_log2, x + xo - 1, y + yo - 1, &u[yo * 3 + xo], &v[yo * 3 + xo]);
                }
            }

            frame->data[3][frame->linesize[3] * y + x] = do_chromakey_pixel(ctx, u, v);
        }
    }

    return 0;
}

2.ffmpeg滤镜colorkey针对rgb处理,将目标像素点设置为透明

static uint8_t do_colorkey_pixel(ColorkeyContext *ctx, uint8_t r, uint8_t g, uint8_t b)
{
    int dr = (int)r - ctx->colorkey_rgba[0];
    int dg = (int)g - ctx->colorkey_rgba[1];
    int db = (int)b - ctx->colorkey_rgba[2];

	//计算相似度
    double diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0 * 3.0));

    if (ctx->blend > 0.0001) {
        return av_clipd((diff - ctx->similarity) / ctx->blend, 0.0, 1.0) * 255.0;
    } else {
        return (diff > ctx->similarity) ? 255 : 0;
    }
}
static int do_colorkey_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs)
{
    AVFrame *frame = arg;

    const int slice_start = (frame->height * jobnr) / nb_jobs;
    const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;

    ColorkeyContext *ctx = avctx->priv;

    int o, x, y;

    for (y = slice_start; y < slice_end; ++y) {
        for (x = 0; x < frame->width; ++x) {
            o = frame->linesize[0] * y + x * 4;
			// 修改rgba a数据
            frame->data[0][o + ctx->co[3]] =
                do_colorkey_pixel(ctx,
                                  frame->data[0][o + ctx->co[0]],
                                  frame->data[0][o + ctx->co[1]],
                                  frame->data[0][o + ctx->co[2]]);
        }
    }

    return 0;
}

参考:
http://ffmpeg.org/ffmpeg-filters.html#colorkey
ffmpeg绿幕抠图原理解析

<a class=ffmpeg是音视频必备,但即使从业数年,它似乎依然有无穷的秘密,感兴趣添加笔者微信:YQW1163720468,加入ffmpeg微信群讨论。但记得备注:ffmpeg爱好者" />

ffmpeg -i 20190323162628578.png -i juren-30s.mp4 -filter_complex “[0:v]colorkey=0x00FF00:0.1:0[out];[1:v][out]overlay[re]” -map [re] -c:v h264_qsv re.mp4

转成yuv就会花屏
ffmpeg -i 20190323162628578.png  -vf  "colorkey=0x00FF00:0.5:0"      -pix_fmt yuv420p t.yuv
ffplay -video_size 146x60 -pixel_format yuv420p -i t.yuv
这样OK
ffmpeg -i 20190323162628578.png  -vf  "colorkey=0x00FF00:0.5:0"     t.png
ffplay t.png
这样OK
ffmpeg -i 20190323162628578.png  -vf  "colorkey=0x00FF00:0.5:0"      -pix_fmt yuva420p t.yuv
ffplay -video_size 146x60 -pixel_format yuva420p -i t.yuv
palettegen滤镜也可以设置透明ffmpeg -i "./了不起\3D%02d.png" -filter_complex "[0:v]scale=700:700:force_original_aspect_ratio=decrease,format=rgba,fps=25,split[v0][v1];[v0]palettegen=reserve_transparent=on:transparency_color=00000000[v];[v1][v]paletteuse" -y 了不起.gif

http://www.niftyadmin.cn/n/5037296.html

相关文章

讨论问题--数据类型、数组、传值/址API函数等

前言 数据类型是编程语言中用于表示数据的分类。常见的数据类型包括整数、浮点数、字符串、布尔值等。数据类型决定了变量能存储的值的种类和范围。 数组是一种存储多个相同类型数据的数据结构。它通过索引来访问并操作其中的元素。数组在内存中是连续存储的&#xff0c;可以…

CentOS服务器利用docker搭建中间件命令集合

一、挂载服务器磁盘 #挂盘语句 fdisk /dev/vdb 在分别输入n、p、1、2048、1048575999、w mkfs.ext4 /dev/vdb mkdir /data echo /dev/vdb /data ext4 defaults 0 0 >> /etc/fstab mount -a df -hfirewall-cmd --zonepublic --add-port8002/tcp --permanent firewall-c…

linux 文件实时同步 rsync + lsyncd

Centos7.x部署lsyncd和rsync实现文件的实时同步

【数据结构】—从直接插入排序升级到希尔排序究极详解(含C语言实现)

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f525;这就不得不推荐此专栏了&#xff1a;C语言 ♈️今日夜电波&#xff1a;透明で透き通って何にでもなれそうで—HaKU 2:05 ━━━━━━️&#x1f49f;──────── 5:38 …

C++中按引用传递参数

C中按引用传递参数 实参通常是通过值传递给函数的&#xff0c;这意味着形参接收的只是发送给它们的值的副本&#xff0c;它们存储在函数的本地内存中。对形参值进行的任何更改都不会影响原始实参的值。 然而&#xff0c;有时候可能会希望一个函数能够改变正在调用中的函数&am…

WordPress wp-file-manager 文件上传漏洞 CVE-2020-25213

1.漏洞复现 WordPress 6.2 插件&#xff1a;wp-file-manager 6.0&#xff0c;File Manager (advanced view) – WordPress plugin | WordPress.org &#xff08;https://wordpress.org/plugins/wp-file-manager/advanced/&#xff09; 复现 后台&#xff0c;安装、启动插件…

linux环境安装redis(亲测完成)

linux环境安装redis 亲测完成 前言一、redis简介Redis 与其他 key - value 缓存产品有以下三个特点&#xff1a;Redis 优势 二、安装redis1.下载安装包2.创建服务器安装路径3.上传安装包4.解压安装包5.依赖安装6.编译 三、启动1)默认启动错误解决方式 2)指定配置启动2.1&#x…

C++中返回类型与return语句

C中返回类型与return语句 有、无返回值的函数及其return语句 无返回值&#xff08;函数声明中&#xff0c;返回值类型为void&#xff09;的函数&#xff0c;如果其中没有任何return语句也是正确的&#xff0c;编译器会自动在函数结束处补上隐式的return;语句。如果这种void函数…