Thread: Histogram: YCM
View Single Post
Old 30th June 2015, 17:27   #10  |  Link
fvisagie
Registered User
 
Join Date: Aug 2008
Location: Isle of Man
Posts: 588
Quote:
Originally Posted by -Vit- View Post
Script for RGB and CMY levels histograms (because there isn't an RGB histogram either, unless I missed it...).
Edit: Also added an RGB parade as it was fairly similar.
Also very useful for checking clipping of individual colour channels whilst working in YUV, thanks .

Updated to minimise/prevent inadvertent histogram scaling with YUV inputs:
Code:
# http://forum.doom9.org/showpost.php?p=1570968&postcount=7
# http://avisynth.nl/index.php/Histograms_in_RGB_%26_CMY
#
#
# Histograms in RGB & CMY
# Updated to minimise/prevent inadvertent histogram scaling with YUV inputs
#
# HistogramRGBParade presents a fairly standard RGB parade color scope.
# Uses the "Classic" avisynth histogram for each RGB component, but applied to columns rather than rows
# - The "width" setting controls the size of the histogram display. Default is 0.25 (height is always 256 pixels)
# - The "coeffs" setting specifies colourspace conversion matrix coefficients - "601" or "709" for Rec.601 and Rec.709 resp. Default is "601".
# Examples:
#   HistogramRGBParade()
#   HistogramRGBParade(width=0.15)      # display histogram a bit smaller (from default 0.25)
#   HistogramRGBParade(coeffs="709")    # for Rec.709/HD content
#
# HistogramRGBLevels / HistogramCMYLevels are like the "Levels" avisynth histogram but for RGB and CMY instead of YUV
# - Set range=false to hide the 16-235 range (a left-over from the Y histogram used to build these)
# - "factor" has same usage as Avisynth Histogram function
# - The "coeffs" setting specifies colourspace conversion matrix coefficients - "601" or "709" for Rec.601 and Rec.709 resp. Default is "601".
# Examples:
#   HistogramRGBLevels()
#   HistogramCMYLevels()
#   HistogramRGBLevels(range=false)     # don't show tv-range from luma graph
#   HistogramRGBParade(coeffs="709")    # for Rec.709/HD content

#---

function HistogramRGBLevels( clip input, bool "range", float "factor", string "coeffs" )
{
    coeffs = default(coeffs,"601")
    return HistogramRGBLevelsType( input, input.ConvertToRGB(matrix="PC." + coeffs), $800000, $008000, $000080, range, factor, coeffs )
}

function HistogramCMYLevels( clip input, bool "range", float "factor", string "coeffs" )
{
    coeffs = default(coeffs,"601")
    return HistogramRGBLevelsType( input, input.ConvertToRGB(matrix="PC." + coeffs).Invert(), $008080, $800080, $808000, range, factor, coeffs )
}

function HistogramRGBParade( clip input, float "width", string "coeffs" )
{
    coeffs = default(coeffs,"601")
    return HistogramRGBParadeType( input, input.ConvertToRGB(matrix="PC." + coeffs), $800000, $008000, $000080, width, coeffs )
}

#---

# Generic levels form, not very useful as a standalone function
function HistogramRGBLevelsType( clip input, clip rgb, int color1, int color2, int color3, bool "range", float "factor", string "coeffs" )
{
    range = default(range,true)
    ChannelHeight = 64
    Gap = 8  # divisible by 4

    r = rgb.ShowRed  ("YV12").HistogramChannel("Levels", color1, "add", ChannelHeight, range, factor)
    g = rgb.ShowGreen("YV12").HistogramChannel("Levels", color2, "add", ChannelHeight, range, factor)
    b = rgb.ShowBlue ("YV12").HistogramChannel("Levels", color3, "add", ChannelHeight, range, factor)
    gap = BlankClip(r, height=Gap)
    hist = StackVertical(r,gap,g,gap,b).ConvertToMatch(input, coeffs)
    return input.Height() > hist.Height() ? \ 
           StackHorizontal(input, hist.AddBorders(0,0,0,input.Height() - hist.Height())) : \
           StackHorizontal(input.AddBorders(0,0,0,hist.Height() - input.Height()), hist)
}

# Generic parade form, not very useful as a standalone function
function HistogramRGBParadeType( clip input, clip rgb, int color1, int color2, int color3, float "width", string "coeffs" )
{
    width = default(width,0.25)
    Gap = 8  # divisible by 4

    rgb = rgb.PointResize( m4(rgb.Width()*width), m4(rgb.Height()) ).TurnRight()
    r = rgb.ShowRed  ("YV12").HistogramChannel("Classic", color1, "chroma", 0, true)
    g = rgb.ShowGreen("YV12").HistogramChannel("Classic", color2, "chroma", 0, true)
    b = rgb.ShowBlue ("YV12").HistogramChannel("Classic", color3, "chroma", 0, true)
    gap = BlankClip(r, height=Gap)
    hist = StackVertical(r,gap,g,gap,b).TurnLeft().ConvertToMatch(input, coeffs)
    return input.Height() > hist.Height() ? \ 
           StackHorizontal(input, hist.AddBorders(0,0,0,input.Height() - hist.Height())) : \
           StackHorizontal(input.AddBorders(0,0,0,hist.Height() - input.Height()), hist)
}

# Used by functions above, not a standalone function
function HistogramChannel( clip input, string type, int color, string colorMode, int height, bool range, float "factor" )
{
    input.Histogram(type, factor).Crop(input.Width(),0,0,height).Greyscale()
    range ? last : Levels(128,1.0,255,0,255,false)
    return Overlay(BlankClip(color=color), mode=colorMode, pc_range=true)
}

# Returns "input" converted to same colorspace as "ref"
function ConvertToMatch( clip input, clip ref, string coeffs )
{
    matrix = "PC." + coeffs
    return ref.IsYV12()  ? input.IsYV12()  ? input : input.ConvertToYV12(matrix=matrix)  : \
           ref.IsRGB32() ? input.IsRGB32() ? input : input.ConvertToRGB32(matrix=matrix) : \
           ref.IsRGB24() ? input.IsRGB24() ? input : input.ConvertToRGB24(matrix=matrix) : \
           ref.IsYUY2()  ? input.IsYUY2()  ? input : input.ConvertToYUY2(matrix=matrix)  : \
           ref.IsYV16()  ? input.IsYV16()  ? input : input.ConvertToYV16(matrix=matrix)  : \
           ref.IsYV24()  ? input.IsYV24()  ? input : input.ConvertToYV24(matrix=matrix)  : \
           ref.IsY8()    ? input.IsY8()    ? input : input.ConvertToY8(matrix=matrix)    : \
           ref.IsYV411() ? input.IsYV411() ? input : input.ConvertToYV411(matrix=matrix) : \
           input
}

# Convert value to multiple of 4 which is  >= 16
function m4( float x ) { return (x < 16 ? 16 : int(round(x / 4.0) * 4)) }
Some test code:
Code:
rgb = StackVertical(\
    BlankClip(length=1, width=320, height=160, pixel_type="RGB32", color=$101010), \
    BlankClip(length=1, width=320, height=160, pixel_type="RGB32", color=$ebebeb) \
)
yuv = StackVertical(\
    BlankClip(length=1, width=320, height=160, pixel_type="YV12", color_yuv=$108080), \
    BlankClip(length=1, width=320, height=160, pixel_type="YV12", color_yuv=$eb8080) \
)
Import("Histograms_in_RGB_&_CMY.avsi")
before = StackHorizontal(HistogramRGBLevels(rgb).Subtitle("RGB32"), HistogramRGBLevels(yuv).ConvertToRGB32(matrix="PC.601").Subtitle("YV12")).Subtitle("Before", align=1)
Import("Histograms_in_RGB_&_CMY_mod.avsi")
after = StackHorizontal(HistogramRGBLevels(rgb).Subtitle("RGB32"), HistogramRGBLevels(yuv).ConvertToRGB32(matrix="PC.601").Subtitle("YV12")).Subtitle("After", align=1)
StackVertical(before, after)
Output (should display once attachment has been approved):
Attached Images
 
fvisagie is offline   Reply With Quote