Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage
Register FAQ Calendar Today's Posts Search

 
 
Thread Tools Search this Thread Display Modes
Prev Previous Post   Next Post Next
Old 27th March 2021, 11:27   #1  |  Link
Emulgator
Big Bit Savings Now !
 
Emulgator's Avatar
 
Join Date: Feb 2007
Location: close to the wall
Posts: 1,545
StrongHaloGhostDeconvolution.avs

Herewith I open a separate thread about abovementioned script which helped getting rid of disgusting ghosting halos.
Dont take the given values as granted to work with your particular video, these have worked for one special case only.
It takes lengthy manual tailoring, but delivers outstanding results. Maybe it can be developed further.

Code:
#€€€€€€€€€€€€€€€€€€€€€€€€   Start of Emulgator's Avisynth Bergwerk "StrongHaloGhostDeConvolution.avs" from 2021-03-26   €€€€€€€€€€€€€€€€€€€€€€€€€€€
# ------------------------- (This is the snippet by .mp4guy from where it started) ----------
# string1 = string(" 0 -20 28 -32 36 36 128 128 72 -56 12 12 -4 ")
# mt_convolution(horizontal=" "+string(string1)+" ", vertical=" 1 ", u=3, v=3)
# ----------------------------------------------------------------------------------------
# StrongHaloGhostDeConvolution.avs
# 2021-03-26 by Emulgator
#
# Das vorliegende Script arbeitet in AviSynth64 (getestet ab 3.6.2) mit 16 bit Auflösung und befaßt sich erfolgreich mit der Auskompensation
# von besonders groben Schärfungs-oder Echoartefakten, wie sie bei Video-Aufzeichnungen früher Analog-Camcorder auftraten.
# Die Anwendung bisher üblicher De-Halo-Algorithmen konnte dort nicht befriedigen, da diese i.d.R. nicht imstande sind,
# Halos größerer Ausdehnung ohne starken Detailverlust zu bekämpfen.
# ----------------------
# Lösungsansatz: Verwendung von Punkt für Punkt manuell angepaßten Faltungsfiltern größerer Länge.
# In der Regel treten Analog-Schärfungs-oder Echoartefakte kausalitätsbedingt zeitlich immer nach einem auslösenden Ereignis auf,
# bei rechtslaufender Scanrichtung also einer Kante rechts nachfolgend.
# Damit ist ein asymmetrischer Korrekturkernel zu erwarten, welcher hauptsächlich Anzapfungsfaktoren links vom aktuellen Pixel besetzt.
# (Eine analytische Lösung wird hier nicht a priori versucht, steht aber jedem offen, der dies versuchen will.)
#
# Eine prinzipbedingte Eigenheit der mt_convolution unter AviSynth ergibt, daß das Ergebnisvideo in YUV keine negativen Werte enthalten kann.
# Daraus ergab sich die Notwendigkeit einer betragsorientierten Aufteilung der Korrektur in 2 Kompensationsvorgänge:
# Der erste Korrekturgang arbeitet mit den Beträgen der positiv ausfallenden 1. horizontalen Ableitungen,
# der zweite mit den Beträgen der negativ ausfallenden 1. horizontalen Ableitungen.
# Dies bedient 1. die Notwendigkeit der vollständigen vorherigen Auskompensation
# der ansonsten erneut fehlereinbringenden Rückgangsflanken der Fehlerantwort aus positiven Gradienten.
# Erst dann kann im 2. Pass die Suche nach "echten" (im gewünschten Bildinhalt befindlichen) negativen Gradienten beginnen. 
# (Das Problem existiert umgekehrt zwar auch, tritt aber in dieser Reihenfolge nicht so prominent auf.)
# 2. Dabei erarbeitet man sich  "en passant" den Luxus der nun für positive und negative Gradienten getrennt verfügbaren Parametrierung.
# --------------------------
# Ermitteln der geeigneten Filterfolge:
# Quellvideo -> Abspalten Hilfsvideo -> Farbraum-Reduktion auf Y16
# -> Bilden der Beträge der positiv ausfallenden räumlichen 1.Ableitung in horizontaler Richtung = scharfes positives Ableitungsvideo
# -> Manuelles Vorformen einer primitiven Kompensationsfunktion durch Faltungsvektor
# -> Globale Vor-Skalierung des Überlagerungsfaktors per Gain = geglättetes positives Ableitungsvideo
# -> probeweise Überlagerung (Overlay) des geglätteten positiven Ableitungsvideos auf das Quellvideo
# -> Probeweises Schieben über die passende x-Bezugsspalte <-> Ausprobieren der Anzapfungsorte im Faltungsvektor 
# <-> probeweise x-Verschiebungskorrektur im Overlay <-> finale Anpassung der Anzapfungspegel im Faltungsvektor unter Kontrolle im Overlay.
# ---------------------------
# Vorbereitung: Ermitteln der Halofehler-Ausdehnung d, danach die Faltungs-Matrix und Größe mindestens (2*d)+1  vorgeben.
# Ersteckt sich also ein Halofehler horizontal über 14 Pixel, gibt man einen 29 Parameter langen Vektor in x-Richtung vor.
# Dann werden die Anzapfungwerte sukzessiv durch Probieren mit Anfangswert Mittelanzapfung = 1 ermittelt.
# Erst wenn der erste Teil perfekt auskompensiert ist, wird der 2.Teil gelingen !
# ---------------------------
# Bildfehleranalyse
# Die unbekannte Videoquelle war vermutlich eine frühe Amateur-SONY im Handtaschenformat.
# Diese Cam A wird "PAL-Stronghalo" benannt.
# Einer der zuerst auszukompensierenden Hauptfehler des vorliegenden PAL-Videos:
# Der zu kompensierende Fehler taucht nur in der Y-Komponente auf
# und folgt der 1.Ableitung von Y, die invertiert 7 Pixel später als negiertes und verschmiertes Echo auftaucht.
# Positive und negative Gradienten tauchen verschieden verschmiert auf, die Gesamtfehlerlänge erstreckt sich jeweils über 14 horizontale Pixel.
# Fehlerlänge 1% der PAL-Zeilenlänge Zeilenfrequenz 1MHz/64 = 15625Hz 64µs = 640ns.
# Pixelrate PAL: 720x576 = 414720 Pixel * 25 = 10.368.000 pix/s Netto.
# Es ist aber ein 625-Zeilen-System, also Scan-Timing 720x625x25 = 1/11.250.000s = 88ns/Pixel * 7 =620ns Delay Duration / 1240ns Fault Duration.
#
# Beschreibung der horizontalen Halo-Fehler an frame 924
# Ein Dunkel->Hell Eingangssprung von Sollwert Y=16 auf Sollwert Y=106 (deltaY=+90) ergibt eine 14 Pixel lange Impulsantwort !
# Anstiegsflanke beginnend bei x=9,Y=16: 
# Folge der Abtastwerte 16,62,106,121,111,106,96,86,81,84,86,90,94,98,104,106, Zielwert 106
# Überschwingantwort mit Maximum nach 3 Pixeln, eingeschwungen nach 5 Pixeln:
# x+1: -> Y/2;  x+2 -> Y+0;  x+3 -> Y+10..15;  x+4 -> Y+5;  x+5 -> Y+0
# Unterschwingantwort mit Maximum nach 8 Pixeln ab x+6 bis x+14 länger negativ gerichtet:
# x+6 -> Y-10, x+7 -> Y-20,  x+8  -> -25, x+9 -> Y-22,  x+10 -> Y-20, x+11 -> Y-16 , x+12 -> Y-12 , x+13 -> Y-8 , x+14 -> Y -2, x+15 -> Y-0
#-------
# Ein Hell->Dunkel Eingangssprung von Sollwert Y=150 auf Sollwert Y=20 (deltaY=-130) ergibt eine 14 Pixel lange Impulsantwort !
# Abfallflanke in Zeile 414, beginnend bei x=425: (x=425,y=414): 
# Folge der Abtastwerte 150,130,107,88,63,46,38,40,51,62,64,58,30,24,22,20,  Zielwert 20
# Unterschwingantwort mit 1.Zwischenminimum nach 6 Pixeln,
# Rückschlag mit Maximum Y+44 nach 10 Pixeln, eingeschwungen auf Endwert nach 15 Pixeln 
#
# Probier-Methodik: Vorbereitung: Ermitteln der Halofehler-Ausdehnung d
# Nun die Matrix mindestens genau so groß vorgeben. Da sie auto-zentriert berechnet wird, je 1x in jede Richtung.
# Soll das Quellbild Teil der Faltung sein, ist der mittlere Koeffizient <>0, also Länge (2*d)+1. 
# Ersteckt sich der Halofehler horizontal über 14 Pixel, gibt man also einen 29 Parameter langen Vektor vor.
#
# Jetzt gehts los !
SetFilterMTMode("DEFAULT_MT_MODE", 2)
SetFilterMTMode("LWLibavVideoSource", 3)
ShowCurve3=false
ShowQTGMCSettings=false
#va=AviSource("D:\source.avi").ConvertBits(bits=16).AssumeTFF()
#aa=AviSource("D:\source.avi")
va=FFVideoSource("D:\source.avi").ConvertBits(bits=16).AssumeTFF()
aa=FFAudioSource("D:\source.avi")
#va=LWLibavVideoSource("D:\source.avi", prefer_hw=1, format="YUV422P16").AssumeTFF()
#aa=LWLibavAudioSource("D:\source.avi")
AudioDub(va,aa)
SeparateFields()
bobby=last
#bobby=last.SuperXBR(str=5, fwidth=720)
#bobby=last.SuperResXBR(passes=5, str=1, fwidth=720)
#bobby=last.SuperRes(fwidth=720, str=1, upscale ="""nnedi3_rpow2(2, cshift="Spline16Resize")""")
bobbw=bobby.ConvertToY()
# Wir arbeiten ausschließlich in Y. Die beschriebenen Halos existieren meist nur in Y. (U und V bieten kaum hinreichend Auflösung, um störende Überschwinger zu ermöglichen.)
#
# Übungsabschnitt ! mt_convolution ist autoscaling, vergibt es also, wenn man die Regel der Summe = 1 nicht beachtet.
# Probeweise alle Positionen mit 0 besetzen. Ein YUV-Video ergäbe die illegale Farbe 0,0,0 (in der Preview als Grün wiedergegeben).
# Vorher auf Y16 konvertieren, dann ergibt es legale Farben. In der AvsPmod-Preview sollte sich ein schwarzes Y16-Bild mit der Farbe 0,-1,-1 ergeben.
string000 = string("0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0")
test000=mt_convolution(bobbw, horizontal=" "+string(string000)+" ", vertical=" 1 ", u=3, v=3)
# Probeweises Einsetzen einer mittleren 1 sollte das Originalbild in Y16 ergeben.
string010 = string("0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0")
test010=mt_convolution(bobbw, horizontal=" "+string(string010)+" ", vertical=" 1 ", u=3, v=3)
# Probeweises Einsetzen zweier 1 einmal links, einmal rechts sollte zwei verschobene Y16-Originalbilder mit je halber Leuchtkraft ergeben.
string101= string("1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1")
test101=mt_convolution(bobbw, horizontal=" "+string(string101)+" ", vertical=" 1 ", u=3, v=3)
# Probeweise die mittleren Positionen mit -1+1 besetzen. Es sollte in der AvsPmod-Preview die Y16-Abbildung der positiven Gradienten in weiß auf schwarz  ergeben.
stringn1p1 = string("0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0")
testn1p1=mt_convolution(bobbw, horizontal=" "+string(stringn1p1)+" ", vertical=" 1 ", u=3, v=3)
# Probeweise die mittleren Positionen mit +1-1 besetzen. Es sollte in der AvsPmod-Preview die Y16-Abbildung der negativen Gradienten in weiß auf schwarz  ergeben.
stringp1n1 = string("0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0")
testp1n1=mt_convolution(bobbw, horizontal=" "+string(stringp1n1)+" ", vertical=" 1 ", u=3, v=3)
#return(weave(test000))
#return(weave(test010))
#return(weave(test101))
#return(weave(testn1p1))
#return(weave(testp1n1))
#
# Jetzt gehts aber echt los !
#
derivkernpos = string("-1 1 0") # ergibt die Beträge der positiv ausfallenden 1. Ableitungen. Gibt man einen 2er Kernel vor, wird dieser rechts mit einer Null aufgefüllt)
derivkernneg = string("1 -1 0") # ergibt die Beträge der negativ ausfallenden 1. Ableitungen
################################################
# Cam A is the "Amateur" cam, oversaturated grainy picture with strong halos:  positive gradients give a smooth dark echo 5..14 pixels later, negative gradients give a bright echo 6..9 pixels later
aderivpos=mt_convolution(bobbw, horizontal=" "+string(derivkernpos)+" ", vertical=" 1 ", u=3, v=3, saturate=true)
# Vorgabe der horizontalen Glättungsfunktion für die zur Abdunklung von Überschwingern verwendeten positiven horizontalen Ableitungen
asmoothkernposdark = string("0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0") #damit machen wir bei diesem Video nichts. Ist für später.
ahaloposdark=mt_convolution(aderivpos, horizontal=" "+string(asmoothkernposdark)+" ", vertical=" 1 ", u=3, v=3)
ahaloposdarkup=SmoothCurve16(ConvertToStacked(ahaloposdark), HQ=true, interp=100, Ycurve="0-0;15360-30720;65535-65535", Ucurve="0-0;65535-65535", Vcurve="0-0;65535-65535").ConvertFromStacked()
# Vorgabe der horizontalen Glättungsfunktion für die zur Aufhellung von Unterschwingern verwendeten positive horizontale Ableitungen
# Probeweises Besetzen mit einer zentralen 1 und Verschieben, bis man den Rhythmus des Halos trifft. 
# Dann Werte links hinzufügen, auch mal rechts. Koeffizienten abstufen, bis die zwei verschobenen Originalbilder sich passend mischen.
# In der Regel treten Analog-Schärfungs-oder Echoartefakte prinzipbedingt immer rechts nach einer Kante auf.
# Damit werden zur Korrektur nur Faktoren links vom aktuellen Pixel benötigt.
asmoothkernposbright = string("0.08, 0.12, 0.18, 0.24, 0.36, 0.48, 0.6, 0.7, 0.8, 1.0, 1.2, 1.0, 0.8, 0.6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0")
ahaloposbright=mt_convolution(aderivpos, horizontal=" "+string(asmoothkernposbright)+" ", vertical=" 1 ", u=3, v=3)
ahaloposbrightup=SmoothCurve16(ConvertToStacked(ahaloposbright), HQ=true, interp=100, Ycurve="0-0;15360-30720;65535-65535", Ucurve="0-0;65535-65535", Vcurve="0-0;65535-65535").ConvertFromStacked()
apd=Overlay(bobby, ahaloposdarkup, x=0,opacity=0.0,mode="subtract")
# Zur Kompensation von Überschwingern werden aus positiven Ableitungen resultierende Y-Werte subtrahierend (abdunkelnd) überlagert,  Erhöhen von x schiebt das Overlay nach rechts.
apb=Overlay(apd, ahaloposbrightup, x=2,opacity=1.0,mode="add")
# Zur Kompensation von Unterschwingern werden aus positiven Ableitungen resultierende Y-Werte addierend (aufhellend) überlagert,  Erhöhen von x schiebt das Overlay nach rechts.
apy=ConvertToY(apb)
aderivneg=mt_convolution(apy, horizontal=" "+string(derivkernneg)+" ", vertical=" 1 ", u=3, v=3, saturate=true)
asmoothkernneg = string("0, 0, 0, 0, 0, 0, 0, 0, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0")
# Gibt die horizontale Glättungsfunktion für die negative horizontale Ableitung vor: linke Seite abklingende Flanke, rechte Seite ansteigende Flanke 
ahaloneg=mt_convolution(aderivneg, horizontal=" "+string(asmoothkernneg)+" ", vertical=" 1 ", u=3, v=3)
ahalonegup=SmoothCurve16(ConvertToStacked(ahaloneg), HQ=true, interp=100, Ycurve="0-0;15360-30720;65535-65535", Ucurve="0-0;65535-65535", Vcurve="0-0;65535-65535").ConvertFromStacked()
camadehalo=Overlay(apb, ahalonegup, x=5,opacity=1.0,mode="subtract")
# Hier werden aus negativen Ableitungen resultierende Y-Werte subtrahierend (abdunkelnd) überlagert,  Erhöhen von x schiebt das Overlay nach rechts.
camadehalocorr=SmoothCurve16(ConvertToStacked(camadehalo),HQ=true, interp=100, limiter=false, debug=ShowCurve3, screenW=1280, screenH=768, \
Ycurve="0-0;5000-7000;25000-25000;32767-32767;45000-45000;65535-65535", \
Ucurve="0-0;20000-22000;32767-32767;50000-42000;65535-62000", \
Vcurve="0-0;20000-15000;32767-32767;50000-47000;65535-65535").ConvertFromStacked()
#return(weave(bobby)) # So sah die Quelle aus.
#return(weave(bobbw)) # So sah der Schwarz-Weiß-Auszug derQuelle aus.
#return(SmoothCurve16(ConvertToStacked(weave(aderivpos)), Ycurve="0-0;15360-61440;65535-65535", Ucurve="0-0;65535-65535", Vcurve="0-0;65535-65535").ConvertFromStacked())
# 4x versteilerte Ansicht der positiven 1.Ableitung
#return(SmoothCurve16(ConvertToStacked(weave(ahaloposbrightup)), Ycurve="0-0;15360-61440;65535-65535", Ucurve="0-0;65535-65535", Vcurve="0-0;65535-65535").ConvertFromStacked())
# 4x versteilerte Ansicht der gefilterten positiven 1.Ableitung
#return(SmoothCurve16(ConvertToStacked(weave(aderivneg)), Ycurve="0-0;15360-61440;65535-65535", Ucurve="0-0;65535-65535", Vcurve="0-0;65535-65535").ConvertFromStacked())
# 4x versteilerte Ansicht der negativen 1.Ableitung
#return(SmoothCurve16(ConvertToStacked(weave(ahalonegup)),Ycurve="0-0;15360-61440;65535-65535", Ucurve="0-0;65535-65535", Vcurve="0-0;65535-65535").ConvertFromStacked())
# 4x versteilerte Ansicht der gefilterten negativen 1.Ableitung
#return(weave(apb))# Ansicht nach dem 1.Kompensationsschritt (Kompensation der Halos aus positiven Gradienten)
#return(weave(camadehalo))# Ansicht nach dem 1+2.Kompensationsschritt (Kompensation der Halos aus positiven, dann aus negativen Gradienten)
weave(camadehalocorr) # Farbkorrigiertes Kompensations-Endergebnis Camera A (Parameter sind dem Video anzupassen, hier nur als Beispiel...)
ConvertToYUV422() # Aus 4:4:4 zurück zu 4:2:2
ConvertBits(bits=10)# Von 16-bit zurück zu 10-bit
Prefetch(24)
#€€€€€€€€€€€€€€€€€€€€€€€€   End of Emulgator's Avisynth Bergwerk "StrongHaloGhostDeConvolution.avs" from 2021-03-26    €€€€€€€€€€€€€€€€€€€€€€€€€€€
After approval the picture below will show the presumed step response and the fault to be compensated as a diagram of sample values.
Attached Images
 
__________________
"To bypass shortcuts and find suffering...is called QUALity" (Die toten Augen von Friedrichshain)
"Data reduction ? Yep, Sir. We're that issue working on. Synce invntoin uf lingöage..."

Last edited by Emulgator; 27th March 2021 at 12:06.
Emulgator is offline   Reply With Quote
 

Tags
convolution, ghosting, halo


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 03:54.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.