Log in

View Full Version : Identify bad fields in a capture


lollo2
2nd January 2022, 18:48
In some of my last analog captures there is sometime a problem with a field (even or odd) beeing corrupt, probably because the VCR is starting to get old.

Here one example:

video https://drive.google.com/file/d/1wHXltGBQJQPC-z0-uOot5sj10qXmNfiK/view?usp=sharing

image https://drive.google.com/file/d/1CEPYr6oh8xHrMQuGmZxFRrIsOMAYOUIz/view?usp=sharing

Here another one:

image https://drive.google.com/file/d/16-2GRU7gWoyFe6Jmb7gnpcJTTp7OM9ln/view?usp=sharing

I generally fix such a problem replacing the bad field with a new field interpolated from previous and next.

I was thinking how to automatically detect such bad fields in the full capture with an AviSynth script, searching maybe for a vertical shif of the content (that always occurs when the field is corrupt), or a percentage of "white" variation between fields, or ..., and write to a file the corrupt frame/field number, in order to include this generated list in a second script to fix all of them with interpolation.

Any idea about defining a good pattern with AviSynth that could detect the problem?

real.finder
2nd January 2022, 21:09
maybe something like this
istff = GetParity()
BWDIF(-2)
SpotLess()
interlaced60or50(BFF=!istff)

lollo2
2nd January 2022, 21:41
Thanks for your reply!

Your code is a fix for the problem, while I need an idea to recognize the bad frames and write the frame number in a file for further processing.

StainlessS
2nd January 2022, 21:47
Post just a minute or so of the source, unprocessed. [not on youtube, maybe MediaFire]

EDIT: You could just try real.finder fix, and in scriptclip find difference between fixed and src,
and if above some threshold then write current_frame to frame file.

EDIT: I have no idea what interlaced60or50(BFF=!istff) is. [if it changes number of frames then above scriptclip thing will not work]

EDIT: https://forum.doom9.org/showthread.php?p=1824067#post1824067

# 60p or 50p progressive to interlaced

FUNCTION interlaced60or50(clip c1, bool "BFF") {
BFF = default ( BFF, false )
Ifrate = round(framerate(c1))==60 ? 1 : framerate(c1)==50 ? 2 : 3
assert(ifrate!=3 && c1.IsFrameBased, "only Frame Based with 50 or ~60 fps is allowed.")

desiredoutputfieldorder = BFF ? c1.AssumeTFF() : c1.AssumeBFF() # opposite to the desired output field order
outputfieldDoubleWeave = desiredoutputfieldorder.DoubleWeave()
return outputfieldDoubleWeave.SelectEvery(4,1)
}

lollo2
2nd January 2022, 22:00
here a segment of the raw capture: https://drive.google.com/file/d/1sbDyDOqpnLByAiF6WQMODWO6BQ52iL2T/view?usp=sharing

You could just try real.finder fix, and in scriptclip find difference between fixed and src,
and if above some threshold then write current_frame to frame file.

I need to pre-process the file to find all the bad fields before fixing them, in order to apply an automated procedure. Otherwise I have to carefully visually check hours of videos to find where the bad fields are located.

EDIT: or, as per your hint, if a procedure exists that, applied to the whole video, is able to touch only the damaged fields, then doing the difference between before and after fix I can later identify the frames. But I am not sure that such a procedure can be written.

StainlessS
2nd January 2022, 22:15
how bout something like this.


/*
RT_FrameDifference(clip c,clip c2,int "n"=current_frame,int "n2"=current_frame,Float "ChromaWeight"=1.0/3.0,
int "x"=0,int "y"=0,int "w"=0,int "h"=0,int "x2"=x,int "y2"=y,bool "Altscan"=false,bool "ChromaI"=false,
Int "Matrix"=(Width>1100||Height>600)?3:2)
Returns difference between clip c frame n area x,y,w,h and clip c2 frame n2 area x2,y2,w,h. (range 0.0 -> 255.0).

Args:-
c, c2, clips to difference.
n, default = current_Frame. Frame from clip c.
n2, default = current_Frame. Frame from clip c2.
ChromaWeight, default 1.0/3.0. Range 0.0 -> 1.0.
Y8, returns same as LumaDifference. ChromaWeight ignored.
YUV,
Weighting applied YUV chroma:- (1.0 - ChromaWeight) * Lumadif + ChromaWeight * ((Udif + Vdif)/2.0).
RGB,
If ChromaWeight > 0.0, then returns same as RT_RGBDifference() [ie average RGB pixel channel difference].
If ChromaWeight == 0.0, then returns same as RT_LumaDifference() using Matrix arg to convert RGB to YUV-Y Luma.
x,y,w,h. All Default 0 (full frame), for clip c.
x2,y2. x2 defaults x, y2 defaults y, for clip c2.
Altscan, default false. If true then scan only every other scanline starting at clip c y coord, and clip c2 y2 coord.
ChromaI, default false. If YV12 and ChromaI, then do YV12 interlaced chroma scanning.
Ignored if not YV12. Both YV12 clips must be same, cannot difference one that is progressive and one that has interlaced chroma.
Matrix, default (c.Width>1100||c.Height>600||c2.Width>1100||c2.Height>600)?3:2
Conversion matrix for conversion of RGB to YUV-Y Luma. 0=REC601 : 1=REC709 : 2 = PC601 : 3 = PC709.
Default = (c.Width > 1100 OR c.Height>600 OR c2.Width > 1100 OR c2.Height>600) then 3(PC709) else 2(PC601). YUV not used
Matrix only Used if RGB and ChromaWeight == 0.0, where returns same as RT_LumaDifference().
Note, 'x2' and 'y2' default to 'x' and 'y' respectively.
v2.0, c and c2 need not be same dimensions but BEWARE, x2 and y2 default to x and y also w and h default to 0
which is converted to c.width-x and c.height-y, may be best to provide x2, y2, w and h where c2 not same dimensions as c.

*/

AviSource(".\defect_field.mp4.AVI")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.

RT_FileDelete(Frames)


SSS = """
n = current_frame
Y = RT_FrameDifference(Last,Last,n=n,n2=n,y=0,y2=1,AltScan=True)
if(Y > TH) {
RT_WriteFile(Frames,"%d",n,Append=True)
}
Subtitle(RT_String("%d] Y=%f",n,Y))
"""

ScriptClip(SSS)

StainlessS
2nd January 2022, 22:28
Maybe safer,


#AviSource(".\defect_field.mp4.AVI")
AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.
CHROMAI = IsYV12


RT_FileDelete(Frames)


SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=0,y2=1,AltScan=True,ChromaI=CHROMAI) # Diff top and bottom fields of frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=0,y2=0,ChromaI=CHROMAI) # Diff Prev and curr
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=0,y2=0,ChromaI=CHROMAI) # Curr and Next

if(Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH) {
RT_WriteFile(Frames,"%d",n,Append=True)
}
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt))
"""

ScriptClip(SSS)

EDIT: Added CHROMAI.
https://i.postimg.cc/vTt2z9F9/Test-00.jpg (https://postimages.org/)

StainlessS
2nd January 2022, 22:38
mod

#AviSource(".\defect_field.mp4.AVI")
AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.
CHROMAI = IsYV12


RT_FileDelete(Frames)


SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=0,y2=1,AltScan=True,ChromaI=CHROMAI) # Diff top and bottom fields of frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Diff top Prev and top curr fields
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Curr top and Next top fields

if(Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH) {
RT_WriteFile(Frames,"%d",n,Append=True)
}
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt))
"""

ScriptClip(SSS)

Changed compare of prev -> curr and Curr next to top fields only. [I had switched off AltScan - should not have done that]
Better numbers.

https://i.postimg.cc/0yTGzQhq/Test-01.jpg (https://postimages.org/)

lollo2
2nd January 2022, 22:46
First of all, thanks a lot for your effort.

Using the following:

loadPlugin("C:\Users\giuse\Desktop\RT_Stats_25_26_x86_x64_dll_v2.00Beta12_20181125\RT_Stats_25&26_x86_x64_dll_v2.00Beta12_20181125\Avisynth26\RT_Stats_x86.dll")

AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.
CHROMAI = IsYV12


RT_FileDelete(Frames)


SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=0,y2=1,AltScan=True,ChromaI=CHROMAI) # Diff top and bottom fields of frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=0,y2=0,ChromaI=CHROMAI) # Diff top Prev and top curr fields
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=0,y2=0,ChromaI=CHROMAI) # Curr top and Next top fields

if(Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH) {
RT_WriteFile(Frames,"%d",n,Append=True)
}
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt))
"""

ScriptClip(SSS)


I have this error: https://drive.google.com/file/d/1rA51G8UkWcFgMrg359kulvLMfPT9j9Mb/view?usp=sharing

tried to debug withous success

StainlessS
2nd January 2022, 22:54
Are you using AVS+ ? [EDIT: I think its complaining about the GScript style if implemented in AVS+]
If not, do you use GScript ?
And do you use Grunt ?

Also, use the later mod when we get it working.

StainlessS
2nd January 2022, 23:01
OK, this should work, requires only RT_Stats, AVS+ and GSCript Not Required.


# Requires, RT_Stats

#AviSource(".\defect_field.mp4.AVI")
AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.
CHROMAI = IsYV12
RT_FileDelete(Frames)

SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=0,y2=1,AltScan=True,ChromaI=CHROMAI) # Diff top and bottom fields of frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Diff top Prev and top curr fields
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Curr top and Next top fields
(Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH) ? RT_WriteFile(Frames,"%d",n,Append=True) : NOP
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt))
"""

ScriptClip(SSS)

lollo2
2nd January 2022, 23:03
No AVS+

Now using:


loadPlugin("C:\Users\giuse\Desktop\RT_Stats_25_26_x86_x64_dll_v2.00Beta12_20181125\RT_Stats_25&26_x86_x64_dll_v2.00Beta12_20181125\Avisynth26\RT_Stats_x86.dll")
loadPlugin("C:\Users\giuse\Desktop\GScript_32_64\GScript\Release\GScript_26_32.dll")
loadPlugin("C:\Users\giuse\Desktop\GRunT-v1.02\x86\grunt.dll")

#AviSource(".\defect_field.mp4.AVI")
AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.
CHROMAI = IsYV12


RT_FileDelete(Frames)


SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=0,y2=1,AltScan=True,ChromaI=CHROMAI) # Diff top and bottom fields of frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Diff top Prev and top curr fields
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Curr top and Next top fields

if(Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH) {
RT_WriteFile(Frames,"%d",n,Append=True)
}
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt))
"""

ScriptClip(SSS)


no success. Thanks again for your time

lollo2
2nd January 2022, 23:05
OK, this should work, requires only RT_Stats, AVS+ and GSCript Not Required.

Thanks! I will try to install avs+ then. Tomorrow, now is too late.

You are a precious resource for the whole community.

StainlessS
2nd January 2022, 23:08
That is intended to mean it only requires RT_Stats, nothing else.
I also added the last line commented out here,


# Requires, Only RT_Stats v2.0 Beta??

#AviSource(".\defect_field.mp4.AVI")
AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.
CHROMAI = IsYV12
RT_FileDelete(Frames)

SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=0,y2=1,AltScan=True,ChromaI=CHROMAI) # Diff top and bottom fields of frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Diff top Prev and top curr fields
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=0,y2=0,AltScan=True,ChromaI=CHROMAI) # Curr top and Next top fields
(Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH) ? RT_WriteFile(Frames,"%d",n,Append=True) : NOP
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt))
"""

ScriptClip(SSS)

# RT_ForceProcess # UnComment to force Frames file to be fully written, and then available to any further scripting after this line.

Return Last

The RT_ForceProcess thingy allows for automation of 2 pass solution.

lollo2
2nd January 2022, 23:16
Works perfectly!

It reports higher Pvr2Cur for frame 2 (ok, frame corrupt) but also for frame 3 (ok, the video becomes nomal again).
I will debug, try to dump the statistics on a file, execute on other captures and let you know.

Your script could easily become a "capture quality checker". Will probably detect scene change also, but that's normal.

Thanks again!

StainlessS
3rd January 2022, 00:29
The tripple > TH required to fire the detector was intended to try avoid false detects at scenchange [on 2nd field of bad frame].
Mid frame scenechange was the inital reasoning behind the triple detect thingy, a mid frame scene change would look like a bad field.
Also, one of the prv->cur or cur->nxt detectors will also fire [which one depends upon field order and whether bad top or bottom field]
with a mid frame scenechange, but the other one should [with appropriate TH] hopefully not fire and avoid false detection.


The top->bot alone will likely detect correctly a lot(most) of the time. [EDIT: given an appropriate TH]

EDITED:

StainlessS
3rd January 2022, 00:57
Nuther little tinker


# Requires, RT_Stats
# If FrameSel line uncommented [would also require RT_ForceProcess line uncommented] then shows bad frames only. [And will require FrameSel plugin].

#AviSource(".\defect_field.mp4.AVI")
AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")

Frames = (".\Frames.txt").RT_GetFullPathName
TH = 20.0 # Picked out of the hat.
RT_FileDelete(Frames)

SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=0,y2=1,AltScan=True,ChromaI=True) # Diff top and bottom fields of frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=0,y2=0,AltScan=True,ChromaI=True) # Diff top Prev and top curr fields
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=0,y2=0,AltScan=True,ChromaI=True) # Diff Curr top and Next top fields
Bingo = (Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH)
(Bingo) ? RT_WriteFile(Frames,"%d",n,Append=True) : NOP
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt),Text_Color=(Bingo)?$FF00FF:$FFFF00)
"""

ScriptClip(SSS)
# Try uncomment both below [Will need Framesel]
#RT_ForceProcess # UnComment to force Frames file to be fully written, and then available to any further scripting after this line.
#Return FrameSel(Last,Cmd=Frames,Show=True,REJECT=FALSE) # Change to REJECT=TRUE to view non bad frames

Return Last

EDIT: Removed CHROMAI setting, made it always true [Is internally ignored if not YV12].

StainlessS
3rd January 2022, 02:44
Yet aNuther twiddle, user configurable to detect top or bottom bad field.


# Requires, RT_Stats
# If FrameSel line uncommented [would also require RT_ForceProcess line uncommented] then shows bad frames only. [And will require FrameSel plugin].

AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")
#AssumeTFF # Set appropriately [Not required in this script so far]

#### CONFIG ####
TOPFIELDBAD = True # True=Top field BAD, False = Bottom field BAD
TH = 20.0 # Picked out of the hat.
SUBS_Y = 20 # Subtitles offset from top, make a bit lower than FrameSel metrics position.
Frames = ".\Frames.txt"
#### END CONFIG ####

BadY = (TOPFIELDBAD ) ? 0 : 1
GoodY = (TOPFIELDBAD ) ? 1 : 0

Frames = Frames.RT_GetFullPathName
RT_FileDelete(Frames)

SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=BadY,y2=GoodY,AltScan=True,ChromaI=True) # Diff top and bottom fields of current frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=BadY,y2=BadY ,AltScan=True,ChromaI=True) # Diff bad field Prev and bad field Curr
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=BadY,y2=BadY ,AltScan=True,ChromaI=True) # Diff bad field Curr and bad field Next
Bingo = (Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH)
(Bingo) ? RT_WriteFile(Frames,"%d",n,Append=True) : NOP
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt),Text_Color=(Bingo)?$FF40FF:$FFFF00,Y=SUBS_Y)
"""

ScriptClip(SSS)
# Try uncomment both below [Will need Framesel]
#RT_ForceProcess # UnComment to force Frames file to be fully written, and then available to any further scripting after this line.
#Return FrameSel(Last,Cmd=Frames,Show=True,REJECT=FALSE) # Change to REJECT=TRUE to view only non bad frames

Return Last

StainlessS
3rd January 2022, 12:25
More configurable. More Bullet proof.


# FieldBadAreaDetect.avs # https://forum.doom9.org/showthread.php?p=1960487#post1960487

# Requires, RT_Stats
# If FrameSel line uncommented [would also require RT_ForceProcess line uncommented] then shows bad frames only. [And will require FrameSel plugin].

AviSource(".\spots_beg_s9_ss5a_amtv_v2_cut.avi")
#AssumeTFF # Set appropriately [Not required in this script so far]

#### CONFIG ####
TOPFIELDBAD = True # True=Top field BAD, False = Bottom field BAD

BADAREA = 4 # Approximate area of frame or field where crap resides. [Make for better more bullet proof detection, can make TH a lot higher without failed detect].
# 0=1st or Top quarter of frame or field.
# 1=2nd quarter of frame or field.
# 2=3rd quarter of frame or field.
# 3=4th or bottom quarter of frame or field.
# 4=Top half of frame or field,
# 5=Bottom half of frame or field,
# 6=full frame or field,
# Usable settings for Lollo2 clip are 0,1,4 and 6. [Lollo2 clip:- bad top field, top half of frame or field]
# 6 is as previous version testing full field, but only the top of lollo2 field is bad, so will get better numbers using 0,1 or 4, than original equivalent of 6.
# If using 0,1 or 4, suggest raising TH.

TH = 20.0 # Picked out of the hat. [Suggest about 40 or above if using BADAREA=0 or 1 or 4 for lollo2 clip]

CW = 1/3.0 # Below from RT_Stats docs. Switching off, ie CW = 0.0 might give better results [only test luma diff].
# ChromaWeight, default 1.0/3.0. Range 0.0 -> 1.0.
# Y8, returns same as LumaDifference. ChromaWeight ignored.
# YUV,
# Weighting applied YUV chroma:- (1.0 - ChromaWeight) * Lumadif + ChromaWeight * ((Udif + Vdif)/2.0).
# RGB,
# If ChromaWeight > 0.0, then returns same as RT_RGBDifference() [ie average RGB pixel channel difference].
# If ChromaWeight == 0.0, then returns same as RT_LumaDifference() using Matrix arg to convert RGB to YUV-Y Luma.
###

SUBS_Y = 20 # Subtitles offset from top, make a bit lower than FrameSel metrics position.
Frames = ".\Frames.txt"
#### END CONFIG ####

Assert(0 <= BADAREA <= 6,"0 <= BADAREA <= 6")

nAREA = (BADAREA<4) ? 4 : (BADAREA<6) ? 2 : 1 # 4=Areas are quarters, 2=Areas are halves, 1=Areas are full frame/field.
QUAD = Height / 16
BadH = QUAD*16/nAREA
QOFF = Select(BADAREA, 0*BadH, 1*BadH, 2*BadH, 3*BadH, 0*BadH, 1*BadH, 0*BadH)

BadY = QOFF + ((TOPFIELDBAD ) ? 0 : 1)
GoodY = QOFF + ((TOPFIELDBAD ) ? 1 : 0)

Frames = Frames.RT_GetFullPathName
RT_FileDelete(Frames)
#RT_DebugF("BADAREA=%d BadY=%d GoodY=%d BadH=%d",BADAREA,BadY,GoodY,BadH,name="LOLLO2: ") # just paranoia.

SSS = """
n = current_frame
Top2Bot = RT_FrameDifference(Last,Last,n=n,n2=n ,y=BadY,y2=GoodY,h=BadH,AltScan=True,ChromaWeight=CW,ChromaI=True) # Diff top and bottom fields of current frame n
Prv2Cur = RT_FrameDifference(Last,Last,n=n,n2=n-1,y=BadY,y2=BadY ,h=BadH,AltScan=True,ChromaWeight=CW,ChromaI=True) # Diff bad field Prev and bad field Curr
Cur2Nxt = RT_FrameDifference(Last,Last,n=n,n2=n+1,y=BadY,y2=BadY ,h=BadH,AltScan=True,ChromaWeight=CW,ChromaI=True) # Diff bad field Curr and bad field Next
Bingo = (Top2Bot > TH && Prv2Cur > TH && Cur2Nxt > TH)
(Bingo) ? RT_WriteFile(Frames,"%d",n,Append=True) : NOP
Subtitle(RT_String("%d] Top2Bot=%.2f : Prv2Cur=%.2f : Cur2Nxt=%.2f",n,Top2Bot,Prv2Cur,Cur2Nxt),Text_Color=(Bingo)?$FF40FF:$FFFF00,Y=SUBS_Y)
"""

ScriptClip(SSS)
# Try uncomment both below [Will need Framesel]
#RT_ForceProcess # UnComment to force Frames file to be fully written, and then available to any further scripting after this line.
#Return FrameSel(Last,Cmd=Frames,Show=True,REJECT=FALSE) # Change to REJECT=TRUE to view only non bad frames

Return Last

We test for bad top field, and only upper half of field instead of entire field [EDIT: BADAREA = 4], better numbers, about 60.0 instead of original ~40.0.
EDIT: BADAREA = 1 or 2, would get similar-ish numbers [top or 2nd quarter of field], better than original equivalent of BADAREA = 6 [full field].

https://i.postimg.cc/brYZvjvf/Test-02.jpg (https://postimages.org/)

EDIT: Added CW ChromaWeight config.

EDIT: Changed

BADAREA = 4 # Approximate area of frame or field where crap resides. [Make for better more bullet proof detection, can make TH a lot higher without false detect

to

BADAREA = 4 # Approximate area of frame or field where crap resides. [Make for better more bullet proof detection, can make TH a lot higher without failed detect

lollo2
3rd January 2022, 14:21
Better and better, thanks a lot!

I quickly tried old script and the key point is obviously the choice of an appropriate TH value. High values may do not detect the bad fields, lower tends to generate false positive.

I also suspect that is easier to have a good detection in "progressive" videos where the fields are taken from the same moment in time rather than in interlaced videos where the fields are coming from different time and then differ more by nature. I will experiment.

Also your idea of reducing the area under analysis is excellent, so it can better work for small defects like the example 2 in my first post, where otherwise I need to decrease the value of TH a lot.

And finally, I am sure your precious effort have generated a script useful for similar but not identical, problems in our videos, because it can be easily customized or generalized, and lot of other users will use or adapt it for their needs. Another great contribution to the community ;)

StainlessS
3rd January 2022, 15:08
Thanx for the kind words, I'm about done here, Have a good 2022 [well better than 2020 or 2021] :)

EDIT: Setting CW = 1.0, would test only Chroma diff.
EDIT: Also, I've come to decide that CW = about 0.15 or 0.2 is better than the default 1.0/3.0 [in general usage, not specifcally for this problem].

lollo2
3rd January 2022, 15:32
Have a wonderful 2022 you too (and the rest of the community)!