下载安装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; }