USB Video Grabber ersetzen automatisch gestörte Bilder durch Kopien des letzten intakten Frames. Bei Grabbings von VHS tritt diese Situation regelmäßig auf. In einer Videokassette, die von einem billigen Recorder ohne Synchronspur aufgezeichnet wurde, hatte ich auf 80 Minuten laufzeit etwa 2000 Duplicate Frames. Diese Duplicate treten meist allein auf. In selten Fällen gibt es auch Serien bis zu 10 aufeinanderfolgenden identische Kopien.
..abc...........opq..stuvwxyz......... Originalframes des Films (gute Frames)
..a-c...........o-q..s------z......... VHS mit Dropouts (Bandknitter)
..aac...........ooq..sssssssz......... Ausgabe vom USB Video Grabber (Duplicate statt Originalframes)
Die Duplikate sind 100% des Vorgängerbildes und können daher nachträglich mit YDifferenceFromPrevious gefunden und genau lokalisiert werden.
Für das Problem wurden hier und hier Lösungen gezeigt, die einzelne Duplicate Frames durch ein aus Vorgänger und Nachfolger interpoliertes Zwischenbild ersetzen.
Um in einem Testklip einen längeren Aussetzer zu korrigieren, habe ich Didées Vorschlag auf 10 Frames angepasst.
#http://forum.doom9.org/showthread.php?t=154022
#http://forum.doom9.org/showthread.php?t=152758
#Recover10Frames
Loadplugin ("mvtools2.dll")
AVIFileSource("test79400.avi")
ConvertToYV12()
#interpolation for 10 Duplicate frames
#............................................................................................................................................................
function Recover10Frames(clip Source, int N)
{
# N is number of the first frame in Source that needs replacing.
# Frames N ... and N+10(O) will be replaced.
Source
Super10=msuper()
bv=manalyse(Super10, isb=true, delta=11)
fv=manalyse(Super10, isb=false, delta=11)
Candidate1 = mflowinter(super10, bv, fv, time=100/11, ml=100)
Candidate2 = mflowinter(super10, bv, fv, time=2*100/11, ml=100)
Candidate3 = mflowinter(super10, bv, fv, time=3*100/11, ml=100)
Candidate4 = mflowinter(super10, bv, fv, time=4*100/11, ml=100)
Candidate5 = mflowinter(super10, bv, fv, time=5*100/11, ml=100)
Candidate6 = mflowinter(super10, bv, fv, time=6*100/11, ml=100)
Candidate7 = mflowinter(super10, bv, fv, time=7*100/11, ml=100)
Candidate8 = mflowinter(super10, bv, fv, time=8*100/11, ml=100)
Candidate9 = mflowinter(super10, bv, fv, time=9*100/11, ml=100)
Candidate10 = mflowinter(super10, bv, fv, time=10*100/11, ml=100)
Source.trim(0,N-1)\
++ Candidate1.trim(N-1,-1) \
++ Candidate2.trim(N-1,-1) \
++ Candidate3.trim(N-1,-1) \
++ Candidate4.trim(N-1,-1) \
++ Candidate5.trim(N-1,-1) \
++ Candidate6.trim(N-1,-1) \
++ Candidate7.trim(N-1,-1) \
++ Candidate8.trim(N-1,-1) \
++ Candidate9.trim(N-1,-1) \
++ Candidate10.trim(N-1,-1) ++ Source.trim(N+10,0)
}
Recover10Frames(57)
#interpolation for 1 Duplicate frame
#............................................................................................................................................................
super = MSuper()
backward_vectors = MAnalyse(super, isb = true, delta=2) #produces a super clip
forward_vectors = MAnalyse(super, isb = false, delta=2) #produces motion vectors
inter = MFlowInter(super, backward_vectors, forward_vectors, time=50, ml=70) #pixel based motion compensation for 50% of time and ml=70
ConditionalFilter(inter.Loop(2,0,0), last, "YDifferenceFromPrevious", "<", ".001")
# testclip, source1, source2, filter, operator, value) ==> apply only to duplicates
#ConvertToRGB24() # for easy display in VirtualDub
Alles anzeigen
Wie lässt sich diese Funktion so schreiben, dass sie allgemein M Frames an Position N ersetzen kann?
Das Vorgehen per explizit aufzurufender Funktion hat noch zwei Mängel:
- es werden Szenenwechsel nicht erkannt. Fällt zufällig das nächste Frame nach den Dups auf einen Szenenwechsel, dann blendet das Script via Motionkompensation zwischen zwei Szenen über. In solchen Fällen sollte aber besser gar nichts passieren. Die Resultate sähen befremdlich aus.
- sollte es ein Möglichkeit geben, das Script automatisiert arbeiten zu lassen, um unterschiedlich lange Aussetzer automatisch zu reparieren.
Eine Lösung bestände darin, zweistufig zu arbeiten.
In einer Analyse wird erst eine Steuerdatei erzeugt, in denen Position und Anzahl der Dupes gelistet werden. Dabei werden Abschnitte bereits ausgeklammert, die mit einem Szenenwechsel beginnen oder enden. (Weil dann Interpolation keinen Sinn macht.)
In einem zweiten Schritt könnte dann die Steuerdatei via ConditionalReader() eingelesen werden und würde Interpolationsroutinen für 1...m Frames starten.
(siehe Beispiel auf http://avisynth.org/mediawiki/ConditionalReader)
Dies hätte diese Vorteile
- die Dupes werden in der Quelldatei genau gefunden
- die Interpolation kann sauber an der deinterlacten und gefilterten Variante erfolgen
- man kann "unglückliche" Stellen aus der interpolation ausklammern, indem die entsprechenden Positionen in der Steuerdatei gelöscht werden.
- die Steuerdatei ist damit gleichzeitig ein Index, um hinterher gezielt die reparierten Stellen via Framenummer visuell überprüfen zu können
Leider bin ich nicht in der Lage, so ein Script zu erstellen. Bedarf daran dürfte jeder haben, der USB Video Grabber verwendet.
Sorry, ich bin blutiger Anfänger mit Avisynth.
Lösung
MorphDups ist ein Avisynth Skript, das solche doppelten Frames findet. Es erzeugt bei der Suche ein zweites Skript (morphmydups.avs) mit einer Funktion, die solche Duplikate ersetzt. Dazu wird die Funktion Morph von Mud Funky genutzt, die künstliche Zwischenbilder errechnet, und mit ihnen Duplikate ersetzt.