Animating Points within ContourFinder

Hey guys! I’m new to OF and playing around with contour finder and ofxCV. I want to make points move around inside the contour, and am slightly confused how to get the points or do that. Do I need a convex Hull? For now I have this in draw:

int n = contour.size();
for(int i = 0; i < n; i++) {
ofPoint center = toOf(contour.getCenter(i));//center point of contour
double area = contour.getContourArea(i);//area of contour
ofPolyline polyline = contour.getPolyline(i);
auto vertices = polyline.getVertices();
for (int p=0; p<100; p+=1) {
ofVec3f point = polyline.getPointAtPercent(p/500.0);
ofDrawCircle(point, 2);

For now, a contour outlined with dots appear. However, I am not sure how to make the dots move or bounce around inside the contour, and am not sure if that’s how I get the contour extremes/points? I know how to make a polyline but am not sure how to get the points for it, I’m guessing I need a points class too?

Would appreciate any help, thank you!

1 Like

Hi, do you want to move those circles along the contour or do you want to have the moving “randoml” inside the contour? can you add some visual reference please for what you want to achieve?
As for movign these along the contour you can do something like

	float speed = .4;
	float t = ofGetElapsedTimef() * speed;
	int numPoints = 10;
	for (int i=0; i<numPoints; i++) {
		ofDrawCircle(polyline.getPointAtPercent( ofWrap(t + i/(float)numPoints,0,1)), 2);
	}

Thank you so much for you reply! I was thinking of the circles to move randomly inside the contour.

So the points will move inside the contours of the hand. The image below is the circles moving along the contour.

This is a reference from friendred studio

I am not sure how you access the points of the contours without getting a polyline.
I see this in the contour finder library and was wondering if this is how I get the extreme points? I iterate through contour.size() but how do I get the separate points, does it have to go through get vertices after making a polyline? Sorry if it’s a super dumb question…

const std::vector<std::vectorcv::Point >& getContours() const ;

Thank you again!

I see.
and there are no stupid questions here :smiley:
actually the contour is just a collection of collections of points (yes a collection of collections, that’s not a type). you access these as in any regular array or vector, using its index.
The thing is that even when the contours have a fisrt and last point it is not necesary that these will be at the extremes so you need to find the extremes. Just iterate through and find which are these

so


auto & contours = contourFinder.getContours(); // this is a reference not a copy. notice the & . simlpy thing of it as an alias in this case, to unclutter the code
	for (int i = 0; i < contours.size(); i++)
	{
		int left_index, right_index;
		float mx = - std::numeric_limits<float>::max(); // we set it to the negative maximum value possible
		float mn =  std::numeric_limits<float>::max();  // we set it to the positive maximum value possible
		
		for (int j = 0; j < contours[i].size(); j++)
		{
			if(mx < contours[i][j].x )
			{
				mx = contours[i][j].x ;
				right_index = j;
			}
			
			if(mn > contours[i][j].x )
			{
				mn = contours[i][j].x ;
				left_index = j;
			}
		}
		//so now you've found the left most and rightmost points and you access these by
		contours[i][left_index];
		contours[i][right_index];
	}

as for the dots moving randomly inside first make some particle system with these particles moving around. On each update test each point to see if it is inside or outside the contour. If it is outside then you should bounce it of the wall. In this case ofPolyline provides several utility functions that will be really helpful. There is one that checks if a point is inside or outside of the polyline.


if( ! polyline.inside(some_point))
{
// bounce. 
}

it is up to you how to make it bounce. you can simply flip its direction or bounce it according to the normal of the polyline shape. there are also functions that will help you with this in the ofPolyline class. Take a look at it’s documentation or read the ofPolyline.h file

Friendred is a friend of mine. :smiley: he is super talented and extremely hard working.

Thank you so much, such a great help! I’m currently working on it and have a quick question, if I do

auto li= contours[i][left_index];

li.x

Is li.x the most extreme left point?

if so, to check if the particles are inside the contour polyline, is it correct to put these bounds as being within the contour? Won’t that miss out the other extreme points along the contour?

if ( ! polyline.inside(li.x,li.y)&(ri.x,ri.y))

as in polyline.h it states ofInsidePoly(float x, float y, const std::vector& polygon)

Also, to initialise my particles, in setup, I set

myParticle.setInitialCondition(ofRandom(0,640),ofRandom(0,480),0,0)

particles get immediately draw all over on the screen before I can update it and check if its in the polygon, so it is not within the contour, is there any other way I could change the setup
I’m playing with using attraction forces with particles[i].addAttractionForce(li.x,li.y, 200, 1); //(x,y,radius, strength). For now, I think the particles are being attracted to the extreme points. I aim for the particles to only be repelled when reaching the bounds of the contour, so they stay within the contour.


Thank you so much once again! Really really appreciate it

it should be.

Not sure what you mean, yet you can skip finding the extreme points if you only want to find if the points are inside the polyline or not.

If you want to find the extreme points out of the ones that are inside the polyline, then you need to check in the same for loop if it is inside and if it is the most extreme, and only then update the extreme’s indices.

I have no idea how your particle system or its attractors work so it depends a lot on it.
Yet you could add to it a condition where it “kills” a particle if it is not inside the contour. This mostly means adding a bool to the particle class and change it to kill the particle. Then the particle controller checks against it for either, removing the particle from the particle collection, reusing it and trying to give to it a new position within the contour or simply not drawing it.

you can skip finding the extreme points if you only want to find if the points are inside the polyline or not

aahhh I see, but to check it using

if( ! polyline.inside(some_point))

how do I get the some_points? is it using contour[i][j].x and y for the arguments for polyline.inside(some_point))

By some_point I meant just any point, not a specific variable named like that.
As countour is a collection of collection of points you can pass it like

if( ! polyline.inside(contour[i][j].x, contour[i][j].y))

Hello! sorry my bad, I tried it and had an error then but have fixed it. Thank you so much!

so I did

for (int i = 0; i < contours.size(); i++)
{

ofPolyline polyline = contourFinder.getPolyline(i);

for (int a = 0; j < particles.size(); j++){
particles[j].resetForce();
particles[j].addAttractionForce(contours[i][j].x,contours[i][j].y, 100, 5); // (x,y, radius, force)
particles[j].addRepulsionForce(contours[i][j].x,contours[i][j].y, 6, 1);
particles[j].addDampingForce();
particles[j].update();
if( ! polyline.inside(contours[i][j].x, contours[i][j].y)){
particles.erase(particles.begin()+j);
}
}

Do you know why when I used

particles.erase(particles.begin()+j);

it erased all the particles on the screen instead of just within the contour areas? It worked when I used it to delete particles which .y position were below a number

my particle class is based on the one in the OF Book

thank you so much again!

Hi, it is not a good idea to use that because it modifies the number of elements on the particles vector and messes up with the indexing values used in the for loop.
Instead do the following.

add a public bool to your particle class set to false by default. just add the following to your particle class h file

bool bKill = false;

then replace the code you posted with the following one.


    for (int i = 0; i < contours.size(); i++)
    {

    ofPolyline polyline = contourFinder.getPolyline(i);

    for (int a = 0; j < particles.size(); j++){
    particles[j].resetForce();
    particles[j].addAttractionForce(contours[i][j].x,contours[i][j].y, 100, 5); // (x,y, radius, force)
    particles[j].addRepulsionForce(contours[i][j].x,contours[i][j].y, 6, 1);
    particles[j].addDampingForce();
    particles[j].update();
    if( ! polyline.inside(contours[i][j].x, contours[i][j].y)){
    particles[j].bKill = true;
    }
ofRemove(particles, [](ParticleClass & p){return p.bKill;});// replace ParticleClass with the correct name of your particle's class

    }

Thank you so much and for your time! Will refine it more! :slight_smile:

1 Like