Hatena::Groupnicovideo

にわかな奴の砂場

    使えそうなものがあれば適当にどうぞ。(自己責任的な意味で) 過去ログ

2009-01-03

[][][][]AviSynthで差分合成する 21:37 AviSynthで差分合成する - にわかな奴の砂場 を含むブックマーク はてなブックマーク - AviSynthで差分合成する - にわかな奴の砂場

内容としては「 ダンスの背景飛ばし……? - にわかな奴の砂場 - ニコニコ部」の応用となる訳ですが、AviSynth標準フィルタだと何かと使い辛いので関数を書いてみたりしたので、拙作をぺたり。自分用のローカルライブラリですが、公開する事で何かの役に立つかもしれませんので。

mylib.avs

#####
###  AviSynth用ローカル関数
#    

#
# EARTHSOFTDV : AviUtl用のPV3/4のDVファイルローダを使って読み込む為の関数.
# ※WarpSharpパッケージが必要.(cf.http://www.avisynth.info/?warpsharp%A5%D1%A5%C3%A5%B1%A1%BC%A5%B8)
#
LoadAviUtlInputPlugin("C:\Program Files\EARTH SOFT\PV3 3.x\AviUtl\EARTH SOFT DV.aui", "EARTHSOFTDV")

#
# DiffMask : 2つのクリップの差分から生成した白黒256階調のクリップ(RGB32)を返す.
#            ※VerticalCleanerが必要.(cf.http://www.avisynth.info/?niiyan%2F2008-02-27)
#
#	s1, s2    … 差分抽出用のクリップ.同じ解像度である事が必要.
#	tolerance … 差分の許容誤差.内部的にはColorKeyMask()のパラメータとして利用.
#
function DiffMask (clip s1, clip s2, int "tolerance") {
	s1 = IsYUY2(s1) ? s1 : ConvertToYUY2(s1)
	s2 = IsYUY2(s2) ? s2 : ConvertToYUY2(s2)
	tolerance = default(tolerance, 0)

	e = Overlay(s1, s2, mode="difference").ColorYUV(off_y=-128).ConvertToRGB32()
	e = ColorKeyMask(e, $000000, tolerance)
	e = e.ShowAlpha().VerticalCleaner().VerticalCleaner().Greyscale()

	return e
}

#
# MaskedLayer : 前景にアルファチャネルを適用し,背景と重ねたクリップ(RGB32)を返す.
#
#	bg   … 背景となるクリップ.
#	fg   … 前景となるクリップ.アルファチャネルが適用される.
#	mask … アルファチャネルとなるクリップ.基本的に白黒256色.
#	※3クリップとも同一の解像度である事が必要.
#
function MaskedLayer (clip bg, clip fg, clip mask) {
	bg = IsRGB32(bg) ? bg : ConvertToRGB32(bg)
	fg = IsRGB32(fg) ? fg : ConvertToRGB32(fg)
	mask = IsRGB32(mask) ? mask : ConvertToRGB32(mask)

	fg = Mask(ResetMask(fg), mask)
	res = Layer(bg, fg, op="add")

	return res
}

使用例

キュンキュンメガネと大正リボンを同時に付けてみると言う。これは以下のようなAviSynthスクリプトで合成しています。

#
# 大正リボンのクリップにキュンキュンメガネのクリップを合成してみる
# ※ColorItが必要.(cf.http://www.avisynth.info/?%B1%C7%C1%FC%B8%FA%B2%CC#bce2e312)
#

#外部スクリプトのインポート.同フォルダに置くか,或いはフルパス指定
Import("mylib.avs")

#大正リボンのクリップ
ribon=EARTHSOFTDV("ribon.dv")
#キュンキュンメガネのクリップ
megane=EARTHSOFTDV("megane.dv")
#セピアサングラスのクリップ
sepisan=EARTHSOFTDV("sepisan.dv")

#メガネとセピサンの差分からマスク作成
mask=DiffMask(megane, sepisan)
#穴が埋まるまでマスクを膨張させる
mask=mask.Morpher(type="dilate").Morpher(type="dilate").Morpher(type="dilate").Morpher(type="dilate").Morpher(type="dilate").VerticalCleaner()
#穴が埋まったらマスクを収縮させる.ついでにエッジぼかし
mask=mask.Morpher(type="erode").Morpher(type="erode").Morpher(type="erode").Morpher(type="erode").Morpher(type="erode").Blur(1)

#目元を合成
MaskedLayer(ribon, megane, mask).ConvertBackToYUY2()

リボンの動画にメガネの動画の目元部分だけを重ねる為、メガネとセピアサングラスの動画差分を利用してマスクを作っていますが、そのままだと穴ぼこだらけで使えないので、ColorItプラグインのフィルタMorpher()で穴を埋めています。

f:id:hdkINO33:20090103212934p:image

こんな感じ。で、後はこのマスクをメガネ動画のアルファチャネルとして適用し、リボンの動画と重ねてめでたく完成。1アングル作る為に3本録らなきゃいけないので時間も保管容量もバカになりません。それに加えて合成処理の遅い事と言ったら、8000フレームの処理が大体30分くらい。全自動なんで放っておけばいい訳でもありますが。

複数のアクセサリを合成する場合は同様の手順を重ねればいいだけですが、重ねて不自然の無い順番を探すのは結構めんどくさいです。*1

nukIM@S-2使えばいいんじゃね?

Exactly.

2007-10-17

[][] ダンスの背景飛ばし……? 01:37  ダンスの背景飛ばし……? - にわかな奴の砂場 を含むブックマーク はてなブックマーク -  ダンスの背景飛ばし……? - にわかな奴の砂場

はじめに

・その他

ステージ差分でキャラ部だけ消せるんじゃね? とか……まあ無理?(爆

コミュの背景飛ばし - にわかな奴の砂場 - ニコニコ部

の実証実験です。レタッチ一切無し、使用ソフトはVirtualDubMod+AviSynth、テロップ入れはVS9。

結果

ニコニコ動画 - アイドルマスター ダンスキャラ抜き実験」を参照下さい。

コマによっては結構良い抜け方をしてるけど、全体的にはキャラ周辺部レタッチ必須と言う感じ。あんまり役に立ちそうに無いかなあ。あと瞬きのタイミングがランダムっぽくて、時々目が抜けてたりしてます。

色滲みの無いHDソースで60fpsとかだと違うのかもしれないけれど……誰かやってみませんか?(爆

とりあえず一番綺麗に抜けたであろう原寸大サンプルも貼っておく。一番綺麗なのでこの程度だから騙されないように御注意(;´Д`)

この指にとまれ

AVSソース

#!AviSynth
# 元動画の解像度は704x400

# 元動画Aをロード
s1=AviSource("H:\tmp\gomyway_1.avi").KillAudio()

# Aとは別背景だが、同一カメラアングルで動作フレームが一致する
# 元動画Bをロード。Aと開始フレームを合わせる
s2=AviSource("H:\tmp\gomyway_2.avi").KillAudio().Trim(12, 3889)

# 白背景を作成
white=BlankClip(length=1, width=704, height=400, pixel_type="RGB32", fps=29.97, color=$ffffff).Loop(4000)

# AとBの差分を表示するクリップを作成し、差分を強調する
# cf.http://avisynth.org/mediawiki/Overlay#Parameters
diff=Overlay(s1, s2, mode="Difference").ColorYUV(off_y=-127).ConvertToRGB32()

# 差分表示クリップからブラックをキーとしてマスク作成。適用レベルは適当
mask=ColorKeyMask(diff, $000000, 25)
# アルファチャンネルを反転しぼかしを掛ける(アンチエイリアスもどき)
mask=mask.ShowAlpha().Invert().Blur(1.3).GreyScale()

# 元動画Aに上で作成したアルファチャンネルを設定
layer=s1.ConvertToRGB32().ResetMask()
layer=Mask(layer, mask)

# アルファチャンネルを設定した元動画Aを適当な背景と合成する
# ここでは白背景と合成
Layer(white, layer, "add")

追記(2007/11/07)

コメートさんPが発展させて下さった模様。

こいつはスゲェー! HDソースとかで色々試してたけどトリオでセンターだけ取り出すと言う発想には至らなかったわ。本当にありがとうございました。

クロップについては適当な矩形マスク作ってAviSynthで合成してやりゃ代用できるかな……VS11と比べたら位置合わせの手間がめんどくさそうではあるけれど。

2007-09-238x8でも辛い

[] また下らんものを作ってしまった…… 03:34  また下らんものを作ってしまった…… - にわかな奴の砂場 を含むブックマーク はてなブックマーク -  また下らんものを作ってしまった…… - にわかな奴の砂場

AviSynthで遊ぶのも良いが早くMADを作成する仕事に戻るんだ。

256分割 フレーム長ランダムトリム

2007-09-21初っ端から

[][] コミュの背景飛ばし 04:43  コミュの背景飛ばし - にわかな奴の砂場 を含むブックマーク はてなブックマーク -  コミュの背景飛ばし - にわかな奴の砂場

「歌入りとカラオケの差分取ってボーカル抜きできるんなら同じような理屈でキャラ動画と背景があればキャラだけ抜けるんじゃね?」

……と思って早数日。(;´Д`)

色滲みの無い高解像度のソースだと綺麗に抜けるのかな? とりあえず上げてみるテスト。万が一試行する際はファイルパスやパラメータ変更をお忘れなく。

免責

本文の記述を元に行われた全ての作業より発生した不具合について、筆者は全ての責任を負わないものとします。

(棒読み)

はじめに

手動レタッチなしでどこまでキャラだけ取り出せるかの実験です。

AviSynthについては以下を参考に。と言うかお世話になりっぱなしです。

キャラ動画を線画化

キャラ動画(オリジナル)

・layer.avs

#!AviSynth
s=AviSource("source.avi").KillAudio()
# Lanczos4Resizeで倍拡大。ソースに無駄部分が多かったのでTrimで適当に削り
layer=s.Trim(440, 1225).Lanczos4Resize(1408, 800)
return layer

これをVirtualDubModに食わせてSmartSmootherHQ*1を掛ける。「Check Greyscale」と「Visualize Blur」をチェック(重要)。他パラはプレビューを観ながら決める。この場合「Diameter」が主線の硬さで「Threshold」が主線の閾値になります。変な使い方してるのでこんな風に憶えてはいけません(;´Д`)

で、これを「layer.avi」とかして保存するわけですが、このSSHQと言う奴は各所で書かれてる通り半端じゃなく重いです。某抜き抜き先生ならこの間に数十枚抜けるんじゃなかろうかなあと思える程に。

処理後はこんな感じ。とりあえずDiameter=5,Threshold=40くらい。

キャラ動画(線画)

背景のコマを線画化

背景(オリジナル)

・bg.avs

#!AviSynth
s=AviSource("source.avi").KillAudio()
# 背景を1フレーム抽出
bg=s.Trim(442, 442).Lanczos4Resize(1408, 800).Loop(1)
return bg

これをVirtualDubModに食わせてSmartSmootherHQを掛ける。パラはキャラ動画のと同様で。

これを「bg.avi」とかして保存。1コマなのですぐ終わります。

処理後はこんな感じ。

背景(線画)

線画化したキャラ動画と背景を合成

diff.avs

#!AviSynth
# bgは1コマしか無いのでループさせる(書き忘れてたorz)
bg=AviSource("bg.avi").KillAudio().Loop(1000)
layer=AviSource("layer.avi").KillAudio()
Overlay(bg, layer, mode="Difference")
ConvertToYUY2().ColorYUV(off_y=-127)
Invert()

まあ要するにOverlay()のDifferenceモードで合成して、排他的論理和的なものを出してると、そういう事です。Subtractモードとか、或いはOverlay()じゃなくてSubtract()を使っても面白いかも。

で、めでたくキャラの線画らしきものが抜けます。動画サンプル→

キャラ背景飛ばし

キャラの内側が線でうるさくなってますが、まあアルファチャンネル作成用なので特に気にしない方向で。

使えるのこれ?

  • 背景だけのフレームがあるのが前提。無いとできない
  • 結局アルファチャンネルは手で抜かないといけない
  • 主線の切れ目を補修しないといけない
  • とにかくSSHQが重い

という問題に目をつむれば使えるかも? 処理時間*2の割には結構微妙かも。

その他

ステージ差分でキャラ部だけ消せるんじゃね? とか……まあ無理?(爆

*1neuron2.net。正しい用法はwavelet NR

*2:実処理時間は自環境で2時間くらい