/** * @brief Función del ratón que permite al usuario seleccionar el objeto a rastrear * @param event El tipo de evento generado por el ratón * @param x La coordenada x del píxel seleccionado * @param y La coordenada y del píxel seleccionado * @param flags Características del ratón * @param param Mis propios parámetros donde guardo las coordenadas y demás */ void mouse( int event, int x, int y, int flags, void *param ) { params *p = (params*)param; static int pressed = FALSE; // Al pulsar el botón izquierdo, guardamos la primera esquina del rectángulo que cubre al objeto if( event == CV_EVENT_LBUTTONDOWN ) { p->loc1.push_back(CvPoint()); p->loc1[p->n].x = x; p->loc1[p->n].y = y; pressed = TRUE; } // Al soltar el botón del ratón, finaliza el rectángulo y lo dibuja en negro else if( event == CV_EVENT_LBUTTONUP ) { p->loc2.push_back(CvPoint()); p->loc2[p->n].x = x; p->loc2[p->n].y = y; cvReleaseImage( &(p->cur_img) ); cvRectangle( first_frame, p->loc1[p->n], p->loc2[p->n], CV_RGB(0,0,0), 1, 8, 0 ); cvShowImage( win_name, first_frame ); pressed = FALSE; p->n++; } // Al arrastrar el ratón va dibujando el rectángulo en blanco else if( event == CV_EVENT_MOUSEMOVE && flags & CV_EVENT_FLAG_LBUTTON ) { p->cur_img = (IplImage*) cvClone( first_frame ); cvRectangle( p->cur_img, p->loc1[p->n], cvPoint(x, y), CV_RGB(255,255,255), 1, 8, 0 ); cvShowImage( win_name, p->cur_img ); cvReleaseImage( &(p->cur_img) ); } }
ColourToTrack::ColourToTrack(IplImage* image, int x, int y, float tolerance):xy(CvPoint()),decoder(MovementDecoder(tolerance)), lastPosition(cvPoint(-1,-1)),lastTolerant(LOST), lastIntolerant(LOST) { // Create the mask & initialize it to white (no color detected) mask = cvCreateImage(cvGetSize(image), image->depth, 1); CvScalar pixel=cvGet2D(image,y,x); colour.rgb.r=(int)pixel.val[2]; colour.rgb.g=(int)pixel.val[1]; colour.rgb.b=(int)pixel.val[0]; // Get the hsv image IplImage* hsv = cvCloneImage(image); //cvCvtColor(image, hsv, CV_BGR2HSV); cvCvtColor(image, hsv, CV_BGR2Lab); // Get the selected pixel pixel = cvGet2D(hsv, y, x); // Change the value of the tracked color with the color of the selected pixel colour.hsv.h = (int)pixel.val[0]; colour.hsv.s = (int)pixel.val[1]; colour.hsv.v = (int)pixel.val[2]; // Release the memory of the hsv image cvReleaseImage(&hsv); }
ColourToTrack::ColourToTrack(int r, int g, int b, float tolerance):xy(CvPoint()),decoder(MovementDecoder(tolerance)), lastPosition(cvPoint(-1,-1)),lastTolerant(LOST), lastIntolerant(LOST) { // Create the mask & initialize it to white (no color detected) mask = NULL; colour.rgb.r=r; colour.rgb.g=g; colour.rgb.b=b; // Get the hsv image IplImage* hsv = cvCreateImage(cvSize(10,10),IPL_DEPTH_8U,3); cvSet(hsv,cvScalar(b,g,r)); //cvCvtColor(image, hsv, CV_BGR2HSV); cvCvtColor(hsv, hsv, CV_BGR2Lab); // Get the selected pixel CvScalar pixel = cvGet2D(hsv, 5, 5); // Change the value of the tracked color with the color of the selected pixel colour.hsv.h = (int)pixel.val[0]; colour.hsv.s = (int)pixel.val[1]; colour.hsv.v = (int)pixel.val[2]; // Release the memory of the hsv image cvReleaseImage(&hsv); }
CvPoint functions::min_elements(vector<CvPoint> vec) { int x_min = INT32_MAX, y_min = INT32_MAX; for (int i = 0; i < vec.size(); i++) { if (vec[i].x < x_min) { x_min = vec[i].x; } if (vec[i].y < y_min) { y_min = vec[i].y; } } return CvPoint(x_min, y_min); }
CvPoint functions::max_elements(vector<CvPoint> vec) { int x_max = 0, y_max = 0; for (int i = 0; i < vec.size(); i++) { if (vec[i].x > x_max) { x_max = vec[i].x; } if (vec[i].y > y_max) { y_max = vec[i].y; } } return CvPoint(x_max, y_max); }
void draw() { double scale = this->scale == 0? 1.0 : this->scale; CvScalar colors[5] = { #if !defined CV_VERSION_EPOCH && (CV_VERSION_MAJOR >= 3) CvScalar(cvRound(color[0].r * 255), cvRound(color[0].g * 255), cvRound(color[0].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[1].r * 255), cvRound(color[1].g * 255), cvRound(color[1].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[2].r * 255), cvRound(color[2].g * 255), cvRound(color[2].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[3].r * 255), cvRound(color[3].g * 255), cvRound(color[3].b * 255), cvRound(alpha * 255)), CvScalar(cvRound(color[4].r * 255), cvRound(color[4].g * 255), cvRound(color[4].b * 255), cvRound(alpha * 255)), #else {{cvRound(color[0].r * 255), cvRound(color[0].g * 255), cvRound(color[0].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[1].r * 255), cvRound(color[1].g * 255), cvRound(color[1].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[2].r * 255), cvRound(color[2].g * 255), cvRound(color[2].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[3].r * 255), cvRound(color[3].g * 255), cvRound(color[3].b * 255), cvRound(alpha * 255)}}, {{cvRound(color[4].r * 255), cvRound(color[4].g * 255), cvRound(color[4].b * 255), cvRound(alpha * 255)}}, #endif }; for (int i = 0; i < (objects ? objects->total : 0); i++) { CvRect* r = (CvRect*) cvGetSeqElem(objects, i); CvPoint center; int thickness = stroke <= 0? CV_FILLED : cvRound(stroke * 100); int linetype = antialias? CV_AA : 8; center.x = cvRound((r->x + r->width * 0.5) / scale); center.y = cvRound((r->y + r->height * 0.5) / scale); switch (shape == 1.0? (rand() % 3) : cvRound(shape * 10)) { default: case 0: { int radius = cvRound((r->width + r->height) * 0.25 / scale); cvCircle(image, center, radius, colors[i % 5], thickness, linetype); break; } case 1: { #if !defined CV_VERSION_EPOCH && (CV_VERSION_MAJOR >= 3) CvBox2D box = CvBox2D(CvPoint2D32f(center.x, center.y), CvSize2D32f(r->width / scale, (r->height / scale) * 1.2), 90); #else CvBox2D box = {{center.x, center.y}, {r->width / scale, (r->height / scale) * 1.2}, 90}; #endif cvEllipseBox(image, box, colors[i % 5], thickness, linetype); break; } case 2: { #if !defined CV_VERSION_EPOCH && (CV_VERSION_MAJOR >= 3) CvPoint pt1 = CvPoint(r->x / scale, r->y / scale); CvPoint pt2 = CvPoint((r->x + r->width) / scale, (r->y + r->height) / scale); #else CvPoint pt1 = {r->x / scale, r->y / scale}; CvPoint pt2 = {(r->x + r->width) / scale, (r->y + r->height) / scale}; #endif cvRectangle(image, pt1, pt2, colors[i % 5], thickness, linetype); break; } } } }
int findStableMatches( CvSeq *seq, float minRad, float maxRad, CandidatePtrVector& kps, IplImage* bin ) { // Return value int retVal = -1; // Threshold Contour entries size int elements = seq->total; if( elements < 8 ) { return retVal; } // Gather statistics CvRect rect = cvBoundingRect( seq ); int high = ( rect.height < rect.width ? rect.width : rect.height ); int low = ( rect.height < rect.width ? rect.height : rect.width ); // If bounding box is very small simply return if( low < minRad*2 ) { return retVal; } // Allocate Contour array CvPoint *group_pos = (CvPoint*) malloc(elements * sizeof(CvPoint)); cvCvtSeqToArray(seq, group_pos, CV_WHOLE_SEQ); // Calculate arc and downsampling statistics double arc_length = cvArcLength( seq ); double arc_approx = arc_length / 10; double rect_approx = 12*(float)high / (float)low; double downsample = 2 * elements / (rect_approx + arc_approx); double ds_length = arc_length / 4; // Perform downsampling int maxSize = downsample * elements; int newSize = 0; CvPoint *dsed = (CvPoint*) malloc(maxSize * sizeof(CvPoint)); dsed[0] = CvPoint( group_pos[0] ); CvPoint last = CvPoint( dsed[0] ); newSize++; for( int i = 1; i < elements; i++ ) { double dist_so_far = dist_squared( group_pos[i], last ); if( dist_so_far > ds_length && newSize < maxSize ) { dsed[newSize] = CvPoint( group_pos[i] ); newSize++; last = CvPoint( group_pos[i] ); } } // Check to make sure reduced Contour size is sufficient [quickfix: todo revise above] if( newSize < 6 ) { free(group_pos); free(dsed); return -1; } // Fit Ellipse CvPoint2D32f* input = (CvPoint2D32f*)malloc(newSize*sizeof(CvPoint2D32f)); for( int i=0; i<newSize; i++ ) { input[i].x = dsed[i].x; input[i].y = dsed[i].y; } CvBox2D* box = (CvBox2D*)malloc(sizeof(CvBox2D)); cvFitEllipse( input, newSize, box ); // Threshold size float esize = PI*box->size.height*box->size.width/4.0f; if( esize < PI*maxRad*maxRad ) { // Add Candidate *kp = new Candidate; kp->angle = box->angle; kp->r = box->center.y; kp->c = box->center.x; kp->minor = box->size.width/2; kp->major = box->size.height/2; kp->magnitude = 0; kp->method = ADAPTIVE; kps.push_back( kp ); retVal = 0; } else { // Interest point too large retVal = 1; } // Deallocations free(box); free(input); free(group_pos); free(dsed); return retVal; }