当前位置: 首页 > 工具软件 > AviSynth > 使用案例 >

ffmpeg php 抠像_利用 Avisynth 2.5.8 的 ColorKeyMask 功能实现视频抠像

符献
2023-12-01

下载安装Avisynth 2.5.8 + 下载安装 FFMpeg

编写 Avisynth 脚本 mating.avs

----------------------------------------------------------------------------------

video1 = AVISource ("背景.avi").ConvertToRGB32

video2 = AVISource ("前景.avi").ConvertToRGB32.colorkeymask($45D168,40).Blur(0,1)

Layer(video1,video2,"add",255,0,0)

----------------------------------------------------------------------------------

然后编写批处理 play.bat

----------------------------------------------------------------------------------

ffplay "mating.avs" -loop 0

----------------------------------------------------------------------------------

运行play.bat

----------------------------------------------------------------------------------

缺点:边界过度不够自然

优点:处理速度较快

下面是优化方案

1.下载 Avisynth 2.5.8 源代码(用VC + MASM32) Avisynth_258_src.zip

http://sourceforge.net/projects/avisynth2/files/AviSynth%202.5/AviSynth%202.5.8/

说明:需要VC6 + MASM32 汇编

MASM32 汇编 下载地址

http://www.masm32.com/masmdl.htm

2.要修改的函数 ColorKeyMask::GetFrame(int n, IScriptEnvironment *env)

Avisynth_258_src.zip 解压到一个 .\avisynth_2.5.8\ 目录

...\avisynth_2.5.8\src\filters\layer.cpp 文件中有这个函数

原先的函数使用 IsClose 函数过滤 去掉设置相近的颜色

要优化的部分在 ColorKeyMask::GetFrame 函数内

static __inline bool IsClose(int a, int b, unsigned threshold)

{

return (unsigned(a-b+threshold) <= threshold*2);

}

PVideoFrame __stdcall ColorKeyMask::GetFrame(int n, IScriptEnvironment *env)

{

PVideoFrame frame = child->GetFrame(n, env);

env->MakeWritable(&frame);

BYTE* pf = frame->GetWritePtr();

const int pitch = frame->GetPitch();

const int rowsize = frame->GetRowSize();

if (!(env->GetCPUFlags() & CPUF_MMX) || vi.width==1)

{

const int R = (color >> 16) & 0xff;

const int G = (color >> 8) & 0xff;

const int B = color & 0xff;

for (int y=0; y < vi.height; y++)

{

for (int x=0; x < rowsize; x+=4)

{

if (IsClose(pf[x],B,tolB) && IsClose(pf[x+1],G,tolG) && IsClose(pf[x+2],R,tolR))

pf[x+3]=0;

//在这里添加进行边缘模糊的算法 开始

//思路

//1.根据这点判断是否是边缘

//2.如果是边缘,就把边缘的内侧alpha通道值逐渐变化处理 0->255

// pf[x+(0-2)]是 RGB 值 pf[x+3] alpha值

// 从 pf 到 pf + pitch 是 一帧图像中的一行

// 这部分代码写出来之后可能不超过 100 行,就是算法需要好好研究

//...

//在这里添加进行边缘模糊的算法 结束

}

pf += pitch;

}

}

else // MMX 这部分是为了加快处理速度 使用 MMX 指令集, 优化时暂不考虑这部分

{

const int height = vi.height;

const int col8 = color;

const int tol8 = 0xff000000 | (tolR << 16) | (tolG << 8) | tolB;

const int xloopcount = -(rowsize & -8);

pf -= xloopcount;

__asm

{

mov esi, pf

mov edx, height

pxor mm0, mm0

movd mm1, col8

movd mm2, tol8

punpckldq mm1, mm1

punpckldq mm2, mm2

yloop:

mov ecx, xloopcount

xloop:movq mm3, [esi+ecx]

movq mm4, mm1

movq mm5, mm3

psubusb mm4, mm3

psubusb mm5, mm1

por mm4, mm5

psubusb mm4, mm2

add ecx, 8

pcmpeqd mm4, mm0

pslld mm4, 24

pandn mm4, mm3

movq [esi+ecx-8], mm4

jnz xloop

mov ecx, rowsize

and ecx, 7

jz not_odd

; process last pixel

movd mm3, [esi]

movq mm4, mm1

movq mm5, mm3

psubusb mm4, mm3

psubusb mm5, mm1

por mm4, mm5

psubusb mm4, mm2

pcmpeqd mm4, mm0

pslld mm4, 24

pandn mm4, mm3

movd [esi], mm4

not_odd:

add esi, pitch

dec edx

jnz yloop

emms

}

}

return frame;

}

 类似资料: