Extract motion from your video sources

Paul van Dinther

New Member
I wish I had access to the Guides section because that is where this belongs.

I was inspired by this video by youtuber Posy and wanted to make this using OBS.
It is basically time shifting a video and subtract the frames from each other thus
highlighting the motion.

For this effect I installed the Multi Source Effect which turns out to be a well rounded plugin.

You start by creating three scenes. Original, Timeshifted and Final Scene.
Place the same source in the Original Scene and Timeshifted Scene.
Add a renderdelay filter to the Timeshifted SCENE. Don't put it directly on the video source.
Set the renderdelay to about 100ms but you should tinker with this depending on the video content.

1701723308449.png


Now we setup the properties for the Multi SourceEffect.
The plugin can take in up to 4 sources but we only need two, being the Scenes holding the video.

The magic happens inside the effects file. For every video frame there will be two images.
The original and another one afew frames later depending on the render delay setting.
The effects file contains the code for canceling out non moving pixels.

1701723902158.png


The fun is that you can do all sorts of crazy stuff with this tool because it can take in multple sources.
Another thing I like is that you can keep the effects file loaded in the editor.
Make a change, save and you instantly see the results. It was unbreakable.
The code for the movement extraction is below. Just make a new text file and copy the code in it.

movement.effect
Code:
uniform float4x4 ViewProj;
uniform texture2d src0;
uniform texture2d src1;

sampler_state def_sampler {
    Filter   = Linear;
    AddressU = Clamp;
    AddressV = Clamp;
};

struct VertInOut {
    float4 pos : POSITION;
    float2 uv  : TEXCOORD0;
};

VertInOut VSDefault(VertInOut vert_in)
{
    VertInOut vert_out;
    vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
    vert_out.uv  = vert_in.uv;
    return vert_out;
}

float4 PSDrawBare(VertInOut vert_in) : TARGET
{
    float4 c1 = src0.Sample(def_sampler, vert_in.uv) / 2;
    float4 c2 = src1.Sample(def_sampler, vert_in.uv) / 2;
    float c = (0.75 + (c1.x + c1.y + c1.z + 0.75) - (c2.x + c2.y + c2.z + 0.75)) / 3;
    return float4(c,c,c,1);
}

technique Draw
{
    pass
    {
        vertex_shader = VSDefault(vert_in);
        pixel_shader  = PSDrawBare(vert_in);
    }
}

Enjoy
 

Attachments

  • 1701723366071.png
    1701723366071.png
    37.2 KB · Views: 96

Geesebreath

New Member
Thank you so much! I've been messing around with regular filters trying to make this work and it just doesn't work nearly as well as your solution.
 
Top