にわとり遊び
PC関連とエンコードの覚書き
スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

差分合成関数 OverDiff5

function OverDiff5 (clip clip1,clip clip2,int "mode",int "top",int "bottom",int "left",int "right",int "smask",int "lmask",clip "c1",clip "c2",int "margin",bool "show") {
mode=default(mode,0)
top=default(top,0)
bottom=default(bottom,0)
left=default(left,0)
right=default(right,0)
smask=default(smask,40)
lmask=default(lmask,20)
margin=default(margin,0)
show=default(show,false)
c1=default(c1,clip1.crop(left,top,-right,-bottom).blur(0,1))
c2=default(c2,clip2.crop(left,top,-right,-bottom).blur(0,1))

check_diff=mt_lutxy(c1,c2,"x y - abs",chroma="process").mt_binarize(5).mt_inpand.mt_inpand.mt_inpand
over_mask=BlankClip(clip1,color=$ffffff).Letterbox(top,bottom,left,right).mt_binarize()
masked_1=mt_merge(clip1,clip2,over_mask,luma=true)
show_mask=Overlay(BlankClip(clip1),check_diff).Grayscale()
show_merge=merge(clip1,clip2)

clip_0=masked_1
clip_0=(show) ? merge(show_merge,over_mask) : clip_0
clip_1=ConditionalFilter(check_diff,clip1,masked_1,"AverageLuma","<","1.0",show=show)
clip_1_show=ConditionalFilter(check_diff,show_merge,show_merge,"AverageLuma","<","1.0",show=show)
clip_1=(show) ? StackVertical(merge(clip_1_show,over_mask),show_mask) : clip_1

c1=clip1.blur(0,1).Letterbox(top,bottom,left,right)
c2=clip2.blur(0,1).Letterbox(top,bottom,left,right)
small=mt_lutxy(c1,c2,"x y - abs",chroma="process").letterbox(0,0,2,2).mt_binarize(smask)
small_u=mt_lutxy(c1.UToY,c2.UToY,"x y - abs",chroma="process")
small_v=mt_lutxy(c1.VToY,c2.VToY,"x y - abs",chroma="process")
small_uv=mt_logic(small_u,small_v,mode="or").PointResize(c1.width,c1.height).letterbox(0,0,2,2).mt_binarize(smask)
small=(mode>=3) ? mt_logic(small,small_uv,mode="or") : small
small_e=mt_lutxy(c1,c2,"x y - abs",chroma="process").letterbox(2,2,2,2).mt_edge
small_e=(mode==4) ? small_e.mt_inpand : small_e
small=mt_logic(small_e,small,mode="or")
small=(margin==0) ? small : mt_logic(small,mt_logic(small.Loop(0,0,margin-1),small.Loop(margin+1,0,0),mode="or"),mode="or")
small=(mode>=4) ? small : small.mt_inpand

big=mt_lutxy(c1,c2,"x y - abs 1.5 ^",chroma="process")
big_u=mt_lutxy(c1.UToY,c2.UToY,"x y - abs 1.5 ^",chroma="process")
big_v=mt_lutxy(c1.VToY,c2.VToY,"x y - abs 1.5 ^",chroma="process")
big_uv=mt_logic(big_u,big_v,mode="or").PointResize(c1.width,c1.height)
big=(mode>3) ? mt_logic(big,big_uv,mode="or") : big
big=big.mt_binarize(lmask)

diff_mask=mt_hysteresis(small,big).mt_expand.mt_expand.mt_expand.mt_expand.mt_expand.mt_expand.mt_expand
masked_2=mt_merge(clip1,clip2,diff_mask,luma=true)
clip_2=ConditionalFilter(check_diff,clip1,masked_2,"averageluma","=","0",show=show)
clip_2_show=ConditionalFilter(check_diff,show_merge,show_merge,"averageluma","=","0",show=show)
clip_2=(show) ? StackVertical(merge(clip_2_show,diff_mask.Grayscale()),show_mask) : clip_2
return select(mode,clip_0,clip_1,clip_2,clip_2,clip_2)
}

clip1 : 元となるクリップ
clip2 : clip1に上書きする為のクリップ
mode : mode=0 無条件で上書きを行う。 / mode=1 clip1とclip2にある程度の差分が認められた場合に上書きを行う。 / mode=2 clip1とclip2の差分にマスクを作成し、その部分のみ上書きを行う。 / mode=3 mode=2に色差を追加する。 / mode=4 mode=2のマスクを拡大する。
top , bottom , left , right : 上下左右の差分を除外する。
smask : 基本となる差分マスク。smaskの範囲をlmaskで拡大し、最終的なマスクが作成される。
lmask : smaskを拡大する為のマスク。
c1 , c2 : clip1とclip2に差分があるかどうかを判定するための入力クリップ。OverlayやBlur等で加工したクリップを判定に使用できる。
margin : 前後フレームの差分マスクを重ねる。
show : 差分マスクの確認を行う。


使用例
#clip1とclip2の差分にclip2を上書きする
clip1=OverDiff5(clip1,clip2,2)

#ANIME+
checktelop=mt_lutxy(clip1,clip2,"x y - abs",chroma="process").crop(560,0,-600,-820).mt_binarize(20).mt_inpand(mode="horizontal")
clip1_ANIME=OverDiff5(clip1,clip2,1,0,820,100,1360)
clip1=ConditionalFilter(checktelop,clip1_ANIME,clip1,"averageluma","<","5")

#clip2の左右4pxをclip1に置き換える
clip2=OverDiff5(clip1,clip2,0,0,0,4,4)
※上記ではclip2の音声がclip1に入れ替わるので注意

#適用範囲を指定する
clip1=clip1.ApplyRange(0,1000,"OverDiff5",clip2,3,700,0,0,0)
※0-1000フレーム区間、上部700pxを除外
スポンサーサイト
FlexibleMerge5
以前との変更点
・入力クリップの順番に関わらず最適な結果が得られるようにした。
・以前のweightに当たる変数を、2つのクリップのノイズ量の差に応じて変動するようにした。

・極力global変数を使わないよう修正

function FlexibleMerge5 (clip clip1,clip clip2,float "weight1",float "weight2",float "weight3",int "top",int "bottom",int "left",int "right",int "thr",float "nmax",int "mode",int "show") {

thr=default(thr,10)
weight1=default(weight1,0.5)
weight2=default(weight2,1.0)
weight3=default(weight3,0.0)
nmax=default(nmax,30.0)
mode=default(mode,2)
show=default(show,0)

top=default(top,0)
bottom=default(bottom,0)
left=default(left,0)
right=default(right,0)

blank1=BlankClip(clip1,color=$ffffff).Letterbox(top,bottom,left,right).mt_binarize()
mask1=CombMask(clip1, thY1 = thr, thY2 = thr)
mask2=CombMask(clip2, thY1 = thr, thY2 = thr)

nmask12=mt_logic(blank1,mt_logic(mask2,mask1,mode="andn"),mode="and")#clip1にノイズ、clip2はきれい
nmask21=mt_logic(blank1,mt_logic(mask1,mask2,mode="andn"),mode="and")#clip2にノイズ、clip1はきれい
nmaskA=mt_invert(mt_logic(mask1,mask2,mode="or"))#両方きれい
nmaskB=mt_logic(mask1,mask2,mode="and")#両方ノイズ
nmaskAB=mt_logic(blank1,mt_logic(nmaskA,nmaskB,mode="or"),mode="and")

clip1=(show==0) ? clip1 : clip1.subtitle("clip1",size=48)
clip2=(show==0) ? clip2 : clip2.subtitle("clip2",size=48,y=50)

global global_thr=thr
global global_nmax=nmax

clipA=Merge(clip1,clip2,weight1)
clipB=Merge(clip1,clip2,weight3)
clipAB=ScriptClip(Interleave(clip1,clip2),"Merge(SelectEven,SelectOdd,0.5/global_nmax*(averageluma(CombMask(SelectEven,thY1=global_thr,thY2=global_thr))-averageluma(CombMask(SelectOdd,thY1=global_thr,thY2=global_thr)))+0.5)")
clip12=Merge(clip1,clip2,weight2)
clip21=Merge(clip2,clip1,weight2)

clip_m0=mt_merge(clip1,clipA,nmaskA,luma=true)
clip_m0=mt_merge(clip_m0,clipB,nmaskB,luma=true)
clip_m1=mt_merge(clip1,clipAB,nmaskA,luma=true)
clip_m1=mt_merge(clip_m1,clipB,nmaskB,luma=true)
clip_m2=mt_merge(clip1,clipAB,nmaskAB,luma=true)

clip=select(mode,clip_m0,clip_m1,clip_m2)
clip=mt_merge(clip,clip12,nmask12,luma=true)
clip=mt_merge(clip,clip21,nmask21,luma=true)

show1=Combcheck(clip)
show2=StackHorizontal(Combcheck(clip1),Combcheck(clip2)).ReduceBy2.StackVertical(ReduceBy2(Combcheck(clip)).AddBorders(clip.width/4,0,clip.width/4,0))
show3=ConditionalFilter(Interleave(mask1,mask2),show2,show2,"averageluma(SelectEven)","<","averageluma(SelectOdd)",show=true)
clip=Select(show,clip,show1,show2,show3)
return clip
}


clip clip1 : ベースとなるクリップ

clip clip2 : ブレンドするクリップ

float "weight1" : clip1とclip2の両方にノイズがない部分をmergeする割合。mode=0のとき無効

float "weight2" : clip1とclip2の片方にノイズがない部分をmergeする割合。

float "weight3" : clip1とclip2の両方にノイズがある部分をmergeする割合。mode=0,1のとき無効

int "top" , "bottom" , "left" , "right" : 上下左右をマスキングする。マスキングした部分はclip1を保つ。

int "thr" : CombMaskの閾値

float "nmax" : weightを変動させるためのclip1とclip2のノイズ量の差の上限。clip1-clip2=-nmaxのときweight=0となりclip1は上書きされない。clip1-clip2=0のときweight=0.5。clip1-clip2=nmaxのときweight=1となりclip1はclip2に上書きされる。

int "mode" : weightの変動を適用するか否か。mode=0のとき変動しない。mode=1のときweight1のみ変動する。mode=2のときweight1とweight3が変動する。

int "show" : ノイズ量を視覚化する。show=0のとき無効。show=1のとき出力結果のノイズ量を視覚化する。show=2のときclip1,clip2,出力結果の3クリップを並べてノイズ量を視覚化する。show=3のときshow=2の出力と共にclip1,clip2のノイズ量を表示する。
LEraser - L字処理の簡単なやつ
あに瓶さんがもっとちゃんとしたものを公開しているので、ちゃんとしたい人はそちらをどうぞ。
とりあえずMXだけです。

function LEraser (clip clip,int start,int end,int frames)
{
l=180.1/frames
b=67.5/frames
function Lstart(clip clip,int start,float l,float b) {
ScriptClip(clip,"
lc=(current_frame-"+string(start)+")*"+string(l)+"
bc=(current_frame-"+string(start)+")*"+string(b)+"
Spline36Resize(1440,540,lc,0,1440-lc,540-bc)
")
return last
}
function Lcrop (clip clip,int frames,float l,float b) {
lc=l*frames
bc=b*frames
clip.Spline36Resize(1440,540,lc,0,1440-lc,540-bc)
return last
}
function Lend(clip clip,int end,float l,float b) {
ScriptClip(clip,"
lc=("+string(end)+"-current_frame)*"+string(l)+"
bc=("+string(end)+"-current_frame)*"+string(b)+"
Spline36Resize(1440,540,lc,0,1440-lc,540-bc)
")
return last
}
clip.SeparateFields
ApplyRange(start,start+frames,"Lstart",start,l,b)
ApplyRange(start+frames+1,end-frames,"Lcrop",frames,l,b)
ApplyRange(end-frames+1,end,"Lend",end,l,b)
Weave()
ApplyRange(start/2,end/2,"Letterbox",0,24,16,0)
return last
}

LEraser(232*2,3331*2+1,31)

start - L字開始フレーム。separatefields後のフレーム数になるので2倍で指定。片フィールドの場合は+1。
end - L字終了フレーム。separatefields後のフレーム数になるので2倍で指定。片フィールドの場合は+1。
frames - L字が出始めてから完成するまでのフレーム数。

使うタイミングはTrim後ロゴ除去前。
WritePosition - 2つのクリップの開始フレームのズレを書き出す

function WritePosition (clip clip1,clip clip2,string filename,int "radius",int "depth",int "luma",bool "slip") {
slip=default(slip,false)
clip2=(slip) ? clip2.SeparateFields().Loop(0,0,0).AssumeFieldBased().Weave() : clip2
radius=default(radius,5)
depth=default(depth,30)
luma=default(luma,50)
clip1=clip1.blur(0,1)
clip2=clip2.blur(0,1)

function until_diff (clip diff,int depth,int "n") {
n=default(n,depth)
r=diff.framecount/n*(n-depth)+rand(diff.framecount/n,seed=true)
diff_frame=diff.Trim(r,-1)
clip=(depth==1) ? diff_frame : until_diff(diff,depth-1,n)
return ConditionalFilter(diff_frame,clip,diff_frame,"AverageLuma","=","0")
}

function add_radius (clip d0,clip clip1,clip clip2,int radius,int luma,int depth,int "radius_n") {
radius_n=default(radius_n,0)
d1=until_diff(mt_lutxy(clip1.Loop(0,0,radius_n),clip2,"x y - abs").Trim(10,clip1.framecount-10).mt_binarize(luma).mt_inpand,depth)
d2=until_diff(mt_lutxy(clip1,clip2.Loop(0,0,radius_n),"x y - abs").Trim(10,clip1.framecount-10).mt_binarize(luma).mt_inpand,depth)
d0=(radius==0) ? d0 : d0++d1++d2
return (radius_n+1<radius) ? add_radius(d0,clip1,clip2,radius,luma,depth,radius_n+1) : d0
}

d0=until_diff(mt_lutxy(clip1,clip2,"x y - abs").Trim(10,clip1.framecount-10).mt_binarize(luma).mt_inpand,depth)

add_radius(d0,clip1,clip2,radius,luma,depth)
return WriteFileif(filename,"AverageLuma==0",""" "n=" ""","round(current_frame/2.0)*round(((current_frame/2.0-current_frame/2)-0.25)*2)",append=false)
}


・2つのクリップを比較して、差分を検知できない開始フレームを外部ファイルに出力する
Adjust2clipと併用して開始位置を合わせることが可能

clip1 - 基準となるクリップ
clip2 - clip1と合わせるクリップ
filename - 出力ファイル名を設定する
radius - フレームをずらす範囲。1なら前後+-1フレームの計3フレーム。
depth - 差分を検知する処理の最大試行回数。差分を検知し次第、次の処理に以降する。正しい位置では差分を検知しないので、必ず最大回数まで試行する。
luma - 差分判定の閾値
slip - clip2を1フィールドずらした状態で処理を開始する

0_20150508195014def.png
→ depth (試行回数上限)

radius (試行フレームの範囲)




#使用例
#clip1
Import("BS11\Trim.avs")
clip1_1=c1.crop(8,250,-8,-160).Trim(0,c1.framecount-330)
clip1_2=c2.crop(8,250,-8,-160)
clip1_3=c3.crop(8,250,-8,-160)
clip1_4=c4.crop(8,250,-8,-160).Trim(0,c4.framecount-330)
#clip2
Import("MX\Trim.avs")
clip2_1=c1.Spline36Resize(1920,last.height,0.12,0,1440,0).crop(8,250,-8,-160).Trim(0,c1.framecount-330)
clip2_2=c2.Spline36Resize(1920,last.height,0.12,0,1440,0).crop(8,250,-8,-160)
clip2_3=c3.Spline36Resize(1920,last.height,0.12,0,1440,0).crop(8,250,-8,-160)
clip2_4=c4.Spline36Resize(1920,last.height,0.12,0,1440,0).crop(8,250,-8,-160).Trim(0,c4.framecount-330)

#Import("slip.txt")
o1=WritePosition(clip2_1,clip1_1,"1.txt")
o2=WritePosition(clip2_2,clip1_2,"2.txt")
o3=WritePosition(clip2_3,clip1_3,"3.txt")
o4=WritePosition(clip2_4,clip1_4,"4.txt")
o1++o2++o3++o4
return last


#使用例 活用編
#BS11
Import("BS11\Trim.avs")
clip1=c1.EraseLOGO(logofile="D:\Movie\logo\BS11_1920x1080.lgd", start=0, fadein=0, fadeout=0, end=framecount(c1)-331)
#MX
Import("MX\Trim.avs")
clip2=c1.EraseLOGO(logofile="D:\Movie\logo\MX_1440x1080.lgd", start=0, fadein=0, fadeout=0, end=-1)
clip2=clip2.Spline36Resize(1920,1080,0.12,0,1440,0)

n=clip2.framecount
Import("1.txt")
clip1=Adjust2clip(clip2,clip1,n,swapaudio=true)
stacksubtract(clip2,clip1,1)

#提供
clip2=clip2.ApplyRange(framecount(clip1)-330,framecount(clip1),"OverDiff3",clip1)#1920

#ANIME+
clip1=OverDiff3(clip1,clip2,0,820,100,1360,mode=1)
#テレビから離れて
clip1=OverDiff3(clip1,clip2,930,80,320,320,mode=1)

BS111=clip1
MX1=clip2
#Merge(clip1,clip2)
return last


Adjust2clip - 2つのクリップの開始位置を合わせる
function Adjust2clip (clip clip1,clip clip2,int n,bool "slip",bool "swapaudio") {
slip=default(slip,false)
swapaudio=default(swapaudio,false)
clip2=(slip) ? clip2.SeparateFields().Loop(0,0,0).AssumeFieldBased().Weave() : clip2
clip2=(n==0) ? clip2 : (n>0) ? (n==1) ? clip1.Trim(0,-1)++clip2 : clip1.Trim(0,-1+n)++clip2 : clip2.Loop(0,0,-1+Abs(n))
clip=Merge(clip1,clip2,1)
return (swapaudio) ? AudioDub(clip,clip2) : clip
}

clip1 - 基準となるクリップ
clip2 - clip1に合わせるクリップ
n - clip2からフレーム数を増減する数値
slip - [default=false] clip2を1フィールドずらす
swapaudio - [default=false] clip2の音声を使う


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。