Log in

View Full Version : get color of an arbitrary pixel in clip?


XBoy
29th February 2008, 04:39
How do I get the color or an arbitrary pixel in a clip?

gzarkadas
2nd March 2008, 17:59
You can get it with a (small) approximation, due to rounding errors, with a script similar to the one appended at the end of this post.

You should be aware however that this kind of information is inherently of "runtime" nature, which means that:

you can only access it inside a runtime script,
every action that you want to perform based on that information must also be contained inside a runtime script.


Even if you write a plugin, the above limitations apply. So, basically, for anything more than basic processing you will need a very good knowledge of runtime scripting, or an entirely different approach.:)

Having said that, below is the script analyzed in sections.

The script
A proper YV12 source clip must have been assigned to 'last' previously, say with:

AviSource(...)

This piece defines needed function and also the x,y coordinates of the pixel in question.

function Min(val x1, val x2) { return x1 < x2 ? x1 : x2 }
function Max(val x1, val x2) { return x1 > x2 ? x1 : x2 }

# assumes 'last' is a yv12 clip

x_pos = <put_your_value_here>
y_pos = <put_your_value_here>

This piece crops the smallest allowable area adjacent to pixel (x,y), equalizes luma to (x,y) value in all pixels and upscales to a size that allows related runtime functions to operate.

#transfer luma of target clip to adjacent 2x2 region
pixel = last.Crop(x_pos, y_pos, 2, 2)
luma = pixel.Greyscale().ConvertToRGB32().Crop(0,0,1,1)
luma = StackVertical(StackHorizontal(luma, luma), StackHorizontal(luma, luma))
pixel = MergeLuma(pixel, luma.ConvertToYV12)
#make clip 64x64 so that Average... functions can work
pixel = StackHorizontal(pixel, pixel, pixel, pixel, pixel, pixel, pixel, pixel)
pixel = StackVertical(pixel, pixel, pixel, pixel, pixel, pixel, pixel, pixel)
pixel = StackHorizontal(pixel, pixel, pixel, pixel)
pixel = StackVertical(pixel, pixel, pixel, pixel)
last = pixel

This piece setups needed variables:

Kr = 0.299
Kg = 0.587
Kb = 0.114
y=0.0
u=0.0
v=0.0
r=0.0
g=0.0
v=0.0
pixel_color=0

This piece, finally, computes the color:

ScriptClip("""
y = AverageLuma()
u = AverageChromaU()
v = AverageChromaV()
return last
""")
FrameEvaluate("""
t_y = (y-16.0)/219.0
t_u = (u-128.0)/112.0
t_v = (v-128.0)/112.0
r = Max(0, Min(255, Round(255.0*(t_y + t_v*(1.0-Kr)))))
g = Max(0, Min(255, Round(255.0*(t_y - (t_u*(1.0-Kb)*Kb + t_v*(1.0-Kr)*Kr)/Kg))))
b = Max(0, Min(255, Round(255.0*(t_y + t_u*(1.0-Kb)))))
pixel_color = 256*(r*256 + g) + b
""", after_frame=true)


You can test it by supplying a known color clip as a source and appending the following lines to the end:

sep = Chr(9)
WriteFile(last, "get_pixel.txt", "current_frame", "sep", "y", "sep", "u", "sep", "v", "sep", "r", "sep", "g", "sep", "b", "sep", "pixel_color")

After running the Avs script for a few frames, open 'get_pixel.txt' and read the values to verify.

Wilbert
2nd March 2008, 19:40
PixelValue: http://forum.doom9.org/showthread.php?p=1045791#post1045791 (supports only RGB though at the moment). The first post of that thread contains a YCbCr version but it is gui-based.