VideoHelp Forum

Try DVDFab and download streaming video, copy, convert or make Blu-rays,DVDs! Download free trial !
+ Reply to Thread
Page 2 of 2
FirstFirst 1 2
Results 31 to 38 of 38
Thread
  1. > AVSMeter64.exe LumaHistogram.avs
    does give me the info about syntax errors.

    A player with a built-in or plug-in histogram feature is the way to go to visualize the histogram of the video as played (performance, wide file-format support without indexing, ease of use).
    The goal of my avs script is different: analyse source video files and then evaluate the processing done in the player (PC video players typically expand range).


    I would like to analyse the source video files in a similar way to ColorYUV(analyze=true), and save the results to a txt file or get an aggregate result for the file. For this I'm currently looking at runtime function such as YPlaneMin(), which are evaluated at each frame of a clip. They have to be passed to runtime filters (ConditionalFilter, ScriptClip, FrameEvaluate). The subject seems somewhat advanced and I haven't found a simple/good example for this so far.
    http://avisynth.nl/index.php/ScriptClip#ScriptClip

    Code:
    ScriptClip("subtitle(string(current_frame))")
    is easy enough: shows the frame-number in a clip. But it crashes if I try with string(YPlaneMin(vid)).
    Quote Quote  
  2. if you just start with Avisynth I recommend just to skip it, exactly because for your purpose. Proceed with Vapoursynth instead. Avisynth has for each thing some hack function and you want more, some change and it needs to be yet written by someone else again. In Vapoursynth you can write what you want right away.
    I'm sure, this script below could be done in Avisynth too, but as described it is ready to be changed, as for formatting, printing, placing.
    Code:
    import vapoursynth as vs
    from vapoursynth import core
    
    def evaluate(n, clip):
        aver = clip.get_frame(n).props['MyPlaneStatsAverage']
        _min = clip.get_frame(n).props['MyPlaneStatsMin']
        _max = clip.get_frame(n).props['MyPlaneStatsMax']
        text = f'Average={aver:.2f}\nMin={_min:.2f}\nMax={_max:.2f}\n' #:.2f means two decimal places, \n means new line
        return clip.text.Text(text)
    
    clip = core.avisource.AVISource('red.avi')
    clip = clip.std.PlaneStats(prop='MyPlaneStats')
    evaluated_clip = core.std.FrameEval(clip, functools.partial(evaluate, clip=clip))
    evaluated_clip.set_output()
    also you can let things evaluate and print it results or make a graph, just using couple of lines, whatever python can do. Not to mention that if you get comfortable, you just use portable versions, freeze the code and you just might use some exe file to analyze things etc.
    Image Attached Thumbnails Click image for larger version

Name:	Capture.PNG
Views:	8
Size:	659.9 KB
ID:	54448  

    Quote Quote  
  3. just realized, you wanted stats per channel:
    Code:
    import vapoursynth as vs
    from vapoursynth import core
    
    def evaluate(n, clip):
        text = []
        for plane in ['Y','U','V']:
            aver = clip.get_frame(n).props[f'Stats{plane}Average']
            _min = clip.get_frame(n).props[f'Stats{plane}Min']
            _max = clip.get_frame(n).props[f'Stats{plane}Max']
            text.append(f'{plane}\nAverage={aver:.2f}\nMin={_min:.2f}\nMax={_max:.2f}\n') #:.2f means two decimal places, \n means new line
        return clip.text.Text(''.join(text))
    
    clip = core.avisource.AVISource('red.avi')
    clip = clip.std.PlaneStats(plane=0, prop = 'StatsY' )\
               .std.PlaneStats(plane=1, prop = 'StatsU' )\
               .std.PlaneStats(plane=2, prop = 'StatsV' )
    evaluated_clip = core.std.FrameEval(clip, functools.partial(evaluate, clip=clip))
    evaluated_clip.set_output()
    so here we go, this is the flexibility I talked about ...
    Image Attached Thumbnails Click image for larger version

Name:	Capture2.PNG
Views:	10
Size:	770.6 KB
ID:	54449  

    Quote Quote  
  4. Other options are ffmpeg/ffplay -vf signalstats to print a text file , or avisynth writefile

    eg. signalstats

    https://ffmpeg.org/ffmpeg-filters.html#signalstats-1
    ffprobe -f lavfi movie=input.ext,signalstats="stat=tout+vrep+brng" -show_frames 1>signalstats.txt



    e.g write file for YPlaneMin YPlaneMax
    http://avisynth.nl/index.php/WriteFile

    #whateversource
    colon = ": "
    WriteFile(last, "log.txt", "current_frame", "colon", "YPlaneMin(last)", "colon", "YPlaneMax(last)" )

    But there seems to be an issue with current avs+ x64 WriteFile , not sure if some syntax changed or something. It works with older x86 version
    Quote Quote  
  5. To analyze video and write stats for all channels in some log in vapoursynth, again, just using Python functions,
    separating tasks into threads, in our case each plane is analyzed in its own thread,
    then writing result on disk as a log file, again using python function:
    Code:
    import vapoursynth as vs
    from vapoursynth import core
    from concurrent import futures   #standard python library module
    
    def analyze_channel(clip, plane_name): 
        text = []
        for frame in range(clip.num_frames):   
            aver = clip.get_frame(frame).props[f'Stats{plane_name}Average']
            _min = clip.get_frame(frame).props[f'Stats{plane_name}Min']
            _max = clip.get_frame(frame).props[f'Stats{plane_name}Max']
            text.append(f'{frame}: {plane_name}Average={aver:.2f} {plane_name}Min={_min:.2f} {plane_name}Max={_max:.2f}\n')
        return ''.join(text)
    
    clip = core.avisource.AVISource('red.avi')
    clip = clip.std.PlaneStats(plane=0, prop = 'StatsY' )\
               .std.PlaneStats(plane=1, prop = 'StatsU' )\
               .std.PlaneStats(plane=2, prop = 'StatsV' )
    
    print('starting to analyze planes\nanalyzing wait ...')
    with futures.ThreadPoolExecutor(max_workers=4) as analyze:
        #starting three jobs, one for each plane , each in separate thread
        jobs = [analyze.submit(analyze_channel, clip, plane_name) for plane_name in ['Y','U','V']]
        texts = [job.result() for job in jobs]
    
    print('analyzing done')
    print('writing log file ...')
    with open('planes_log.log', 'w') as log:
        for text in texts:
            log.write(text) 
    print('writing done')
    Last edited by _Al_; 8th Aug 2020 at 16:54.
    Quote Quote  
  6. @poisondeathray: I was looking at the same WriteFile example, but it wasn't working well with AvsPmod, vdub2, mpc-be.
    The solution for me was to run it with: >> AVSMeter64.exe luma_stats.avs

    The following code is clean/compact enough.

    Code:
    /* luma_stats.avs
    tested on Avisynth+ v3.6.1 x64. Run with: AVSMeter64.exe luma_stats.avs 
    Saves luma.csv with full Y stats 
    perf: 107fps on 1080p
    */ 
    fname = "b:\Videos\monster-1_ed.mp4" 
    LSmashVideoSource(fname, prefer_hw=2)
    fname_stats = "C:\temp\luma.csv"
    sep = "; "
    header = "frame" +sep+ "Ymin" +sep+ "Ymin(0.4)" +sep+ "Ymed" +sep+ "Yavg" +sep+ "Ymax(0.4)" +sep+ "Ymax"
    WriteFileStart(fname_stats, "header", append=false)
    WriteFile(fname_stats, "current_frame", "sep", "YPlaneMin", "sep", "YPlaneMin(0.4)", "sep", "YPlaneMedian", "sep", "AverageLuma", "sep", "YPlaneMax(0.4)", "sep", "YPlaneMax", flush=false, append=true)
    Quote Quote  
  7. The the runtime WriteFile() function works for me (AviSynth+ 64 bit):

    Code:
    WhateverSource()
    
    ylabel = "    Y "
    ulabel = "    U "
    vlabel = "    V "
    dash = "-"
    thresh = 0.4
    WriteFile(last, "Info.txt", "current_frame", \
        "ylabel", "YPlaneMin(last, threshold=thresh)", "dash", "YPlaneMax(last, threshold=thresh)", \
        "ulabel", "UPlaneMin(last, threshold=thresh)", "dash", "UPlaneMax(last, threshold=thresh)", \
        "vlabel", "VPlaneMin(last, threshold=thresh)", "dash", "VPlaneMax(last, threshold=thresh)")
    Open in VirtualDub2 (64 bit), preview input, log:

    Code:
    0    Y 20-216    U 109-158    V 98-145
    0    Y 20-216    U 109-158    V 98-145
    1    Y 19-216    U 109-158    V 98-145
    2    Y 20-216    U 109-158    V 99-145
    3    Y 20-216    U 109-158    V 99-145
    4    Y 19-216    U 109-158    V 99-145
    5    Y 20-216    U 109-157    V 98-145
    6    Y 20-216    U 109-158    V 98-145
    7    Y 20-216    U 109-159    V 98-145
    8    Y 20-216    U 109-159    V 98-145
    9    Y 19-216    U 109-158    V 97-145
    10    Y 19-216    U 109-158    V 98-145
    11    Y 19-216    U 109-158    V 98-145
    12    Y 20-216    U 109-158    V 98-145
    The first line appears twice because virtualdub displays the first frame when you open the script, then displays it again (and the rest of the frames) when you preview.

    Though I find a waveform monitor to be much more useful...
    Quote Quote  
  8. Those stats are needed for some visual later?
    Code:
    from concurrent import futures
    import matplotlib.pyplot as plt   #python -m pip install -U matplotlib
    
    clip = core.avisource.AVISource('red.avi')
    
    def analyze_channel(clip, plane_name): 
        _min, _max = [],[]
        for frame in range(clip.num_frames):   
            #aver.append(clip.get_frame(frame).props[f'Stats{plane_name}Average'])
            _min.append(clip.get_frame(frame).props[f'Stats{plane_name}Min'])
            _max.append(clip.get_frame(frame).props[f'Stats{plane_name}Max'])
        return [_min, _max]
    
    clip = clip.std.PlaneStats(plane=0, prop = 'StatsY' )\
               .std.PlaneStats(plane=1, prop = 'StatsU' )\
               .std.PlaneStats(plane=2, prop = 'StatsV' )
    
    print('starting to analyze planes\nanalyzing wait ...')
    with futures.ThreadPoolExecutor(max_workers=4) as analyze:
        #starting three jobs, one for each plane , each in separate thread
        jobs = [analyze.submit(analyze_channel, clip, plane_name) for plane_name in ['Y','U','V']]
        y_axis = [job.result() for job in jobs]
    print('analyzing done')
    
    x_axis    = list(range(clip.num_frames))
    for plane, plane_color in enumerate(['yellow', 'blue', 'red']):  
        plt.title(f"Min & Max values for Y-yellow, U-blue, V-red")
        plt.xlabel("frames")
        plt.ylabel("min & max per channel")
        [plt.scatter(x_axis, y_axis[plane][min_max], s=10, c=plane_color) for min_max in [0,1]]
        plt.show()
    Image Attached Thumbnails Click image for larger version

Name:	Capture3.PNG
Views:	9
Size:	70.5 KB
ID:	54450  

    Quote Quote  



Similar Threads