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

Reply
 
Thread Tools Search this Thread Display Modes
Old 3rd May 2021, 10:50   #1  |  Link
chmars
Registered User
 
Join Date: Apr 2021
Posts: 128
[Solved] Colour mark detection for frames remouval in 8mm/S8 transfer

Hello dear users,

BACKGROUND
I am achieving the construction of a film-transfer system for 8mm and Super8 films.
It is based on the method of capturing the frames directly into the projector's gate with a running video camera (versus frame by frame capture).
My first goal coming here was to enjoy the huge Fred's script and John's version generously shared here and perfected with the help of many users in this thread.
As I needed to have a frame accurate capture (one video frame for one footage frame) to use these scripts, i built a system and posted my setup description and question there. But that became off topic. I began this thread.

SETUP Detailed setup + pictures here
As is not possible to synchronize the camera I am using with the projector, I had to find a way to peseudo-sync them.
The idea I had was to place an LED on the side of the gate. The LED is turned on each time the projector is changing from one frame to the next one, then turned off when the frame is steady. The projector runs at 18 fps while the camera shoots at 50 fps.
This way, the capture contains the information about which frames are usable and which are not.

THE SITUATION
Sample here, md5:0820A24F2D0AB47483FA5E3BF5DADB69 File is directly out of the camera, hence inverted.
As you can see in the sample, I now have captured sequences containing one or more "bad frames" followed by one or more "good frames":

Here is a screenshot to give you an idea:


B = Bad frame (blue light presence)
G = good frame (no blue light)

Example starting from frame 314 included, to 335:
G B GG B GG B G BB G BB G B GG B GG B

We sometimes have GG, sometimes BB.
But we always have at least one G between one or some B.

I think we could say:

"keep only one G between each B/each group of B", it should work, don't You think?

Step by step, more or less human spoken, it would give:
If B, throw away and flag "last was B"
else if G, and flag is "last was B", keep and flag "last was G"
else if G, and flag is "last was G", throw away
and so on...


THE QUESTION
How do we ask this to Avisynth?

I'll share my attempts into the next post.

Last edited by chmars; 30th May 2021 at 10:53. Reason: explain inverted image, add pic Edit2: mark as solved
chmars is offline   Reply With Quote
Old 3rd May 2021, 10:56   #2  |  Link
chmars
Registered User
 
Join Date: Apr 2021
Posts: 128
Being very noob, I needed half of last night to find a start of partly working solution.
It may be very naive and inappropriate but here it is, at least to prove my effort :--)
This code is removing all B frames except when two are directly in a row.

Code:
LoadPlugin("C:\Program Files (x86)\AviSynth+\plugins/ffms2.dll")            # Load the plugin able to read MXF files
initial_video = FFmpegSource2("C:\some_path\my_sample.MXF", atrack=-2)      # How to read and which is the file
video = Crop(initial_video, 474, 190, -166, -170)                           # Crop my video frame

ScriptClip(video, \                                                         #Will be done on each frame of clip "video"
"frame_chromaU = AverageChromaU(Crop(video,0, 0, -1000, 0))" + chr(13) + \  #Store the chroma U average of a cropped part of the immage in a variable
"frame_chromaV = AverageChromaV(Crop(video,0, 0, -1000, 0))" + chr(13) + \  #Store the chroma V average of a cropped part of the immage in a variable
"frame_luma = AverageLuma(Crop(video,0, 0, -1000, 0))" + chr(13) + \        #Store the luma average of a cropped part of the immage in a variable
"black_ref_luma = AverageLuma(Crop(video,150, 560, -1000, 0))" + chr(13) + \#Same for black part as reference
"round(frame_chromaU) > 520  &&  \                                          # If chroma U average is bigger than 520 AND
round(frame_chromaV) < 503  && \                                            # if chroma V average is smaller than 503 AND
round(frame_luma) > 200 && \                                                # if luma average is bigger than 200 AND
round(black_ref_luma) < 200  \                                              # if the black part of the image is not lit by something else
? DeleteFrame(current_frame) : subtitle(string()) ")                        # then we can hope the led is ON and delete the frame. Else, do nothing
This code works but has to be adapted (crop values) and run a second time on the resulting avi file as it appeared to me that it seems not possible to delete two frames in a row.
And then? It'll result in a file with lots of duplicated frames. I could then use someting like a duplicated frame detector.
But this is no good solution as it adds an interpretation of the images, introducing a cause of errors (Am I right on this point?).

What would be needed is to store the B frame-number into a variable outside of the run-time environment to be able to keep only one of the next G frames.
Or write a list into a text file?
I'll make some tries but if you have suggestions, they are very welcome.
chmars is offline   Reply With Quote
Old 3rd May 2021, 16:24   #3  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
Script moved here from this post:- https://forum.doom9.org/showthread.p...99#post1941999

Blue_LED_Detect.avs [detector, frames.txt maker]
Code:
# Blue_LED_Detect.avs
/*
    Requires, AVS+, RT_Stats, MaskTools
    Detects Blue LED's, selects mid frame of those frames between blue LEDs,
       when SEL2ND==True and frame count between Blue LEDs are even, then selects the later middle frame rather than default earlier middle frame.
    Writes only single middle frame between BLUE frames.

    May need to adjust AREA Coords where BLUE expected
*/

FN = "MBGV0403.MXF"

############
VFLIP    = True         # Vertical Flip if upside down

SETUP_BLUE = False      # Setup BLUE Detect Vars MODE ONLY. DOES NOT  Detect non BLUE nor write Frames
BAFFLE     = 4          # Blue Detect Vars (RT_YInRangeLocate, Probably should leave this one alone)
THRESH     = 10.0           # Ditto, Maybe bout 5.0 -> 20.0
LUMA_MIN   = 60             # Ditto, blue luma min
LUMA_MAX   = 255            # Ditto (Leave alone)
AREA_X     = 240        # BLUE Coords test area
AREA_Y     = 300            # Ditto
AREA_W     = 530            # Ditto
AREA_H     = 572            # Ditto
SEL2ND     = False      # When NonBlue count is EVEN, false selects earlier middle frame, True select later middle frame.
SHOW       = true       # Metrics + BLUE MARKER [FALSE for final, quicker]

############
FN = FN.RT_GetFullPathName
LWLibavVideoSource(FN)
############

ConvertBits(8).ConvertToYV12                  # Just for Detect
ORG = Last
(VFLIP) ? FlipVertical : NOP

# Un-comment BELOW to SHOW BLUE TEST AREA COORDS
#return Overlay(Last.BlankClip(Length=1,Width=AREA_W,Height=AREA_H,color=$FFFF00),x=AREA_X,y=AREA_Y,Opacity=0.3)

##########################
DB     = ".\MyDBase.DB".RT_GetFullPathName
FRAMES = ".\Frames.txt".RT_GetFullPathName
TypeStr = "iiiiiiii"
RT_FileDelete(FRAMES)
RT_DBaseAlloc(DB,FrameCount,TypeStr)

############ DBase Field Index's
STAT_FLD   = 0   # 0=Unknown, 1=BLUE, 2=Non Blue Frame(Not chosen),  3=Non Blue chosen Frame.

                 # Valid only When STAT==2 OR STAT==3 (NOT BLUE_LED Stat==1)
FRM_S_FLD  = 1   #   Ditto, 1st frame of non BLUE
FRM_M_FLD  = 2   #   Ditto  Chosen Non Blue (writen to Frames file)
FRM_E_FLD  = 3   #   Ditto Last frame of non BLUE

BLUE_X_FLD = 4   # Blue Detect Coords, Valid ONLY when STAT==1 (BLUE_LED)
BLUE_Y_FLD = 5   #   Ditto
BLUE_W_FLD = 6   #   Ditto
BLUE_H_FLD = 7   #   Ditto


# Setup Detect Vars Script
SCRIPT_0 = """
    n=current_frame
    if(RT_YInRangeLocate(Last,n=n,x=AREA_X,y=AREA_Y,w=AREA_W,h=AREA_H,Baffle=BAFFLE,Thresh=THRESH,Lo=LUMA_MIN,Hi=LUMA_MAX)) {
        Blue_x = YIRL_X /2 * 2              Blue_y = YIRL_Y / 2 * 2
        Blue_w = (YIRL_W + 1) / 2 * 2       Blue_h = (YIRL_H + 1) / 2 * 2
        Mrk = Last.BlankClip(Length=1,Width=Blue_w,Height=Blue_h,Color=$FFFF00)
        Msk = Hit_Marker(Blue_w,Blue_h,False)
        Overlay(Mrk,x=Blue_x,y=Blue_y,Mask=Msk,Mode="Blend")
    }
    Subtitle("Setup BLUE Detect Vars",Size=48)
    Return Last
"""

# Write FRAMES File Script
SCRIPT_1="""
    n=current_frame
    Stat = RT_DBaseGetField(DB,n,STAT_FLD)
    if(Stat == 0) { # Unknown
        Stat = RT_YInRangeLocate(Last,n=n,x=AREA_X,y=AREA_Y,w=AREA_W,h=AREA_H,Baffle=BAFFLE,Thresh=THRESH,Lo=LUMA_MIN,Hi=LUMA_MAX) ? 1 : 2
        if(Stat==1) { # BLUE
            Blue_x = YIRL_X / 2 * 2             Blue_y = YIRL_Y / 2 * 2
            Blue_w = (YIRL_W + 1) / 2 * 2       Blue_h = (YIRL_H + 1) / 2 * 2
            RT_DBaseSet(DB,n,Stat,   -1,-1,-1,   Blue_X,Blue_Y,Blue_W,Blue_H)
        } Else { # NOT BLUE
            Frame_S = n
            For(i=n-1,0,-1) { # Step Backwards looking for previous BLUE
                # i is Always either KNOWN BLUE or Unknown
                Stat = RT_DBaseGetField(DB,i,STAT_FLD)
                if(Stat == 0) { # Unknown
                    if(RT_YInRangeLocate(Last,n=i,x=AREA_X,y=AREA_Y,w=AREA_W,h=AREA_H,Baffle=BAFFLE,Thresh=THRESH,Lo=LUMA_MIN,Hi=LUMA_MAX)) {
                        Blue_x = YIRL_X / 2 * 2             Blue_y = YIRL_Y / 2 * 2
                        Blue_w = (YIRL_W + 1) / 2 * 2       Blue_h = (YIRL_H + 1) / 2 * 2
                        RT_DBaseSet(DB,i,1,   -1,-1,-1,   Blue_X,Blue_Y,Blue_W,Blue_H)    # set BLUE stuff
                        Frame_S = i + 1 # Start frame = BLUE + 1
                        i = 0   # Break
                    } Else { Frame_S = i }     # Non BLUE
                } else { # KNOWN BLUE
                    Assert(Stat==1,"Internal Error #1 Stat="+String(Stat))
                    Frame_S = i + 1 # Start frame = BLUE + 1
                    i = 0   # Break
                }
            }
            Frame_E = n
            For(i=n+1,FrameCount-1) { # Step Forwards looking for next BLUE
                # i is Always either KNOWN BLUE or Unknown
                Stat = RT_DBaseGetField(DB,i,STAT_FLD)
                if(Stat == 0) { # Unknown
                    if(RT_YInRangeLocate(Last,n=i,x=AREA_X,y=AREA_Y,w=AREA_W,h=AREA_H,Baffle=BAFFLE,Thresh=THRESH,Lo=LUMA_MIN,Hi=LUMA_MAX)) {
                        Blue_x = YIRL_X / 2 * 2             Blue_y = YIRL_Y / 2 * 2
                        Blue_w = (YIRL_W + 1) / 2 * 2       Blue_h = (YIRL_H + 1) / 2 * 2
                        RT_DBaseSet(DB,i,1,  -1,-1,-1,  Blue_X,Blue_Y,Blue_W,Blue_H)    # set BLUE stuff
                        Frame_E = i - 1 # End frame = BLUE - 1
                        i = FrameCount-1   # Break
                    } Else { Frame_E = i }     # Non BLUE
                } else { # KNOWN BLUE
                    Assert(Stat==1,"Internal Error #2 Stat="+String(Stat))
                    Frame_E = i - 1 # End frame = BLUE - 1
                    i = FrameCount-1   # Break
                }
            }
            SelIx = (Frame_E - Frame_S) / 2
            Frame_M = (SEL2ND) ? Frame_E-SelIx : Frame_S + SelIx
            for(i=Frame_S,Frame_E) {
                Stat = (i==Frame_M)?3:2
                RT_DBaseSet(DB,i,Stat, Frame_S,Frame_M,Frame_E,  -1,-1,-1,-1)
            }
            Stat = (n==Frame_M)?3:2
        }
    } # End, if(Stat == 0)
    # Here, Stat=1=BLUE, =2 non-blue Frame - not chosen, 3=Chosen Frame
    if(Stat==1) { # BLUE
        if(SHOW) {
            Blue_x = RT_DBaseGetField(DB,n,BLUE_X_FLD)  Blue_y = RT_DBaseGetField(DB,n,BLUE_Y_FLD)
            Blue_w = RT_DBaseGetField(DB,n,BLUE_W_FLD)  Blue_h = RT_DBaseGetField(DB,n,BLUE_H_FLD)
            Mrk = Last.BlankClip(Length=1,Width=Blue_w,Height=Blue_h,Color=$FFFF00)
            Msk = Hit_Marker(Blue_w,Blue_h,False)
            Overlay(Mrk,x=Blue_x,y=Blue_y,Mask=Msk,Mode="Blend",Opacity=0.3)
            Subtitle(RT_String("%d ] BLUE LED, detect x=%d y=%d w=%d h=%d",n,Blue_x,Blue_y,Blue_w,Blue_h),Size=48,Align=1)
        }
    } else if(Stat==3 || SHOW) {
        Frame_S = RT_DBaseGetField(DB,n,FRM_S_FLD)
        Frame_E = RT_DBaseGetField(DB,n,FRM_E_FLD)
        (SHOW) ? Subtitle(RT_String("%d ] S=%d E=%d Len=%d",n,Frame_S,Frame_E,Frame_E-Frame_S+1),Size=48) : NOP
        if(Stat==3) { # Write To Frames File
            if(!SEL2ND || n == Frame_S + ((Frame_E - Frame_S) / 2)) {
                RT_WriteFile(FRAMES,"%d",n,Append=n!=0)
                (SHOW) ? Subtitle(RT_String("Writing"),Size=48,y=48) : NOP
            } else {
                RT_WriteFile(FRAMES,"%d    # 2nd of middle pair",n,Append=n!=0)
                (SHOW) ? Subtitle(RT_String("Writing, 2nd of middle pair"),Size=48,y=48) : NOP
            }
        }
    }
    Return Last
"""


SSS = (SETUP_BLUE) ? SCRIPT_0 : SCRIPT_1

ScriptClip(SSS)
Return Last


Function Hit_Marker(int W, Int H, Bool "Hit", Int "BW", Int "BH",Int "PW",Int "PH",Bool "YV12",Bool "Mod2") {
/*
    Req RT_Stats & mt_tools v2.     http://forum.doom9.org/showthread.php?t=174527
    Creates a marker mask WxH, for use with Overlay as Mask arg.
    Intended for use via some kind of detector to show detection Hit, or Miss.
    Returns Single frame clip with null audio, the marker top left hand side is aligned to 0,0.
            Default return clip colorspace is Y8 for Avisynth v2.6 and above, or YV12 if defunct version.
    Args:-
        W,H,    Size of marker mask (can be odd), return clip dimensions are rounded up to next multiple of 2 if YV12 return clip.
                  Bare minimum usable size is 4x4 with defaulted BW, BH, PW, PH.
        HIT,    Default False, returns marker as angled corners (Thickness set by BW and BH).
                        True,  returns marker as angled corners + outer perimeter where perimeter thickness set by PW and PH.
        BW,     Default Max(W/8,1). Horizontal thickness of the marker corners.
        BH,     Default Max(H/8,1). Vertical   thickness of the marker corners.
        PW,     Default Max(BW/8,1). Horizontal thickness of the vertical perimeter.
        PH,     Default Max(BH/8,1). Vertical thickness of the horizontal perimeter.
        YV12,   Default False if Avisynth version 2.6 or greater(Y8), else true(YV12). Selects return clip colorspace.
        Mod2,   Default True. If Y8 then round odd dimensions up modulo 2 (the mask is still WxH).

    Example:-
        Import("Hit_Marker.avs")
        WW=128  HH=WW   HIT=True
        BlankClip
        Yell=Last.BlankClip(Width=WW,Height=HH,Length=1,Color=$FFFF00)
        Return OverLay(Yell,x=(Width-WW)/2,y=(Height-HH)/2,mask=Hit_Marker(WW,HH,HIT))
*/
    Hit=Default(hit,False)                    BW=Max(Default(BW,W/8),1)   BH=Max(Default(BH,H/8),1)
    BW2=(W>4)?BW*2:BW                         BH2=(H>4)?BH*2:BH
    PW=Max(Default(PW,BW/8),1)                PH=Max(Default(PH,BH/8),1)  is26 = VersionNumber>=2.6
    YV12=(!is26) ? True : Default(YV12,False) Mod2=Default(Mod2,True)     Mod = (YV12||Mod2) ? 2 : 1
    CanvasW=(W+Mod-1)/Mod*Mod                 CanvasH=(H+Mod-1)/Mod*Mod
    Rpn= RT_String("x %d < x %d >= | y %d < | y %d >= | x %d < x %d >= | & y %d < y %d >= | & ",BW,W-BW,BH,H-BH,BW2,W-BW2,BH2,H-BH2)
    Rpn= (Hit) ? Rpn + RT_String("x %d < x %d >= | y %d < | y %d >= | | ",PW,W-PW,PH,H-PH) : Rpn
    Rpn= Rpn + RT_String("x %d < y %d < & & 255 0 ?",W,H)
    Blankclip(width=CanvasW,height=CanvasH,Length=1,pixel_type=YV12?"YV12":"Y8").Killaudio
    return mt_lutspa(relative = false,yExpr=Rpn, chroma = "-128")
}
Blue_LED_FrameSel.avs
Code:
# Blue_LED_FrameSel.avs

# Requires FrameSel plugin. (OK for HBD so long as dont use FrameSel SHOW arg).
# Requires Frames.txt as generated by Blue_LED_Detect.avs

FN     = "MBGV0403.MXF".RT_GetFullPathName
FRAMES = "Frames.txt".RT_GetFullPathName
############
VFLIP    = True         # Vertical Flip if upside down
REJECT   = False        # If True then show all rejected frames instead of selected frames


LWLibavVideoSource(FN)
(VFLIP) ? FlipVertical : NOP

# FrameSel, DONT USE SHOW ARG if NOT 8 bit.
Return FrameSel(Last,Cmd=FRAMES,Ordered=True,REJECT=REJECT)
EDIT: click to enlarge
Blue Detect Frame [SHOW=true]


Non Blue selected frame [SHOW=true]


EDIT: I can possibly mod current script, (I'll leave above in-situ), to auto scan [will seem to pause for some time],
and then do equivalent to calling the FrameSel script, and be ready to output final clip in eg VDub2 Save AVI or whatever.
All in single script, and auto deleting the DBase file on clip closure.
ScriptClip MUST have same number of output frames as input, and also same size/colorspace etc, that is why you are ending up
with many dupes at end of clip. [The framecount, size, colorspace, is fixed as soon as frameserving begins]

EDIT: Is the BLUE_LED detection working as per requirement ?
Also, is it required that you can execute two or more separate instances of the script simultaneously ?
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 3rd May 2021 at 16:39.
StainlessS is offline   Reply With Quote
Old 3rd May 2021, 19:23   #4  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,723
My guess is that you can use one or two lines of code, simply using the YDDifference function built into AVISynth. I do this all the time to find "flash frames," my term for the grossly overexposed frame that you get in a movie camera at the first frame when the camera is still coming up to speed, and the shutter blade is rotating too slowly, resulting in overexposure.

All you need to do is compare the current frame to each adjacent frame, and when this bidirectional metric blows up, you have found your LED frame.
johnmeyer is offline   Reply With Quote
Old 3rd May 2021, 20:13   #5  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
YDifference just tells absolute difference, could be going lighter, or darker, if different to prev, then could be black to blue or blue to black,
if same then could be both black or both blue.
Something additional is needed [ie Averageluma or similar on current frame].
If just picking 1st non blue frame after blue, then dont think you need bother about next frame at all, only previous.
You still got lots of dupes at end to remove.

EDIT: Also, there is maybe need to specifiy what exactly a blue frame is, ie how much blue, is any blue at all
considered blue. My detector looks for a 'chunk of blue of a minimum size [avoid any noise] and possibly moving
[as Blue LED does].

6] With current settings, this is considered [2nd of 2] Not Blue [but could be tweaked to consider as blue]


7] Blue


8] Not blue [1 of 1]


9] Blue


The detector is looking for a chunk of blue of a certain size & 'density'.
And the fact that its a blue LED dont really make a whole helluva lot of difference, brightness will quite suffice to detect.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 3rd May 2021 at 20:40.
StainlessS is offline   Reply With Quote
Old 3rd May 2021, 20:21   #6  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,723
I use the ratio of YDifferenceToNext and YDifferenceToPrevious. This gets rid of the problem of how these metrics vary over time as the nature of the video changes. I posted such a detection script several years ago and, with StainlessS' help, turned it into a pretty useful detection script for finding individual "bad" frames. The LED flash is a classic bad frame, and my detection script should therefore work perfectly. Here is the link:

Finding individual "bad" frames in video; save frame number; or repair


My finished script appears in post #6.
johnmeyer is offline   Reply With Quote
Old 3rd May 2021, 20:55   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
With current clip cap speeds, there can be single or multiple [2] of either blue or non blue frames,
any single would appear as a flash in a YDifferenceToNext and YDifferenceToPrevious ratio thingy,
whether it be black flash or blue flash. You still need to be able to tell one from other.

I've deliberately made my detector be able to cope with (single or) many blue and/or (single or) many black frames,
if cap speeds were to be changed.

EDIT:
Simple-ish detector would test luma [AverageLuma, or maybe YPlaneMax] and if BELOW some threshold, then
also test if sufficiently different to prev frame, if so then is first non blue.
[ie current frame TEST AREA is BLACK, prev frame TEST AREA is NOT BLACK]

EDIT: Fixed, I originally wrote "Above".
EDIT: Yep, Maybe YPlaneMax(threshold=100/256.0) # where threshold = 0.4% Percent of extreme [possible noise] pixels to ignore.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 3rd May 2021 at 21:14.
StainlessS is offline   Reply With Quote
Old 3rd May 2021, 21:30   #8  |  Link
chmars
Registered User
 
Join Date: Apr 2021
Posts: 128
Hi,

I was very excited to find your script, it's great to have such a tool for my setup! Thanks again very much for the work.

Quote:
Originally Posted by StainlessS View Post
ScriptClip MUST have ... many dupes at end of clip.
Ok, thanks. But...you know, I think i'll leave my "script" on the side for the moment and focus on yours.

Your functional proposals are interesting. The more is automated, the best it is. But I am far from asking any more, as it is already time spent for you and so great compared to what I can write!
Quote:
Originally Posted by StainlessS View Post
Also, is it required that you can execute two or more separate instances of the script simultaneously ?
Ideally? Put all the clips into a directory, go drink a coffee (or shoot some more) and have finished deduped+deblued clips in another dir when I come back. :-)
Quote:
Is the BLUE_LED detection working as per requirement ?
EDIT: Works perfectly in AvsPmod 2.6.7.5.
On my side, half way: It behaves as if one part of it would be too fast for another part. It ends with only some frames numbers into the txt file. Same with/without showing metrics+marker.
Code:
Text file:
0
11
52
68
121
140
302
321
371
495
701
718
743
766
782
816
844
849

Error Window:
Error parsing plugin string at position 0:
 
Error parsing Func plugin parameters: unknown character 'n'
Error parsing ConditionalSelect plugin parameters: unknown character 'n'
Error parsing ConditionalSelect plugin parameters: unknown character 'n'
Error parsing ConditionalFilter plugin parameters: unknown character 'n'
Error parsing ConditionalFilter plugin parameters: unknown character 'n'
Error parsing ConditionalFilter plugin parameters: unknown character 'n'
Error parsing ScriptClip plugin parameters: unknown character 'n'
Error parsing ScriptClip plugin parameters: unknown character 'n'
Error parsing WriteFile plugin parameters: unknown character 'n'
Error parsing WriteFile plugin parameters: + without preceeding argument
Error parsing WriteFileIf plugin parameters: unknown character 'n'
Error parsing WriteFileIf plugin parameters: + without preceeding argument
Error parsing WriteFileStart plugin parameters: unknown character 'n'
Error parsing WriteFileStart plugin parameters: + without preceeding argument
Error parsing WriteFileEnd plugin parameters: unknown character 'n'
Error parsing WriteFileEnd plugin parameters: + without preceeding argument
Error parsing WriteFile plugin parameters: unknown character 'n'
Error parsing WriteFile plugin parameters: + without preceeding argument
Error parsing WriteFileIf plugin parameters: unknown character 'n'
Error parsing WriteFileIf plugin parameters: + without preceeding argument
Error parsing WriteFileStart plugin parameters: unknown character 'n'
Error parsing WriteFileStart plugin parameters: + without preceeding argument
Error parsing WriteFileEnd plugin parameters: unknown character 'n'
Error parsing WriteFileEnd plugin parameters: + without preceeding argument
Error parsing propSet plugin parameters: unknown character 'a'
Error parsing propSetInt plugin parameters: unknown character 'n'
Error parsing propSetFloat plugin parameters: unknown character 'n'
Error parsing propSetString plugin parameters: unknown character 'n'
Error parsing propSetArray plugin parameters: unknown character 'n'
Error parsing propSet plugin parameters: unknown character 'a'
Error parsing propSet plugin parameters: unknown character 'a'
Error parsing propSet plugin parameters: unknown character 'a'
Error parsing propSet plugin parameters: unknown character 'a'
Error parsing OnCPU plugin parameters: unknown character 'n'
Error parsing OnCPU plugin parameters: unknown character 'n'
But when I run it manually (arrow key), it works correctly.
I use AVS+ 3.7.0 on a win10 PC.
and going to search the way to determine the version of the DLLs

EDIT: I tried many times, to be sure. Deleting the db, lwi and text file between attempts. The source file (...403.mxf) is in the same directory.

Last edited by chmars; 3rd May 2021 at 22:32. Reason: it works.
chmars is offline   Reply With Quote
Old 3rd May 2021, 22:03   #9  |  Link
chmars
Registered User
 
Join Date: Apr 2021
Posts: 128
Wow, works absolutely fluently in AvsPmod 2.6.7.5 !
chmars is offline   Reply With Quote
Old 3rd May 2021, 22:35   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
I cannot make my ver$ fully automatic.
TWriteAVI(), could have made possible but cannot write files > 2GB, nor supports HBD. [I cannot mod for > 2GB, I dont speak x86 assy nor
do I know how to mod for DML AVI spec supporting > 2GB files.]
If TWriteAVI suppored both HBD and > 2GB files, would be a [near] walk in the park.

[EDIT: Only small amount of x86 assy in TWriteAVI, main prob is the DML AVI spec >2GB stuff]

This stuff
Quote:
Error Window:
Error parsing plugin string at position 0:
Error parsing Func plugin parameters: unknown character 'n'
Error parsing ConditionalSelect plugin parameters: unknown character 'n'
Error parsing ConditionalSelect plugin parameters: unknown character 'n'
Error parsing ConditionalFilter plugin parameters: unknown character 'n'
Error parsing ConditionalFilter plugin parameters: unknown character 'n'
Error parsing ConditionalFilter plugin parameters: unknown character '
Was that output from my script, or yours ? [definitely should not have come out of my script, I dont even use WriteFileIf, nor other stuff],
but referring to deleting the DB has me puzzled.

Quote:
Wow, works absolutely fluently in AvsPmod 2.6.7.5 !
And what is that referring to, what works in AvsPMod.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 3rd May 2021 at 22:57.
StainlessS is offline   Reply With Quote
Old 3rd May 2021, 23:26   #11  |  Link
doctorkhv
Registered User
 
Join Date: Mar 2019
Posts: 48
I don’t understand why to do this?
The cost of high-quality digitizing of 8 mm film 60 min ~ $ 100
doctorkhv is offline   Reply With Quote
Old 4th May 2021, 01:08   #12  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
Quote:
The cost of high-quality digitizing of 8 mm film 60 min ~ $ 100
Well if he has 1000 hours of the stuff, then that would be $100,000.00, that would be a more than good enough reason for me.

chmars,
Metrics viewer, for adjusting test area coords and thresholds.
Using same method should work pretty well. Choose Detection_Threshold midway between displayed metrics for
minimum Blue_LED frame, and maximum Non_blue_LED frame. Also can choose metrics as for 8 bit or native bit depth
eg 10 bit for your posted clip. [8 Bit will be easily more than sufficient (and more familiar values)].

Code:
# Requires Grunt() plugin

LWLibavVideoSource(".\MBGV0403.MXF")
############
TEST_X   = 374
TEST_Y   = 210
TEST_W   = 372
TEST_H   = 700
BITS8    = True         # Metrics are as 8 bit
MMDIFTH  = 0.4          # YPlaneMinMaxDifference Threshold (100.0/256.0) about 0.4 % [Percentage of extreme (noise) pixels to ignore].
VFLIP    = True         # Vertical Flip if upside down
############
(VFLIP) ? FlipVertical : NOP

Show_TestArea(TEST_X,TEST_Y,TEST_W,TEST_H,BITS8,MMDIFTH)

Return Last

Function Show_TestArea(clip c,int x,int y,int w,int h,Bool "Bits8",Float "MMDifTh") {
    Bits8 = Default(Bits8,False) # If True, then metrics are for 8 bit
    Th    = Default(MMDifTh,0.4) # YPlaneMinMaxDifference Threshold (%)
    tc = c.Crop(x,y,w,h)
    tc = Bits8 ? tc.ConvertBits(8).ConvertToYV12 : tc
    SSS="""Return Subtitle(String(current_frame)+String(tc.YPlaneMinMaxDifference(threshold=Th),"] %.1f"),Size=48)"""
    c.ScriptClip(SSS, Args="tc,Th")
    Return Last.OverLay(c.BlankClip(Length=1,Width=w,Height=h,Color=$FFFF00),x=x,y=y,Opacity=0.1)
}
The Yellow Overlayed Block shows the Test area.

23] Blue_LED [frame number, then Metric ie YPlaneMinMaxDifference(threshold=0.4) in 8 Bit]


24] Black
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 4th May 2021 at 02:38.
StainlessS is offline   Reply With Quote
Old 4th May 2021, 01:25   #13  |  Link
doctorkhv
Registered User
 
Join Date: Mar 2019
Posts: 48
Quote:
Originally Posted by StainlessS View Post
Well if he has 1000 hours of the stuff, then that would be $100,000.00, that would be a more than good enough reason for me.
If the job is big, then you can just buy a scanner
https://www.ebay.com/b/Film-Scanner-...0/bn_108187128
doctorkhv is offline   Reply With Quote
Old 4th May 2021, 01:42   #14  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
Not as much 'fun' as DIY, then Fred/Johns scripts for the ultimate results.
Maybe
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 4th May 2021, 05:31   #15  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
Here is simpler detect [or will be when slimmed down] script, test version to see if the YPlaneMinMaxDifference thingy works OK.

Code:
LWLibavVideoSource(".\MBGV0403.MXF")
############
TEST_X   = 374          # Test AREA COORDS (Even only)
TEST_Y   = 210          #   Ditto
TEST_W   = 372          #   Ditto
TEST_H   = 700          #   Ditto
BITS8    = True         # Metrics are as 8 bit
DETTH    = 50.0         # Detection Threshold (50 is 8 bit thresh)
MMDIFTH  = 0.4          # YPlaneMinMaxDifference Threshold (100.0/256.0) about 0.4 % [Percentage of extreme (noise) pixels to ignore].
VFLIP    = True         # Vertical Flip if upside down
FRAMES   = ".\Frames.txt"
############
(VFLIP) ? FlipVertical : NOP
############
FRAMES=FRAMES.RT_getFullPathName
RT_FileDelete(FRAMES)

tc = Crop(TEST_X,TEST_Y,TEST_W,TEST_H)
tc = Bits8 ? tc.ConvertBits(8).ConvertToYV12 : tc


SSS = """
    DetCur = tc.YPlaneMinMaxDifference(threshold=MMDifTh)
    DetPrv = tc.YPlaneMinMaxDifference(threshold=MMDifTh,offset=-1)
    T1= DetCur <  DetTh
    T2= DetPrv >= DetTh
    T3 = (T1 && (current_frame==0 || T2))
    (T3) ? RT_WriteFile(FRAMES,"%d",current_frame,Append=true) : NOP
    s= RT_string("%d] DetCur=%d(%.1s) DetPev = %d(%.1s) T=%s",current_frame,DetCur,T1,DetPrv,T2,T3)
    Subtitle(s,size=48)
    Return Last
"""

ScriptClip(SSS)
I will mod to use WriteFileIf whotsit [tomorrow, I'm off to bed].

Output identical frame numbers to original script except this one outputs 91 and original 90.
Output of this will extract good frames using the same Framsel script.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 4th May 2021, 06:00   #16  |  Link
chmars
Registered User
 
Join Date: Apr 2021
Posts: 128
Quote:
Originally Posted by StainlessS View Post
I cannot make my ver$ fully automatic.
I made you spend enough time already. I was not asking seriously. Your script is infinitely better than wha I could do and works perfectly. Fits perfectly my needs.

You are right, the errors output are present even with Version().
Nothing to do with your script.

Quote:
Originally Posted by StainlessS View Post
And what is that referring to, what works in AvsPMod.
Your script. It misses lots of good frames when I run it in Avspmod 2.5.1, but everything is ok in Avspmod 2.6.7.5.

Deleting the DB and all that was generated by your script was just a way to restart from zero with no elements in the directory that could (remember, i am a total noob) have perturbed the results and made me report wrongly.


Quote:
Originally Posted by StainlessS View Post
chmars,
Metrics viewer, for adjusting test area coords and thresholds.
Great, perfect, luxury, lots of thanks!
Quote:
Originally Posted by doctorkhv View Post
I don’t understand why to do this?
The cost of high-quality digitizing of 8 mm film 60 min ~ $ 100
Yes, not as much fun at all.
Also, the price/quality from certain "professional" services I could see is alas far from what you describe.
I also ha e seen some regrets in this direction while reading the The power of Avisynth: restoring old 8mm films.
chmars is offline   Reply With Quote
Old 4th May 2021, 12:45   #17  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
Quote:
You are right, the errors output are present even with Version().
Nothing to do with your script.
At a guess, I'de say you may have a script in plugins that should not be there.
AVSI's should really only contain eg constants [like the colors_rgb.avsi thing], OR,
script function definitions [there might be a few additional exceptions].
It should not contain script to eg try to load some clip, and process it.
[This is my suspected problem - if it fails with "Version()" then is failing in erroneous script before it even gets to Version() whosit].
[Remove them all, then add then back, maybe one at a time until problem script is revealed with "Version()" script.]
[It is possible that there is an *.AVS script in plugins, with code not intended for AVSI script, AVS+ also loads AVS from plugins,
assuming that you forgot to rename to AVSI (pre-AVS+ did not auto load AVS)].

You did not have to delete the DB, RT_DBaseAlloc() initializes a new DBase, whether existing or not.

The Chosen YPlaneMinMaxDifference(threshold=0.4) builtin runtime filter whotsit,
counts all pixels values into an array [each element a population count for the pixel value that is same as element array index].
For YMax, It scans array elements from topmost downwards [one at a time] until sum of population is greater or equal to 0.4%,
and ignores any extreme values in array ABOVE that element. If there are a few extreme pixels [less than 0.4%] at top end, then these
are ignored, if the highest pop count in array has population of 0.4% or more, then nothing is ignored.
Same sort of thing happens at the bottom of array for the YMin thingy.
Final result of YPlaneMinMaxDifference(0.4) is the difference between these top and bottom chosen array index's.
Above roughly correct, hope that it made some sense.

EDIT:
YPlaneMinMaxDifference seems to work at least as well as the original detection method with yellow marker, and could be
substituted in the original DBase detector [probably also faster]. [I will likely do that].
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 4th May 2021 at 13:24.
StainlessS is offline   Reply With Quote
Old 4th May 2021, 16:18   #18  |  Link
chmars
Registered User
 
Join Date: Apr 2021
Posts: 128
I tried to empty the plugins dirs. Error window says the same.
But this happens only when I use Avspmod 2.5.1, not 2.6.7.5.
As long scripts are working, is it really a "must solve"?

I didn't see your new detect version. much faster! and so shorter.

Thank you for your explanations. I feel like a cat in an astrophysics conference: I get the very basic principles but not much more. My knowledge is not rich enough and my English neither is.

I tried the detector as it is in your post #15, without the DB part. It creates the text list of frames to keep. Then, I can generate the clip with FrameSel.avs.
So... I am sorry to ask, it is certainly obvious for most people but what is the DB part for?
Or, by saying
Quote:
... and could be
substituted in the original DBase detector ...
must I understand the detector from post #15 must replace the whole first version?

If you have time, would you agree to write some comments into the detector lines so I could understand easier how it works?

Thank you,
BR
chmars is offline   Reply With Quote
Old 4th May 2021, 16:53   #19  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,042
The DB thing was a detector, the one in post #15 is another detector with a different detection device/method,
both create a frames file.
The 2nd [#15] one writes the first frame after BLUE_LED, no matter how many consecutive BLUES or BLACKS there are,
the original DB one selects the middle BLACK frame, so if your timings differed, and/or LED or equivalent was not so precise,
it would give a better chance of selecting good frame.
I was just making a script that might be usable [hackable] in other circumstances, if with a different 'BLUE_LED' indicator, so more flexible, maybe.

I'll add comments to final versions.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 4th May 2021, 17:12   #20  |  Link
chmars
Registered User
 
Join Date: Apr 2021
Posts: 128
Beautyfull!
In my case, I can adjust the LED start and stop times at the 1/1000 of second scale. So there is no need of possibility choosing the kept frame. But that could be useful for a more analogic system.
I made some tries with higher resolutions also. It works perfect after ajusting the size + pos of the detection zone.
It's a detail but I also made a modification to name the txt file with a part of the name of the clip to avoid mixing by error.

While testing it with several clips, I thought back to your idea of making both scripts into one. This would be very handy as with lots of clips to treat, it represents many manipulations:
Quote:
I can possibly mod current script, (I'll leave above in-situ), to auto scan [will seem to pause for some time],
and then do equivalent to calling the FrameSel script, and be ready to output final clip in eg VDub2 Save AVI or whatever.
All in single script, and auto deleting the DBase file on clip closure.
But I feel just like having received a Rolls Royce and complaining about the tint! Understand me: Any tint fits perfectly to me and I am very happy with what I have.
chmars is offline   Reply With Quote
Reply

Tags
image analysis decimation

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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 15:08.


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