Skip to content

Commit

Permalink
Add Optical Flow effect with example #97
Browse files Browse the repository at this point in the history
  • Loading branch information
brianchirls committed Sep 5, 2015
1 parent 77a6faf commit f34009e
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ Full documentation is in progress at the [wiki](https://github.com/brianchirls/S
- Checkerboard Generator
- Chroma Key
- Color Complements
- Color Generator
- [Color Cube](http://www.youtube.com/watch?v=rfQ8rKGTVlg&t=24m30s)
- Color Generator
- Color Look-Up Table
- Color Select
- Color Temperature
- Crop
Expand Down Expand Up @@ -60,6 +61,7 @@ Full documentation is in progress at the [wiki](https://github.com/brianchirls/S
- Luma Key
- Mirror
- Night Vision
- Optical Flow
- Panorama
- Pixelate
- Polar Coordinates
Expand Down
145 changes: 145 additions & 0 deletions effects/seriously.opticalflow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/* global define, require */
(function (root, factory) {
'use strict';

if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['seriously'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS
factory(require('seriously'));
} else {
if (!root.Seriously) {
root.Seriously = { plugin: function (name, opt) { this[name] = opt; } };
}
factory(root.Seriously);
}
}(window, function (Seriously) {
'use strict';

/*
Horn-Schunke Optical Flow
Based on shader by Andrew Benson
https://github.com/v002/v002-Optical-Flow/blob/master/v002.GPUHSFlow.frag
Creative Commons, Attribution – Non Commercial – Share Alike 3.0
http://v002.info/licenses/
*/

Seriously.plugin('opticalflow', function () {
var previousFrameBuffer,
baseShader;

return {
initialize: function (initialize) {
previousFrameBuffer = new Seriously.util.FrameBuffer(this.gl, this.width, this.height);
initialize();
baseShader = this.baseShader;
},
resize: function () {
previousFrameBuffer.resize(this.width, this.height);
},
commonShader: true,
shader: function (inputs, shaderSource) {
shaderSource.fragment = [
'precision mediump float;',

'varying vec2 vTexCoord;',

'uniform sampler2D source;',
'uniform sampler2D previous;',
'uniform vec2 resolution;',

'uniform vec2 scale;',
'uniform float offsetX;',
'uniform float lambda;',
// 'const vec4 lumcoeff = vec4(0.299, 0.587, 0.114, 0.0);',

'void main() {',
' vec4 a = texture2D(previous, vTexCoord);',
' vec4 b = texture2D(source, vTexCoord);',
' vec2 offset = offsetX / resolution;',
' vec2 x1 = vec2(offset.x, 0.0);',
' vec2 y1 = vec2(0.0, offset.y);',

//get the difference
' vec4 curdif = b - a;',

//calculate the gradient
' vec4 gradx = texture2D(source, vTexCoord + x1) - texture2D(source, vTexCoord - x1);',
' gradx += texture2D(previous, vTexCoord + x1) - texture2D(previous, vTexCoord - x1);',

' vec4 grady = texture2D(source, vTexCoord + y1) - texture2D(source, vTexCoord - y1);',
' grady += texture2D(previous, vTexCoord + y1) - texture2D(previous, vTexCoord - y1);',

' vec4 gradmag = sqrt((gradx * gradx) + (grady * grady) + vec4(lambda));',

' vec4 vx = curdif * (gradx / gradmag);',
' float vxd = vx.r;', //assumes greyscale

//format output for flowrepos, out(-x,+x,-y,+y)
' vec2 xout = vec2(max(vxd, 0.0), abs(min(vxd, 0.0))) * scale.x;',

' vec4 vy = curdif * (grady / gradmag);',
' float vyd = vy.r;', //assumes greyscale

//format output for flowrepos, out(-x,+x,-y,+y)
' vec2 yout = vec2(max(vyd, 0.0), abs(min(vyd, 0.0))) * scale.y;',

' gl_FragColor = clamp(vec4(xout.xy, yout.xy), 0.0, 1.0);',
' gl_FragColor.a = 1.0;',
'}'
].join('\n');

return shaderSource;
},
draw: function (shader, model, uniforms, frameBuffer, parent) {
uniforms.previous = previousFrameBuffer.texture;

parent(shader, model, uniforms, frameBuffer);

//todo: just swap buffers rather than copy?
parent(baseShader, model, uniforms, previousFrameBuffer.frameBuffer);
},
destroy: function () {
if (previousFrameBuffer) {
previousFrameBuffer.destroy();
previousFrameBuffer = null;
}
}
};
},
{
inPlace: false,
inputs: {
source: {
type: 'image',
uniform: 'source',
shaderDirty: false
},
lambda: {
type: 'number',
uniform: 'lambda',
min: 0,
defaultValue: 0,
description: 'noise limiting'
},
scaleResult: {
type: 'vector',
dimensions: 2,
uniform: 'scale',
defaultValue: [1, 1]
},
offset: {
type: 'number',
uniform: 'offsetX',
defaultValue: 1,
min: 1,
max: 100,
description: 'distance between texel samples for gradient calculation'
}
},
description: 'Horn-Schunke Optical Flow',
title: 'Optical Flow'
});
}));
1 change: 1 addition & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<li><a href="demo/select.html">Select</a></li>
<li><a href="demo/drunk.html">Drunk</a></li>
<li><a href="demo/fog.html">Fog</a></li>
<li><a href="opticalflow.html">Optical Flow</a></li>
<li><a href="demo/panorama.html">Panorama</a></li>
<li><a href="demo/threejs-source.html">Three.js Source</a></li>
<li><a href="demo/threejs-target.html">Three.js Target</a></li>
Expand Down
59 changes: 59 additions & 0 deletions examples/opticalflow.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>Seriously.js Optical Flow Example</title>
<style type="text/css">
#canvas {
max-width: 100%;
}
</style>
</head>
<body>
<canvas id="canvas" width="1280" height="720"></canvas>
<script src="../seriously.js"></script>
<script src="../sources/seriously.camera.js"></script>
<script src="../effects/seriously.opticalflow.js"></script>
<script>
(function() {
//main code goes here

// declare our variables
var seriously, // the main object that holds the entire composition
camera, // wrapper object for source video
opticalflow, // mirror detection effect
target, // a wrapper object for our target canvas
reformat;

if (Seriously.incompatible('camera')) {
document.body.appendChild(document.createTextNode('Sorry, your browser does not support getUserMedia'));
document.querySelector('canvas').style.display = 'none';
return;
}

// construct our seriously object
seriously = new Seriously();

camera = seriously.source('camera'/*, {
todo: refactor camera plugin for updated getUserMediaConstraints
video: {
width: 1280,
height: 720
}
}*/);
target = seriously.target('#canvas');
opticalflow = seriously.effect('opticalflow');
reformat = seriously.transform('reformat');
reformat.width = 1280;
reformat.height = 720;
reformat.mode = 'cover';

// connect all our nodes in the right order
reformat.source = camera;
opticalflow.source = reformat;
target.source = opticalflow;

seriously.go();
}());
</script>
</body>
</html>
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<script type="text/javascript" src="effects/seriously.directionblur.js"></script>
<script type="text/javascript" src="effects/seriously.nightvision.js"></script>
<script type="text/javascript" src="effects/seriously.noise.js"></script>
<script type="text/javascript" src="effects/seriously.opticalflow.js"></script>
<script type="text/javascript" src="effects/seriously.pixelate.js"></script>
<script type="text/javascript" src="effects/seriously.polar.js"></script>
<script type="text/javascript" src="effects/seriously.ripple.js"></script>
Expand Down

0 comments on commit f34009e

Please sign in to comment.