Attaching shapes to ofxcv contour across frames?

hi hi! wanted to reach out to y’all and ask if anyone could help me understand this problem better. i want to attach shapes to a contour that i get from ofxcv. however the movement is very jerky and convulsive. i think it’s because i get a variable number of points back every frame when finding contours and turning them into polylines.

i’m now resampling the polylines so that i get ones with the same amount of points every frame, but i think there’s still an issue of how to figure out where to put the start position for each polyline, and i’m not quite sure how to address this computationally. some guidance here would be very much appreciated.

thanks!
tristan

The starting point vertex should not be a problem, theoretically, ofxCV does not know what is what you define as “starting point”. Once you have a contour, you have a polyline (or even points using ofxCV), and once you have a polyline you can have shapes. There are several ways to get a shape, you could:

The main problem, usually, is to get a stable contour.

Edit, I read your question again and I have understand what you meant with “start position”. I forgot to say that you should empty your polyline/ofPath/tesselletad mesh before every new call to the contourFinder.findContours(frameImg);. It sounds expensive, but it is the way to go.

one solution to this problem is to try to figure out what the best index to start from is by point by point comparison with the poly line from the last frame.

the polyline is a chain so potentially it’s start could be anywhere, right?

for example if you always resample to 100 points, check the incoming polyline starting from 0…100, then starting at 1 (and wrapping around to 0), then starting at 2 (and wrapping to 1), all the way up to starting at point 99… you can check what is the average distance of each point of this new polyline to the previous one and find the best “fit”, which starting position gives the smallest amount of change.

I usually do this + some smoothing then I can attach things to the contour fine… for example:

1 Like

Oh, only now I understand your original question. Another solution could be that each time you detect a new contour, you pick as first point for the polyline that one that is more close to a fixed point, that could be, for example, the the top left corner of the screen. In this case, I can imagine that the difference between each frame can be minimal and even if it changes it should change smoothly.

@edapx + @zach thanks for your suggestions and super compelling example, this was really helpful to understand things on a higher level. i think i’m still a little unsure about how checking each point and wrapping it around + determining the smallest amount of change translates to code, but i’ll try to break it down a little more and see where that gets me.

Well, if you want to compare two polylines, probably the best way is to iterate between the two vectors of points and calculate the euclidian distance between them? the smaller is the distance the more closer are the points?

1 Like

my two cents. instead of using the euclidean distance, which involves a square root calculation (that is expensive), just use the squared distance. As you would be only comparing squared distances you will also be able to determine the closest point and it will save you a lot of cpu cycles. This will become noticeable when using polylines with a lot of points and/or a lot of polylines.

So, considering you are using the last OF version which uses GLM for vector maths.

float squaredDistance =  glm::length2(point1 - point2);//this returns the squared distance
float euclideanDistance = glm::distance(point1 - point2);//this returns the euclidean distance

cheers

1 Like

@zach ++ @edapx / others

had time to sit down today and work through it. is this little snippet going in the right direction?

    while (index < numPoints)
    {
        float average;
        float sum;
        
        for (int i = index; i < index + numPoints; i++)
        {
            float euclideanDistance = glm::distance(prevContour[i%numPoints], currentContour[i%numPoints]);
            sum += euclideanDistance;
        }
        
        average = sum / numPoints;
        
        if (average < minDistance)
        {
            minDistance = average;
            start = index
        }
        
        index++;
    }

if so can i do something like this after to set the starting position of the current contour:

    for (int i = 0; i < numPoints i++)
    {
        currentPoly[i] = resampledPoly[(start+i)%numPoints];
    }

@roymacdonald i’m using euclidean distance right now but i’ll probably start using squared distance if i end up resampling to more points and / or comparing between multiple polylines.