Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion demos/flowWebCam/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ set (CMAKE_CXX_COMPILER "g++")
set (CMAKE_CXX_FLAGS "-std=c++11 -flto -O2 -Wall")



add_executable( flowWebCam src/flowWebCam.cpp )
target_link_libraries( flowWebCam ${OpenCV_LIBS} ${LIBS})
target_link_libraries( flowWebCam ${OpenCV_LIBS} ${LIBS})
40 changes: 26 additions & 14 deletions demos/flowWebCam/src/flowWebCam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include <iostream>
#include <vector>

#include <ctime>
#include <unistd.h>
#include <sys/time.h>

#include <opencv2/opencv.hpp>

#include <flowfilter/gpu/flowfilter.h>
Expand Down Expand Up @@ -40,6 +44,7 @@ void wrapCVMat(Mat& cvMat, image_t& img) {
int main(int argc, char** argv) {

int cameraIndex = 0;
timeval start, end;

// if user provides camera index
if(argc > 1) {
Expand All @@ -50,12 +55,12 @@ int main(int argc, char** argv) {
if(!cap.isOpened()){
return -1;
}

Mat frame;


Mat frame, frameTrue;

// captura a frame to get image width and height
cap >> frame;
cap >> frameTrue;
cv::flip(frameTrue, frame, 1);
int width = frame.cols;
int height = frame.rows;
cout << "frame shape: [" << height << ", " << width << "]" << endl;
Expand All @@ -69,14 +74,13 @@ int main(int argc, char** argv) {

wrapCVMat(frameGray, hostImageGray);
wrapCVMat(fcolor, hostFlowColor);


//#################################
// Filter parameters
//#################################
float maxflow = 40.0f;
vector<float> gamma = {500.0f, 50.0f, 5.0f};
vector<int> smoothIterations = {2, 8, 20};
float maxflow = 4.0f;
vector<float> gamma = {10, 50,10};
vector<int> smoothIterations = {3, 3,3};

//#################################
// Filter creation with
Expand All @@ -94,21 +98,26 @@ int main(int argc, char** argv) {
Mat flowHost(height, width, CV_32FC2);
image_t flowHostWrapper;
wrapCVMat(flowHost, flowHostWrapper);


// Color encoder connected to optical flow buffer in the GPU
FlowToColor flowColor(filter.getFlow(), maxflow);
FlowToColor flowColor(filter.getFlow(), maxflow, 1);


// Capture loop
for(;;) {


// capture a new frame from the camera
// and convert it to gray scale (uint8)
cap >> frame;
cvtColor(frame, frameGray, CV_BGR2GRAY);
gettimeofday(&start, 0);
cap >> frameTrue;

cv::flip(frameTrue, frame, 1);

cvtColor(frame, frameGray, CV_BGR2GRAY);

// transfer image to flow filter and compute

filter.loadImage(hostImageGray);
filter.compute();

Expand All @@ -128,8 +137,11 @@ int main(int argc, char** argv) {

imshow("image", frameGray);
imshow("optical flow", fcolor);

if(waitKey(1) >= 0) break;
waitKey(5);
//if(waitKey(5) >= 0) break;
gettimeofday(&end, 0);
//cout << "difference: " << (end.tv_usec/1000.0 - start.tv_usec/1000.0) << endl << endl;
cout << "fps: " << 1000.0/(end.tv_usec/1000.0 - start.tv_usec/1000.0) << endl << endl;
}

// the camera will be deinitialized automatically in VideoCapture destructor
Expand Down
4 changes: 3 additions & 1 deletion include/flowfilter/colorwheel.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ namespace flowfilter {
* The color wheel texture contains RGB values for each
*/
FLOWFILTER_API extern unsigned char COLOR_WHEEL_D[];
FLOWFILTER_API extern unsigned char COLOR_WHEEL_DARK_D[];

FLOWFILTER_API const int COLOR_WHEEL_HEIGHT = 256;
FLOWFILTER_API const int COLOR_WHEEL_WIDTH = 256;
FLOWFILTER_API const int COLOR_WHEEL_DEPTH = 4;


FLOWFILTER_API image_t getColorWheelRGBA();
FLOWFILTER_API image_t getColorWheelDarkRGBA();

}; // namespace flowfilter

#endif // FLOWFILTER_COLORWHEEL_H_
#endif // FLOWFILTER_COLORWHEEL_H_
4 changes: 3 additions & 1 deletion include/flowfilter/gpu/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class FLOWFILTER_API FlowToColor : public Stage {
public:
FlowToColor();
FlowToColor(flowfilter::gpu::GPUImage inputFlow, const float maxflow);
FlowToColor(flowfilter::gpu::GPUImage inputFlow, const float maxflow, const int colorwheelselected);
~FlowToColor();

public:
Expand Down Expand Up @@ -78,6 +79,7 @@ class FLOWFILTER_API FlowToColor : public Stage {
bool __inputFlowSet;

float __maxflow;
int __colorWheelSelect;

flowfilter::gpu::GPUImage __colorWheel;
flowfilter::gpu::GPUTexture __colorWheelTexture;
Expand All @@ -95,4 +97,4 @@ class FLOWFILTER_API FlowToColor : public Stage {
}; // namepsace gpu
}; // namespace flowfilter

#endif // FLOWFILTER_DISPLAY_H_
#endif // FLOWFILTER_DISPLAY_H_
2 changes: 1 addition & 1 deletion include/flowfilter/gpu/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,4 @@ class FLOWFILTER_API GPUTexture {
}; // namespace flowfilter


#endif // FLOWFILTER_GPU_IMAGE_H_
#endif // FLOWFILTER_GPU_IMAGE_H_
261 changes: 27 additions & 234 deletions notebooks/GPU_example.ipynb

Large diffs are not rendered by default.

49 changes: 0 additions & 49 deletions python/flowfilter/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"""

import numpy as np
import numpy.linalg as la
import scipy.ndimage as nd

__all__ = ['imagePyramid', 'imageDown', 'imageUp']
Expand Down Expand Up @@ -141,51 +140,3 @@ def imageUp(img, order=1):

# recombine channels and return
return np.concatenate([p[...,np.newaxis] for p in zoomList], axis=2)


def endpointError(flow1, flow2):
"""returns Endpoint Error between two flow fields

Parameters
----------
flow1 : ndarray.
First optical flow field.

flow2 : ndarray.
Second optical flow field.

Returns
-------
EE : endpoint error field.
Scalar field with the endpoint error.
"""

return la.norm(flow1 - flow2, axis=2)


def angularError(flow1, flow2):
"""returns the angular error between two flow fields.

Parameters
----------
flow1 : ndarray.
First optical flow field.

flow2 : ndarray.
Second optical flow field.

Returns
-------
AE : angular error field.
Scalar field with the angular error field in degrees.
"""

f1_x = flow1[...,0]
f1_y = flow1[...,1]

f2_x = flow2[...,0]
f2_y = flow2[...,1]

top = 1.0 + f1_x*f2_x + f1_y*f2_y
bottom = np.sqrt(1.0 + f1_x*f1_x + f1_y*f1_y)*np.sqrt(1.0 + f2_x*f2_x + f2_y*f2_y)
return np.rad2deg(np.arccos(top / bottom))
45 changes: 33 additions & 12 deletions python/flowfilter/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@

# load color wheel image
colorWheel = misc.imread(pkg_resources.resource_filename('flowfilter.rsc', 'colorWheel.png'), flatten=False)
colorWheelDark = misc.imread(pkg_resources.resource_filename('flowfilter.rsc', 'colorWheelDark.png'), flatten=False)

# RGB components of colorwheel
_colorWheel_R = np.copy(colorWheel[...,0])
#_colorWheel_R = np.copy(colorWheel[...,0])
#_colorWheel_G = np.copy(colorWheel[...,1])
#_colorWheel_B = np.copy(colorWheel[...,2])
_colorWheel_R = np.copy(colorWheel[...,2])
_colorWheel_G = np.copy(colorWheel[...,1])
_colorWheel_B = np.copy(colorWheel[...,2])
_colorWheel_B = np.copy(colorWheel[...,0])
_colorWheelDark_R = np.copy(colorWheelDark[...,2])
_colorWheelDark_G = np.copy(colorWheelDark[...,1])
_colorWheelDark_B = np.copy(colorWheelDark[...,0])


def flowToColor(flow, maxflow=1.0):
def flowToColor(flow, maxflow=1.0, colorWheelReq=0):
"""Returns the color wheel encoded version of the flow field.

Parameters
Expand All @@ -37,6 +44,9 @@ def flowToColor(flow, maxflow=1.0):
maxflow : float, optional
Maximum flow magnitude. Defaults to 1.0.

colorWheelReq : int, optional
ColorWheel assignment. Defaults to light wheel.

Returns
-------
flowColor : ndarray
Expand All @@ -48,10 +58,17 @@ def flowToColor(flow, maxflow=1.0):
"""

if maxflow <= 0.0: raise ValueError('maxflow should be greater than zero')

# height and width of color wheel texture
h, w = colorWheel.shape[0:2]


if colorWheelReq == 0:
h, w = colorWheel.shape[0:2]
elif colorWheelReq == 1:
h, w = colorWheelDark.shape[0:2]
else:
print "Error: flowToColor (3rd var) call wrong colorWheel value"
return 0

# scale optical flow to lie in range [0, 1]
flow_scaled = (flow + maxflow) / float(2*maxflow)

Expand All @@ -73,15 +90,19 @@ def flowToColor(flow, maxflow=1.0):
color_B = np.zeros_like(color_R)

# interpolate flow coordinates into RGB textures
interp.map_coordinates(_colorWheel_R, flow_swapped, color_R, order=0, mode='nearest', cval=0)
interp.map_coordinates(_colorWheel_G, flow_swapped, color_G, order=0, mode='nearest', cval=0)
interp.map_coordinates(_colorWheel_B, flow_swapped, color_B, order=0, mode='nearest', cval=0)

if colorWheelReq == 0:
interp.map_coordinates(_colorWheel_R, flow_swapped, color_R, order=0, mode='nearest', cval=0)
interp.map_coordinates(_colorWheel_G, flow_swapped, color_G, order=0, mode='nearest', cval=0)
interp.map_coordinates(_colorWheel_B, flow_swapped, color_B, order=0, mode='nearest', cval=0)
elif colorWheelReq == 1:
interp.map_coordinates(_colorWheelDark_R, flow_swapped, color_R, order=0, mode='nearest', cval=0)
interp.map_coordinates(_colorWheelDark_G, flow_swapped, color_G, order=0, mode='nearest', cval=0)
interp.map_coordinates(_colorWheelDark_B, flow_swapped, color_B, order=0, mode='nearest', cval=0)

# creates output image
flowColor = np.zeros((flow.shape[0], flow.shape[1], 3), dtype=np.uint8)
flowColor[:,:,0] = color_R.reshape(flow.shape[0:2])
flowColor[:,:,1] = color_G.reshape(flow.shape[0:2])
flowColor[:,:,2] = color_B.reshape(flow.shape[0:2])

return flowColor

return flowColor
63 changes: 63 additions & 0 deletions python/flowfilter/rotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
flowfilter.rotation
----------------------

Module containing rotational optical flow methods.

:copyright: 2015, Juan David Adarve, ANU. See AUTHORS for more details
:license: 3-clause BSD, see LICENSE for more details
"""

import numpy as np
import numpy.linalg as la


def rotationalOpticalFlow(K, ishape, w):
"""Computes rotational optical flow given camera intrinsics and angular velocity.

Parameters
----------
K : ndarray.
3x3 camera intrinsics matrix.

ishape : 2-vector.
image resolution (height, width).

w : 3-vector.
angular velocity (wx, wy, wz).

Returns
-------
phi : ndarray.
Rotational optical flow field. (height, width, 2) float32 array.
"""

# inverse intrinsics matrix
Kinv = la.inv(K)

# angular velocity components
wx, wy, wz = w

# pixel coordinates
X, Y = np.meshgrid(np.arange(ishape[1]), np.arange(ishape[0]))

# image plane coordinates
pcoord = np.zeros((ishape[0], ishape[1], 3))

# p = Kinv*(x, y, 1)^T
pcoord[...,0] = Kinv[0,0]*X + Kinv[0,1]*Y + Kinv[0,2]*1
pcoord[...,1] = Kinv[1,0]*X + Kinv[1,1]*Y + Kinv[1,2]*1
pcoord[...,2] = Kinv[2,0]*X + Kinv[2,1]*Y + Kinv[2,2]*1

# cross product between angular velocity and pcoord
crossProd = np.zeros((ishape[0], ishape[1], 3))
crossProd[...,0] = -pcoord[...,1]*wz + pcoord[...,2]*wy
crossProd[...,1] = pcoord[...,0]*wz - pcoord[...,2]*wx
crossProd[...,2] = -pcoord[...,0]*wy + pcoord[...,1]*wx

# rotational optical flow
phi = np.zeros((ishape[0], ishape[1], 2), dtype=np.float32)
phi[...,0] = K[0,0]*crossProd[...,0] + (K[0,2] - X)*crossProd[...,2]
phi[...,1] = K[1,1]*crossProd[...,1] + (K[1,2] - Y)*crossProd[...,2]

return phi
Binary file added python/flowfilter/rsc/colorWheelDark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def createExtension(name, sources):
# package data include Cython .pxd files
package_data = {'flowfilter' : ['*.pxd'],
'flowfilter.gpu': ['*.pxd'],
'flowfilter.rsc' : ['colorWheel.png']}
'flowfilter.rsc' : ['colorWheel.png','colorWheelDark.png',]}

#################################################
# CYTHON EXTENSIONS
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ message(STATUS "entering src folder")
add_gpu_sources (
image.cpp
colorwheel.cpp
colorwheeldark.cpp
)

# process CMakeLists.txt in gpu folder
Expand Down
4 changes: 2 additions & 2 deletions src/colorwheel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace flowfilter {

unsigned char COLOR_WHEEL_D[] =
unsigned char COLOR_WHEEL_D[] =
{
0x00, 0x27, 0xBF, 0xFF, 0x00, 0x26, 0xBF, 0xFF, 0x00, 0x26, 0xBF, 0xFF,
0x00, 0x25, 0xBF, 0xFF, 0x00, 0x25, 0xBF, 0xFF, 0x00, 0x24, 0xBF, 0xFF,
Expand Down Expand Up @@ -21873,4 +21873,4 @@ image_t getColorWheelRGBA() {
}


};
};
Loading