ffmpeg抠图

2023-09-19 12:03:13

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值作用来改变灰阶度来达到透明效果。
chromakey与colorkey的区别,官网给了这四个例子

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绿幕抠图原理解析

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
更多推荐

python Sqlalchemy

简介SQLAlchemy是python中,通过ORM操作数据库的框架。它简化了应用程序开发人员在原生SQL上的操作,使开发人员将主要精力都放在程序逻辑上,从而提高开发效率。它提供了一整套著名的企业级持久性模式,设计用于高效和高性能的数据库访问。安装pipinstallSQLAlchemy连接数据(engine)任何SQ

Java性能调优工具“JRMC”的介绍

Java虚拟机(JVM)及垃圾收集器(GC)负责管理大多数的内存任务,但是Java应用系统中还是有可能出现内存泄漏。事实上,OOM之类的现象在大型项目中也是一个常见的问题。避免内存泄漏的第一步是要弄清楚它是如何发生的,然后对症下药。那究竟是什么导致了Java程序中的内存泄漏呢?难道Java虚拟机的垃圾收集器不应该管理未

开源日报 0824 | 构建UI组件和页面的前端工作坊

Storybook是一个用于构建UI组件和页面的前端工作坊,支持多种主流框架,提供丰富的插件,具有可配置性强和扩展性好的特点。storybookjs/storybookStars:79.9kLicense:MITStorybook是一个用于构建UI组件和页面的前端工作坊,可以独立地进行开发、测试和文档编写。它支持多种主

Nginx 配置错误导致漏洞

Nginx配置错误导致漏洞运行成功后,Nginx将会监听8080/8081/8082三个端口,分别对应三种漏洞。Mistake1.CRLF注入漏洞漏洞描述CRLF是”回车+换行”(\r\n)的简称,,其十六进制编码分别为0x0d和0x0a。在HTTP协议中,HTTPHeader与HTTPBody是用两个CRLF分隔的,

redis-操作带过期时间的key需保证操作的原子性

问题:先执行get获取值,判断符合条件再执行incr、decr操作。在临界缓存失效的情况下,会默认赋值当前key为永不过期的0,再执行加减法,导致程序异常。推荐解决方案:1、限制接口频率:先incr,执行后值为1,说明是第一次执行,需要额外设置过期时间,再判断是否超过当前接口频率限制(注意上述步骤不可调换顺序)2、使用

迷宫寻路:(深搜广搜)

迷宫寻路题目描述机器猫被困在一个矩形迷宫里。迷宫可以视为一个n×mn\timesmn×m矩阵,每个位置要么是空地,要么是墙。机器猫只能从一个空地走到其上、下、左、右的空地。机器猫初始时位于(1,1)(1,1)(1,1)的位置,问能否走到(n,m)(n,m)(n,m)位置。输入格式第一行,两个正整数n,mn,mn,m。接

TVS二极管的小知识

TVS二极管的小知识文章目录TVS二极管的小知识1、工作原理2、TVS二极管参数详解3、选型指南4、TVS二极管选型注意事项1、工作原理TVS(TransientVoltageSuppressors)二极管,即瞬态电压抑制器,又称雪崩击穿二极管,是采用半导体工艺制成的单个PN结或多个PN结集成的器件。TVS二极管有单向

Java基于SpringBoot的会员制医疗预约服务系统,可作为毕业设计

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W+、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌文章目录1简介2技术栈3系统分析3.1需求分析4系统总体设计4.1系统结构4.2数据库设计4.2.1数据库概念结构设计4.2.2数据库逻辑结构设计5系统

【Spring Boot】数据缓存Redis实现高并发 —— Redis入门

🌿欢迎来到@衍生星球的CSDN博文🌿🍁本文主要学习Redis的入门🍁🌱我是衍生星球,一个从事集成开发的打工人🌱⭐️喜欢的朋友可以关注一下🫰🫰🫰,下次更新不迷路⭐️💠作为一名热衷于分享知识的程序员,我乐于在CSDN上与广大开发者交流学习。💠我希望通过每一次学习,让更多读者了解我,也希望能结识更多志同

利用 Python PyPDF2库轻松提取PDF文本(及其他高级操作)

当需要从PDF文件中提取文本时,Python中的PyPDF2库是一个非常有用的工具。无论您是需要分析PDF文档中的内容还是需要在文档中搜索特定的信息,PyPDF2都可以帮助您轻松实现这些任务。在本文中,我们将探讨如何使用PyPDF2库提取PDF文件中的文本,并提供一些示例代码来帮助您入门。安装PyPDF2库首先,您需要

全局异常处理+JSR303验证

一、前言我们在日常开发中,避不开的就是参数校验,有人说前端不是会在表单中进行校验的吗?在后端中,我们可以直接不管前端怎么样判断过滤,我们后端都需要进行再次判断,为了安全。因为前端很容易拜托,当测试使用PostMan来测试,如果后端没有校验,不就乱了吗?肯定会有很多异常的。今天小编和大家一起学习一下JSR303专门用于参

热文推荐