Artykuł dostępny jest również w formie dokumentu
Transkrypt
Artykuł dostępny jest również w formie dokumentu
PAL Inverse Telecine w AviSynth Aby wykorzystać dowolną z opisanych tu metod należy zainstalować AviSynth 2.5.x oraz wyposażyć się w odpowiednie wtyczki dostępne tutaj (ściągając każdą z nich należy wybrać wersję dla AviSynth 2.5.x). Pliki *.dll z archiwów *.zip poszczególnych wtyczek należy skopiować do katalogu wtyczek AviSynth (domyślnie C:\Program Files\AviSynth 2.5\plugins) - wówczas będziemy mogli się nimi posługiwać bez użycia LoadPlugin(). Zakłada się, że czytelnik zna podstawy AviSynth oraz obsługę programu VirtualDubMod (który w dalszych rozważaniach będziemy określać skrótem VDM). Słowo wstępne W zależności od źródła jego pochodzenia, możemy wyróżnić dwa rodzaje przeplotu: "naturalny" i "sztuczny". Przeplot "naturalny" (którego dotyczy ten artykuł) powstaje już w trakcie filmowania - kamera nie filmuje pełnych klatek, lecz najpierw jeden półobraz, zaś chwilę później drugi (w ten sposób pracują kamery telewizyjne a także amatorskie kamery cyfrowe DV). Przeplot "sztuczny" (którego dotyczy niniejsze opracowanie) powstaje wskutek wykonania procesu telecine, czyli dostosowania filmu progresywnego (filmowanego pełnowymiarowymi klatkami) do emisji w telewizji. Elementem procesu telecine jest rozdzielenie każdej klatki na półobrazy, ponieważ w analogowym sygnale telewizyjnym muszą być one rozdzielone. Z progresywnych klatek ABCD uzyskujemy klatki podzielone na półobrazy górne (t) i dolne (b): AtBtCtDt AbBbCbDb Jest to tzw. 2:2 pulldown. Następnie konieczna jest korekta ilości klatek na sekundę (w skrócie FPS od angielskiego frames per second) w filmie. Filmy kinowe kręcone są przy 24 FPS, zaś systemy telewizyjne PAL i SECAM używają 25 FPS (50 półobrazów na sekundę), a NTSC 29.97 FPS (59.94 półobrazów na sekundę). W przypadku dwóch pierwszych systemów (których dotyczy niniejsze opracowanie) zazwyczaj dokonuje się tego poprzez przyspieszenie z 24 do 25 FPS oraz ewentualnej późniejszej korekty tonacji dźwięku (która wskutek jego przyspieszenia została nieco podniesiona i może brzmieć nienaturalnie, co jest szczególnie odczuwalne w przypadku muzyki). W systemie NTSC jest to nieco bardziej skomplikowane - najpopularniejszym sposobem konwersji z 24 do 29.97 FPS jest tzw. 3:2 pulldown, który wygląda następująco: z czterech klatek ABCD rozdzielonych na półobrazy górne (t) i dolne (b): AtBtCtDt AbBbCbDb poprzez przestawienie i duplikację niektórych półobrazów uzyskujemy pięć klatek: AtAtBtCtDt AbBbCbCbDb Jak widać, teoretycznie proces telecine wymaga odwracania tylko w przypadku NTSC, zaś dla systemów PAL i SECAM po spleceniu półobrazów powinniśmy bez żadnych dodatkowych zabiegów odzyskać prawidłowe progresywne klatki. Często jednak się tak nie dzieje i takich przypadków dotyczy niniejsze opracowanie. UWAGA: Niedopuszczalna jest zmiana rozdzielczości pionowej obrazu przed usunięciem przeplotu (zmiana rozdzielczości poziomej też nie jest polecana). 1. Określanie prawidłowej kolejności półobrazów Działanie funkcji i wtyczek AviSynth opisywanych w tym artykule jest uzależnione od kolejności półobrazów w materiale żródłowym, toteż musimy ją prawidłowo określić. Wprawdzie AviSynth sam stara się ją rozpoznać i dysponuje wbudowaną funkcją GetParity() (zwracającą true dla materiału TFF, zaś false dla materiału BFF), lecz często informacja ta okazuje się nieprawdziwa. Aby "ręcznie" określić prawidłową kolejność półobrazów, piszemy skrypt postaci: AVISource("•cie•ka\plik.avi") AssumeTFF() SeparateFields() Prawa autorskie © VideoAudio.pl 2001-2008 Następnie otwieramy go w VirtualDubMod i przewijamy suwakiem obserwując ruch. Jeśli ruch przebiega tylko w jednym kierunku (z ewentualnymi przestojami spowodowanymi półobrazami pochodzącymi z tej samej klatki) bez żadnych cofnięć, oznacza to, że znaleźliśmy właściwą kolejność półobrazów - jest to TFF, czyli półobraz górny jest zapisany jako pierwszy. Jeśli ruch jest szarpany (po półobrazie zawierającym ruch w prawidłowym kierunku następuje półobraz z cofnięciem), czynność powtarzamy dla skryptu: AVISource("•cie•ka\film.avi") AssumeBFF() SeparateFields() Teraz ruch powienien już być prawidłowy, a kolejność półobrazów to BFF - dolny półobraz jest zapisany jako pierwszy. Kolejność półobrazów należy zapamiętać, gdyż będziemy ją podawać jako argument funkcjom używanym w kolejnych przykładach. 2. Określenie rodzaju błędu telecine (a) field-shifted PAL Jest to błąd polegający na przesunięciu dolnych półobrazów w czasie o jedną klatkę podczas procesu 2:2 pulldown. Aby go zdiagnozować, otwieramy w VirtualDubMod skrypt: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym Telecide(order=?,guide=2,post=3,show=true,chroma=true) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Teraz powoli przewijając go w VDM sprawdzamy, czy Telecide() znalazł stały wzorzec układu półobrazów. Należy zwrócić uwagę na informacje wyświetlane w ostatnich dwóch linijkach. Jeśli w danej scenie (pomiędzy cięciami) wartość pattern mismatch jest równa 0.00% lub wynosi najwyżej kilka procent oraz w rubryce [using ?] dla wszystkich klatek występuje ta sama litera (p, c albo n), zaś w sąsiadujących z nią rubrykach mamy [progressive] oraz [in-pattern] (ewentualnie [interlaced] oraz [in-pattern*], ale tylko sporadycznie). Prawa autorskie © VideoAudio.pl 2001-2008 Jeśli warunek ten jest spełniony dla każdej sceny (tzn. zmiana wzorca występuje tylko w momentach cięć), znaczy to, że zidentyfikowaliśmy problem - jest to field-shifted PAL. Aby naprawić bład przesunięcia półobrazów, wystarczy zmodyfikować powyższy skrypt do postaci: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym Telecide(order=?,guide=2,post=2,show=false,chroma=true,blend=false) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF To spowoduje, że Telecide() usunie przesunięcie półobrazów, a następnie wykona postprocessing, czyli usunie pozostające w filmie artefakty przeplotu (któych powinno być bardzo mało, mogą wystąpić np. w logo wytwórni na początku lub końcu filmu) metodą analogiczną do FieldDeinterlace(blend=false) (informacje o poszczególnych parametrach funkcji Telecide() oraz FieldDeinterlace() znajdziecie na polskiej stronie AviSynth). Ustawiając w Telecide() parametr blend=true uzyskamy zlewanie półobrazów w obszarach zawierających przeplot (w przypadku blend=false stosowana jest interpolacja). Możliwe też jest użycie KernelDeint() do postprocessingu zamiast FieldDeinterlace() - wystarczy użyć skryptu postaci: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym Telecide(order=?,guide=2,post=1,show=false,chroma=true,hints=true) KernelDeint(order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF (b) nieregularny wzorzec Prawa autorskie © VideoAudio.pl 2001-2008 Jeśli oglądając w VDM pierwszy skrypt przedstawiony w punkcie field-shifted PAL nie możemy znaleźć stałego wzorca układu półobrazów (tzn. w polu [using ?] litera wciąż się zmienia i/lub na wielu klatkach pojawiają się obszary zawierające artefakty przeplotu zaznaczone kolorem białym oraz napis [interlaced]), oznacza to, że błąd telecine w filmie jest poważniejszy. Może on być efektem następującego postępowania: film progresywny 23.976/24 FPS poddano procesowi 3:2 pulldown, a następnie dokonano konwersji z 29.97/30 FPS na 25 FPS jak gdyby był to materiał telewizyjny zamiast wykonać inverse telecine do 23.976/24 FPS i przyspieszyć do 25 FPS. Materiał taki może zawierać wiele "zlanych" półobrazów (powstałych wskutek konwersji metodą przystosowaną do materiałów telewizyjnych), przez co odtworzenie progresywnych klatek przez poszukiwanie pasujących do siebie półobrazów będzie niemożliwe. W takim wypadku użyjemy metody bobbingu (zmiany każdego półobrazu na pełną klatkę), a następnie usuniemy zduplikowane klatki. Otwieramy w VDM skrypt postaci: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym DGBob(order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF FDecimate(metrics=true) a następnie dla każdej klatki (w wybranym przedziale 50 klatek) zapisujemy, czy jest ona oryginalna, czy zduplikowana, np. OODODD, gdzie O oznacza klatkę oryginalną, zaś D duplikat. W określeniu, czy klatka jest oryginałem, czy duplikatem może nam pomóc wyświetlona na każdej klatce wartość metryki FDecimate() bardzo niskie wartości metric (poniżej 3) oznaczają duplikat, wyższe oryginał (wartość ta oznacza różnicę aktualnej klatki od poprzedniej). Z użyciem wartości metryki w celu rozpoznawania duplkatów na tym etapie pracy wiąże się jednak pewne ryzyko (patrz niżej), więc warto polegać na własnym wzroku. Następnie liczymy ilość klatek oryginalnych wśród tych 50 klatek i używamy tej wartości w skrypcie postaci: AVISource("•cie•ka\film.avi") Prawa autorskie © VideoAudio.pl 2001-2008 AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym DGBob(order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF FDecimate(rate=N) # parametr N to ilo•• oryginalnych klatek Zazwyczaj oryginalny materiał był kręcony przy 24 FPS, ale zdarzają się też progresywne materiały tworzone przy 25, 29.97 lub 30 klatkach na sekundę, a w przypadku bardzo starych filmów (np. niemych) wartośc FPS mogła wynosić od 12 do 28 - trzeba wziąć to pod uwagę podczas dobierania parametru rate dla FDecimate. Ponieważ jednak proces usuwania duplikatów przez FDecimate nie jest doskonały, a odtworzenie niektórych oryginalnych klatek z półobrazów (w procesie bobbingu) czasem jest niemożliwe (ponieważ wszystkie pochodzące z nich półobrazy zostały zlane z innymi), może się okazać, że trzeba zwiększyć wartość parametru rate aby uzyskać płynny obraz. Należy też pamiętać, że w scenach bardzo statycznych wartość metryki obliczana przez FDecimate będzie niska, co może spowodować uznanie oryginalnych klatek za duplikaty. Z kolei obecność "szumu" w klipie (np. pochodzącego z zakłóceń analogowej transmisji telewizyjnej) może sztucznie zwiększyć różnicę między identycznymi klatkami. Dlatego FDecimate umożliwia zmianę parametru threshold, który działa następująco: gdy wartość metryki dla danej klatki jest wyższa od threshold, klatka zostaje uznana za różną od poprzedniej. Aby ustalić odpowiednią wartość threshold dla klipu oglądamy w VDM skrypt: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym DGBob(order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF FDecimate(metrics=true) i sprawdzamy, jak wysokie są wartości metryki dla zduplikowanych klatek. Na przykład jeśli dla klatek będących duplikatami występują wartości metryki niższe od 2.5, zaś dla oryginałów wyższe od tej wartości, to threshold ustawiamy na 2.5. Oczywiście w scenach statycznych różnice pomiędzy poszczególnymi oryginalnymi klatkami są niskie, zaś w scenach dynamicznych wysokie, dlatego ustalenie idealnej wartości threshold często jest niemożliwe - w taki wypadku trzeba użyć wartości wyłapującej duplikaty w najbardziej statycznych scenach. Suplement A. Duplikaty po zastosowaniu Telecide() Czasem spotykane są klipy field-shifted PAL, w których zmiana wzorca 2:2 pulldown (patrz punkt 2a) następuje dokładnie dwa razy na sekundę. Dzieje się tak, ponieważ w tych klipach co dwunasty półobraz został zduplikowany aby z 48 półobrazów na sekundę (żródło to film progresywny 24 FPS z rozdzielonymi półobrazami) uzyskać 50 (czasem jest to nazywane field-dupe PAL). Wzorzec ten wygląda tak: 1t 2t ... 12t 12t 13t ... 23t 24t 1b 2b ... 12b 13b 14b ... 24b 24b Po wykonaniu procedury z punktu 2a uzyskamy: 1t 2t ... 12t 13t 14t ... 24t 24t 1b 2b ... 12b 13b 14b ... 24b 24b czyli: 1 2 ... 12 13 ... 24 24 Jak widać, co dwudziesta czwarta klatka jest zduplikowana (dzięki czemu mamy 25 FPS zamiast 24). Aby pozbyć się "zacięć", które podczas odtwarzania takiego klipu występują regularnie co sekundę, stosujemy: Decimate(cycle=25,quality=3) albo: FDecimate(rate=24) Prawa autorskie © VideoAudio.pl 2001-2008 Należy zaznaczyć, że tej samej metody użyjemy dla klipów typu frame-dupe PAL, czyli takich, które powstały poprzez duplikację co dwudziestej czwartej klatki materiału źródłowego (posiadającego 24 FPS). W przypadku frame-dupe PAL artefakty przeplotu nie występują, zatem przed Decimate() (lub FDecimate()) nie musimy używać Telecide(). Suplement B. Materiały hybrydowe (a) ...nakręcone dla systemu PAL Takie klipy zawierają materiał wideo kręcony przy 50 półobrazach na sekundę zawierający "naturalny" przeplot oraz materiał progresywny przyspieszony z 24 do 25 FPS (który może zawierać "sztuczny" przeplot w postaci field-shifted PAL). Jeśli w partiach pochodzących z progresywnego źródła widzimy artefakty przeplotu (w partiach wideo na pewno one wystepują), stosujemy: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym Telecide(order=?,guide=2,post=2,chroma=true,blend=false) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Wówczas Telecide() dopasuje półobrazy w partiach progresywnych odtwarzając pełne klatki, zaś w partiach wideo usunie przeplot metodą FieldDeinterlace(blend=false) (patrz też punkt 2a). Aby zamiast FieldDeinterlace(blend=false) zastosowano KernelDeint(), używamy: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym Telecide(order=?,guide=2,post=1,chroma=true,hints=true) KernelDeint(order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Ponieważ jednak Telecide() najpierw podejmuje próbę dopasowania półobrazów aby odtworzyć progresywną klatkę, a dopiero po znalezieniu najlepszego (tzn. zawierającego najmniej artefaktów przeplotu) dopasowania następuje usuwanie pozostających w klatce artefaktów przeplotu, fragmenty wideo mogą zawierać "zacięcia". Aby zmusić Telecide() do usunięcia przeplotu z partii wideo bez uprzedniego dopasowywania półobrazów, musimy odnaleźć w naszym klipie (np. przy pomocy VDM) numery klatek początkowych i końcowych tych partii. Przypuśćmy (przykładowo), że w naszym klipie fragmenty wideo to klatki 1500-7000 oraz 12400-25000. Tworzymy plik tekstowy o nazwie (na przykład) override.tel (w katalogu, w którym znajduje się nasz skrypt) i wpisujemy do niego następujące linijki (np. Notatnikiem): 1500,7000 c 1500,7000 + 12400-25000 c 12400-25000 + Przecinek pomiędzy numerami klatek oznacza cały przedział klatek (z klatką początkową i końcową włącznie). Litera c oznacza, że Telecide() ma użyć półobrazów górnego i dolnego z tej samej klatki (nie próbując znaleźć bardziej pasującego półobrazu w następnej i poprzedniej klatce), zaś + każe Telecide() uznać tą klatkę za zawierającą artefakty przeplotu i dokonać postprocessingu. Dokładny opis zawartości plików z podpowiedziami dla funkcji z pakietu decomb.dll znajduje się w dokumentacji do niego dołączonej. Następnie piszemy skrypt postaci: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym Telecide(order=?,guide=2,post=2,chroma=true,blend=false,ovr="override.tel") # parametr order ustawiamy na 1 dla TFF, 0 dla BFF albo: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym Telecide(order=?,guide=2,post=1,chroma=true,hints=true,ovr="•cie•ka\override.tel") Prawa autorskie © VideoAudio.pl 2001-2008 KernelDeint(order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Alternatywą dla Telecide() może być w tym przypadku skrypt: AVISource("•cie•ka\film.avi") AssumeTFF() # je•li stwierdzili•my TFF w punkcie pierwszym # AssumeBFF() je•li stwierdzili•my BFF w punkcie pierwszym DGBob(order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Zapewni to doskonałą płynność fragmentów wideo, jednak trzeba pamietać, że klip wynikowy będzie miał 50 FPS, zatem jego kompresja potrwa dłużej, zaś dekodowanie będzie wymagało większej mocy procesora niż w przypadku klipu 25 FPS stworzonego metodą pierwszą (Telecide()). (b) ...konwertowane z NTSC na PAL Materiały hybrydowe to często programy dokumentalne dotyczące powstawania filmu (tzw. "making of") umieszczane na DVD jako dodatki. W przypadku filmów hollywoodzkich (a takie stanowią większość na rynku DVD) programy te będą kręcone dla systemu NTSC i konwertowane na PAL. Takie klipy stanowią trudne wyzwanie, ponieważ zawarte w nich fragmenty pochodzące z filmu progresywnego zostały poddane 3:2 pulldown (podczas montażu programu w wersji NTSC), a następnie potraktowane jak gdyby były kręcone z przeplotem (podczas konwersji programu z NTSC na PAL), zatem w partiach pochodzących z filmu progresywnego wystąpią problemy opisywane w punkcie 2b. Z kolei półobrazy we fragmentach wideo będą zawierać "duchy" (efekt konwersji poprzez "zlewanie" półobrazów). Zastosowanie KernelDeint(), TomsMoComp(), GreedyHMA() czy FieldDeinterlace(blend=false) najprawdopodobniej spowoduje "zacięcia" we fragmentach filmowych, zaś FieldDeinterlace(blend=true) spotęguje efekt "duchów" zarówno w partiach wideo, jak i filmowych. Użycie DGBob() da w miarę płynny obraz, lecz również spowoduje "duchy" (bardziej widoczne w partiach filmowych), zaś późniejsze zastosowanie FDecimate() spowoduje wyrażne "zacięcia" we fragmentach wideo. Gdy zależy nam na uzyskaniu znośnego rezultatu przy 25 FPS, możemy odnaleźć numery klatek poczatkowych i końcowych wszystkich fragmentów filmowych i zastosować metodę z punktu 2b (pamietając, że FDecimate() musimy zastosować parametr rate równy 25, ewentualnie 24 i później użyć AssumeFPS(25,true) przetwarzając dźwięk razem z obrazem), zaś dla fragmentów wideo jedną z metod usuwania "naturalnego" przeplotu dających 25 FPS (np. KernelDeint(), TomsMoComp(), GreedyHMA(), FieldDeinterlace(blend=false), SmoothDeinterlace(doublerate=false), DGBob(mode=0)). Jeśli np. klatki 0-1000 pochodzą z materiału filmowego, a 1001-2000 to materiał wideo, skrypt może wyglądać tak: Clip=AVISource("•cie•ka\film.avi") Clip=AssumeTFF(Clip) # je•li stwierdzili•my TFF w punkcie pierwszym # Clip=AssumeBFF(Clip) je•li stwierdzili•my BFF w punkcie pierwszym Clip1=Trim(Clip,0,1000) Clip2=Trim(Clip,1001,2000) Clip1=DGBob(Clip1,order=?) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Clip1=FDecimate(Clip1,rate=25) Clip2=KernelDeint(Clip2,order=?,sharp=true,threshold=20) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Clip=AlignedSplice(Clip1,Clip2) Return Clip (c) logo wytwórni z przeplotem, film progresywny Czasem do edycji DVD filmu kinowego wytwórnia "dokleja" na poczatku lub końcu swoje logo z "naturalnym" przeplotem. Tym razem sprawa jest prosta. Znajdujemy numery początkowej i końcowej klatki logo z przeplotem (przypuśćmy dla przykładu, że to klatki 0 i 200) i piszemy skrypt: Clip=AVISource("•cie•ka\film.avi") Clip=AssumeTFF(Clip) # je•li stwierdzili•my TFF w punkcie pierwszym # Clip=AssumeBFF(Clip) je•li stwierdzili•my BFF w punkcie pierwszym Clip1=Trim(Clip,0,200) Clip2=Trim(Clip,201,FrameCount(Clip)-1) Clip1=KernelDeint(Clip1,order=?,sharp=true,threshold=20) # parametr order ustawiamy na 1 dla TFF, 0 dla BFF Clip=AlignedSplice(Clip1,Clip2) Prawa autorskie © VideoAudio.pl 2001-2008 Return Clip Oczywiście wybór metody usuwania przeplotu z logo jest dowolny (nie musi być to KernelDeint()), byle tylko nie zmieniała ona wartości FPS. Może się też zdarzyć, że logo zawiera "naturalny" przeplot, zaś film to field-shifted PAL. Wtedy w powyższym skrypcie zastosowalibyśmy dla Clip2 metodę opisaną w punkcie 2a. Epilog Jak widać z powyższych przykładów, temat inverse telecine jest niesłusznie ograniczany do systemu NTSC - w systemie PAL proces ten bywa tak samo, a nawet bardziej skomplikowany. Niemożliwe jest opisanie wszystkich możliwych patologii, na jakie możemy się natknąć przetwarzając materiały w PALu pochodzące ze źródeł progresywnych, dlatego ów poradnik należy traktować jako zachętę do dalszych eksperymentów, nie zaś jak zamknięte kompendium wiedzy. Prawa autorskie © VideoAudio.pl 2001-2008