Ich würde es mit FixVHSoversharp 2.5 versuchen. Funktioniert hier sehr gut und lässt alles andere unverändert.
Die DLL ist auch in den üblichen avisynth Sammlungen, dort ist allerdings nirgends ein aktueller Link auf die Homepage.
Ich würde es mit FixVHSoversharp 2.5 versuchen. Funktioniert hier sehr gut und lässt alles andere unverändert.
Die DLL ist auch in den üblichen avisynth Sammlungen, dort ist allerdings nirgends ein aktueller Link auf die Homepage.
Lösung, erster Teil: erstellt Textdatei mit Duplicate Frames
Gut, dann versuche ich selbst eine Lösung. Das folgende Script durchsucht die source nach Duplicate frames und schreibt sie in die Datei dups.txt.
[B]frame position : gap-length : Ydiffpregap : Ydiffpostgap : marker[/B]57 10 3.217846 10.803629 104 1 4.960470 4.838520 107 1 7.204895 4.491889 ...
Neben Frame nummer und Länge des Aussetzers stehen hier auch die Ydifference vor und nach dem Aussetzer, damit später Szenenwechsel oder zu große Unterschiede von der Interpolation der Lücke ausgeschlossen werden können.
Hier das Script:
#http://forum.gleitz.info/showthread.php?45066-Duplicate-Frames-in-VHS-grabbings-interpolieren-die-zweite&p=422499&viewfull=1#post422499
#http://forum.doom9.org/showpost.php?p=380090&postcount=2
#OP 2011, v0.5
#YDifferenceFromPrevious() can ONLY be used within conditional functions, as it changes on every frame
#Also remember that conditional variables must be assigned bottom up.
#http://avisynth.org.ru/docs/english/corefilters/conditionalfilter.htm
global source1=AVISource("test79400.avi")
last=source1
ConvertToYV12() # YV12 needed for MVTools and for CCE Basic
global diffp=0
global diffn=0
global fp1=0
global dup_thresh=0.0001 #threshold, below threshold is considered as duplicate frame
global gap_pos=0 #Gap start
global gap_l=0 #Gap length
global pregap=0 #Gap YDifference before gap
global postgap=0 #Gap YDifference after gap
global gap_end=false # Bolean, triggers writing of gap properties into dup.txt file
global gapmarker="=" #Visual Gap length marker
#Test function: display parameter results visually
#............................................................................................................................................................
ScriptClip("""Subtitle("frame_number: "+String(fp1)+", YdiffP: "+String(diffp)+", YdiffN: "+String(diffn)) """)
ScriptClip("""Subtitle(x=8, Y=20,text_color=$FF4422,\
"pos: "+String(gap_pos)+", gap_l: "+String(gap_l)+", pregap: "+String(pregap)\
+", postgap: "+String(postgap)+", gapmarker: "+String(gapmarker) ) """)
#Display frame number and diffp, diffn
#............................................................................................................................................................
ScriptClip("f1()")
ScriptClip("f3()")
ScriptClip("f4()")
function f1(clip c) {
c=FrameEvaluate(c,"fp1=current_frame")
return(c)
}
function f3(clip c) {
c=FrameEvaluate(c,"diffp=YDifferenceFromPrevious(source1)")
return(c)
}
function f4(clip c) {
c=FrameEvaluate(c,"diffn=YDifferenceToNext(source1)")
return(c)
}
#Search gaps with duplicate frames and write dups.txt
#............................................................................................................................................................
ScriptClip("fg1a()")
ScriptClip("fg1b()")
ScriptClip("fg1c()")
ScriptClip("fg2()")
ScriptClip("fg3a()")
ScriptClip("fg3b()")
ScriptClip("fg3c()")
colon=" " #define colon
#doesn't work
gapmarker=LeftStr("=========",gap_l) #visually marking gap length
WriteFileStart("dups.txt", """ "frame number : gap-length : Ydiffpregap : Ydiffpostgap : marker" """)
WriteFileIf("dups.txt", "gap_end== true", "gap_pos", "colon", "gap_l", "colon", "pregap", "colon","postgap", "colon", "gapmarker")
#begin gap: gap_pos=current_frame, gap_l=1
#YDifferenceFromPrevious() > dup_thresh && YDifferenceToNext() < dup_thresh ?
function fg1a(clip c) {
c=FrameEvaluate(c,"ydfp=YDifferenceFromPrevious(source1)"\
+"ydfn=YDifferenceToNext(source1)" \
+"gap_pos= ydfp > dup_thresh && ydfn < dup_thresh ? current_frame+1 : gap_pos" )
return(c)
}
function fg1b(clip c) {
c=FrameEvaluate(c,"ydfp=YDifferenceFromPrevious(source1)"\
+"ydfn=YDifferenceToNext(source1)" \
+"gap_l= ydfp > dup_thresh && ydfn < dup_thresh ? 0 : gap_l" )
return(c)
}
function fg1c(clip c) {
c=FrameEvaluate(c,"ydfp=YDifferenceFromPrevious(source1)"\
+"ydfn=YDifferenceToNext(source1)" \
+"pregap= ydfp > dup_thresh && ydfn < dup_thresh ? ydfp : pregap" )
return(c)
}
#middle gap: gap=gap+1
#YDifferenceFromPrevious() < dup_thresh && YDifferenceToNext() < dup_thresh ?
function fg2(clip c) {
c=FrameEvaluate(c,"ydfp=YDifferenceFromPrevious(source1)"\
+"ydfn=YDifferenceToNext(source1)" \
+"gap_l= ydfp < dup_thresh && ydfn < dup_thresh ? gap_l+1 : gap_l" )
return(c)
}
#end gap: gap=gap+1 , call writefileif,
#YDifferenceFromPrevious() < dup_thresh && YDifferenceToNext() > dup_thresh ?
function fg3a(clip c) {
c=FrameEvaluate(c,"ydfp=YDifferenceFromPrevious(source1)"\
+"ydfn=YDifferenceToNext(source1)" \
+"gap_l= ydfp < dup_thresh && ydfn > dup_thresh ? gap_l+1 : gap_l" )
return(c)
}
function fg3b(clip c) {
c=FrameEvaluate(c,"ydfp=YDifferenceFromPrevious(source1)"\
+"ydfn=YDifferenceToNext(source1)" \
+"gap_end= ydfp < dup_thresh && ydfn > dup_thresh ? true : false" )
return(c)
}
function fg3c(clip c) {
c=FrameEvaluate(c,"ydfp=YDifferenceFromPrevious(source1)"\
+"ydfn=YDifferenceToNext(source1)" \
+"postgap= ydfp < dup_thresh && ydfn > dup_thresh ? ydfn : postgap" )
return(c)
}
Alles anzeigen
Dies lässt sich sicher vereinfachen und eleganter schreiben.
Diese Version hat noch zwei Fehler:
Ich bitte um Hilfe. Danke.
Lösung gefunden
MorphDups ist ein Avisynth Skript, das solche doppelten Frames findet. Es erzeugt bei der Suche ein zweites Skript (morphmydups.avs) mit einer Funktion, die diese Duplikate ersetzt. Dazu wird die Funktion Morph von Mud Funky genutzt, die künstliche Zwischenbilder errechnet, und mit ihnen Duplikate ersetzt.
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:
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
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.