ribbon model

Hi All,

This is my first piece with OpenFrameworks, it´s a work in progress but for now enjoy it. One video and source code at ->

www.jorgecano.net/cinta-OF.html

One more time :thanks for the library, Zach !

compiler: DEV c++
OF Version: 0.02
keys: space to capture background

[/b]

hey nice!

I’ve tried to run the code and it says something about ofCvContourFinder not having maxX and maxY. Did you hack anything on the opencv addon? (i think i have the latest version…)

anyway, thanks for sharing!

Hi, I forgot this.

To solve the problem you must add these lines to the ofCvContourFinder.h

float maxX;
float maxY;

And this is my ofCvContourFinder function in ofCvContourFinder.cpp :

//--------------------------------------------------------------------------
void ofCvContourFinder::findContours ( ofCvGrayscaleImage input,
int minArea,
int maxArea,
int nConsidered,
bool bFindHoles){

reset();

// opencv will clober the image it detects contours on, so we want to copy it
// into a copy before we detect contours. That copy is allocated if necessary
// (necessary = (a) not allocated or (b) wrong size)
// so be careful if you pass in different sized images to “findContours”
// there is a performance penalty, but we think there is not a memory leak to worry about
// better to create mutiple contour finders for different sizes, ie,
// if you are finding contours in a 640x480 image but also a 320x240 image
// better to make two ofCvContourFinder objects then to use one, because
// you will get penalized less.

if (inputCopy.width == 0){
inputCopy.allocate(input.width, input.height);
inputCopy = input;
} else {
if (inputCopy.width == input.width && inputCopy.height == input.height){
inputCopy = input;
} else {
// we are allocated, but to the wrong size –
// been checked for memory leaks, but a warning:
// be careful if you call this function with alot of different
// sized “input” images!, it does allocation every time
// a new size is passed in…
inputCopy.clear();
inputCopy.allocate(input.width, input.height);
inputCopy = input;
}
}

CvSeq* contour_list = NULL;
contour_storage = cvCreateMemStorage(1000);
storage = cvCreateMemStorage(1000);

CvContourRetrievalMode retrieve_mode = (bFindHoles) ? CV_RETR_LIST : CV_RETR_EXTERNAL;
cvFindContours (inputCopy.getCvImage(), contour_storage, &contour_list, sizeof(CvContour), retrieve_mode, CV_CHAIN_APPROX_SIMPLE);
CvSeq* contour_ptr = contour_list;

nCvSeqsFound = 0;
//-------------------------------------
// put the contours from the linked list, into an array for sorting
while ((contour_ptr != NULL)){

float area = fabs(cvContourArea(contour_ptr, CV_WHOLE_SEQ));

if ((area > minArea) && (area < maxArea)) {
if (nCvSeqsFound < MAX_NUM_CONTOURS_TO_FIND){
cvSeqBlobs[nCvSeqsFound] = contour_ptr; // copy the pointer
nCvSeqsFound++;
}
}

contour_ptr = contour_ptr->h_next;
}
//------------------------------------- sort the pointers based on size…
if (nCvSeqsFound > 0){
qsort( cvSeqBlobs, nCvSeqsFound, sizeof(CvSeq*), qsort_carea_compare);
}

// now, we have nCvSeqsFound contours, sorted by size in the array cvSeqBlobs
// let’s get the data out and into our structures that we like…

nBlobs = MIN(nConsidered, nCvSeqsFound); // take the minumum!

//vamos a averiguar cuál es el punto más alto de los contornos detectados
maxX = 0.0f;
maxY = 240.0f;

for (int i = 0; i < nBlobs; i++){

float area = cvContourArea(cvSeqBlobs[i], CV_WHOLE_SEQ);
CvRect rect = cvBoundingRect(cvSeqBlobs[i], 0);
cvMoments(cvSeqBlobs[i], myMoments);

blobs[i].area = fabs(area);
blobs[i].hole = area < 0 ? true : false;
blobs[i].length = cvArcLength(cvSeqBlobs[i]);
blobs[i].boundingRect.x = rect.x;
blobs[i].boundingRect.y = rect.y;
blobs[i].boundingRect.width = rect.width;
blobs[i].boundingRect.height = rect.height;
blobs[i].centroid.x = (int) (myMoments->m10 / myMoments->m00);
blobs[i].centroid.y = (int) (myMoments->m01 / myMoments->m00);

// get the points for the blob:
blobs[i].nPts = MIN(MAX_CONTOUR_LENGTH, cvSeqBlobs[i]->total);

CvPoint pt;
CvSeqReader reader;
cvStartReadSeq (cvSeqBlobs[i], &reader, 0);

for (int j=0; j < blobs[i].nPts; j++){
CV_READ_SEQ_ELEM(pt, reader);
blobs[i].pts[j].x = (float)pt.x;
blobs[i].pts[j].y = (float)pt.y;
//si la coordenada y es menor (punto mas alto)…
if ((float)pt.y < maxY){
maxY = (float)pt.y;
maxX = (float)pt.x;
}
}
}
//-----------------------------------------------------
// Free the storage memory.
// Warning: do this inside this function otherwise you get a strange memory leak
if (contour_storage != NULL) { cvReleaseMemStorage(&contour_storage);}
if (storage != NULL) { cvReleaseMemStorage(&storage);}

}

try it. Un saludo!