"Recording" a contour obtained with ofxCv

#1

hi all,

i am having trouble understanding how an idea might look as code. i would be grateful for anyone who can offer input and direction :slight_smile:

i am using ofxcv to receive the contour of an object. i want to record it’s movement so that once this specific contour is no longer being tracked, a “shadow” is left behind that is the same shape as the contour and moves exactly how the object did in its lifetime. so if the object moves around in a bunch of irregular spirals and then it disappears, a shadow of the object is drawn and moves in the same irregular spirals, and i can just loop that movement so that once it ends it starts from the beginning again.

some specific questions i have, beyond the general “how i might do what i just described”:

  • ofxcv has a tracker that i think i can use for this? i’m looking at the header file though and am not sure i completely grasp the differences between the labels (current, previous, new, dead).
  • if i am interested in recording multiple objects, and having several shadows and their movements looping and possibly interacting with each other, will it be computationally expensive? are there areas i can optimize?
  • better to use a depth camera over usb camera? i am doing this with controlled lighting with a usb camera right now, but don’t think it will be as uniform in other places.

thank you!

tristan

#2

To obtain the contour you can use for example kinect camera and using the depth map apply a contourFinder, that will make the obtain of the contour much more easy than with a webcam.

You can later store those contours in a vector to later draw those or you can use something like the fboTrails example.

#3

This old (but excellent) project does contour recording, perhaps it is useful to you?

#4

@pandereto
@phaseIV

hi both, thanks for offering input! i found this project that @zach did that i think is a little closer to what i’m going for, specifically the innerstamp section. i hope it clarifies things.

i think i have to do something where each point in a contour remembers its previous locations while being recorded, and then interpolating through them to “replay” the shape?

1 Like
#5

Hi,
To “replay the shape” you can record the contour for each new video frame. Meaning that for each frame you have to record the time of this frame and the points of the contour. This is enough to replay the shape at the same speed than the video input.
This way, you don’t need to interpolate between the successive contours. Interpolation may be usefull if you want to replay the shape at a lower speed and smooth the movement, but can be tricky to implement: OpenCV don’t give you for each frame a contour with the same number of points, or a “same point” may not have the same indice in successive frames.

#6

hi @lilive,

thanks for what you’re suggesting! it feels like a good direction. i’m not quite sure though if i understand how this looks as code. am i recording the time of the frame and the contour in their own vectors? if i’m not interpolating, how do i replay the shape?

#7

Here what’s on my mind:

  • The camera (or the video) show an object
  • You track the object Contour (with an uppercase C, meaning its real contour, on object has one contour)
  • You obtain N contours, one for each video frame (contour with a lowercase c, meaning the position of the Contour in each frame, the same real object produce many contours)
  • Each contour has a recording time, meaning the moment of its detection in the video

To replay, you just have to draw each contour, in the same order, at the same rate they were detected.

For me, interpolate in this context means: compute (create) a contour at a time where I’ve got no existing contour. If you just want to display again the Contour, as it was detected, there’s no need to do that. But perhaps you’ve got something else in your mind ?

To store the contours and their times you’ve got many solutions. For example, if a contour is an ofPolyline, you can do:

  • 2 vectors, like you said, vector< float > for the times and vector< ofPolyline > for the contours
  • a vector of pairs, vector< pair< float, ofPolyline > > where the first element of a pair is the time and the second a contour
  • a vector of a custom object Record, vector< Record > where Record can be
struct Record {
    float time;
    ofPolyline contour;
}

and there are other solutions.

A rough pseudocode for the replay can be:

function startReplay
    startReplayTime = now

function drawReplay
    replayTime = now - startReplayTime
    contour = ( find first contour which has a time >= replayTime )
    if contour found, draw it
    else stop replay
#8

hi @lilive,

sorry for my very very slow reply. i have been casually coming to this problem in the last few weeks! it’s now working closer to what i wanted. i decided to store each recording into a map and use lower_bound to get the contour that was recorded at the replayTime. now i’m trying to understand how to “loop” the replay because it stops once it reaches the end. thanks for your help up to this point :slight_smile:

:blossom: tristan

#9

sorry for my very very slow reply. i have been casually coming to this problem in the last few weeks!

No problem !

it’s now working closer to what i wanted. i decided to store each recording into a map and use lower_bound to get the contour that was recorded at the replayTime.

Glad you make it works. I didn’t know lower_bound. Really handy here.

now i’m trying to understand how to “loop” the replay because it stops once it reaches the end.

I think you will find quickly. If you have a function like my startReplay() pseudocode, you just have to call it again. But perhaps you’re looking for a “ping-pong loop” ? Anyway, feel free to post your code for more help.

#10

@lilive and all,

i ended up solving it quickly like you mentioned. rather than calling the replay function again once it reaches the end, i just move the start time, like so:


function drawReplay
    ...
    if (end of replay is reached) startReplayTime = now;
    replayTime = now - startReplayTime;
    ...

now am going to do weird fun art things with this. thank you again! cheers

1 Like