• 利用 Avisynth 2.5.8 的 ColorKeyMask 功能实现视频抠像


    下载安装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.8srcfilterslayer.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;
    }
    
    
    
  • 相关阅读:
    Android:短信发送
    Android 自制拍照软件
    Android 联系人的读取,查询,添加
    android activity生命周期
    android 让 EditText, TextView自动识别链接
    android Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)
    FileOutputStream 读文件的模式
    Android 使用 SharedPreferences 保存和加载软件参数
    使用google的GSON处理JSON
    Android SqlLite数据库的创建、增、删、改、查、使用事务
  • 原文地址:https://www.cnblogs.com/nlsoft/p/3500003.html
Copyright © 2020-2023  润新知