Esempio n. 1
0
/////////////////////////////////////////////////////////
// processGrayImage
//
/////////////////////////////////////////////////////////
void pix_fiducialtrack :: processGrayImage(imageStruct &image)
{
  if(image.xsize!=m_width || image.ysize!=m_height)
    deinit_segmenter();

  m_width =image.xsize;
  m_height=image.ysize;

  if(!initialized){
    initialize_segmenter( &segmenter, m_width, m_height, treeidmap.max_adjacencies );
    initialized=true;
  }

  step_segmenter( &segmenter, image.data);
  int count = find_fiducialsX( fiducials, MAX_FIDUCIAL_COUNT,  
                               &fidtrackerx , 
                               &segmenter, 
                               m_width, m_height);

  int i;
  for(i=0;i< count;i++) {
    if(fiducials[i].id!=INVALID_FIDUCIAL_ID){
      SETFLOAT((m_outlist+0), (fiducials[i].id));         // id (as in treeidmap)
      SETFLOAT((m_outlist+1), (fiducials[i].x/m_width));  // x (normalized)
      SETFLOAT((m_outlist+2), (fiducials[i].y/m_height)); // y (normalized)
      SETFLOAT((m_outlist+3), (fiducials[i].angle));      // phi (radiant)
      outlet_list(m_infoOut, gensym("list"), 4, m_outlist);
    }
  }
}
Esempio n. 2
0
void FidtrackFinder::process(unsigned char *src, unsigned char *dest, SDL_Surface *display) {

/*
	#ifdef WIN32
		long start_time = GetTickCount();
	#else
		struct timeval tv;
		struct timezone tz;
		gettimeofday(&tv,&tz);
		long start_time = (tv.tv_sec*1000000)+(tv.tv_usec);
	#endif
*/

	// segmentation
	step_segmenter( &segmenter, dest );
	// fiducial recognition
	int fid_count = find_fiducialsX( fiducials, MAX_FIDUCIAL_COUNT,  &fidtrackerx, &segmenter, width, height);

	float total_leaf_size = 0.0f;
	float total_fiducial_size = 0.0f;
	int valid_fiducial_count = 0;

	// process found symbols
	for(int i=0;i< fid_count;i++) {
		if ( fiducials[i].id >=0 ) {
			valid_fiducial_count ++;
			total_leaf_size += fiducials[i].leaf_size;
			total_fiducial_size += fiducials[i].root_size;
		}
		
		FiducialObject *existing_fiducial = NULL;
		// update objects we had in the last frame
		// also check if we have an ID/position conflict
		// or correct an INVALID_FIDUCIAL_ID if we had an ID in the last frame
		for (std::list<FiducialObject>::iterator fiducial = fiducialList.begin(); fiducial!=fiducialList.end(); fiducial++) {
	
			float distance = fiducial->distance(fiducials[i].x,fiducials[i].y);
	
			if (fiducials[i].id==fiducial->fiducial_id)  {
				// find and match a fiducial we had last frame already ...
				if(!existing_fiducial) {
					existing_fiducial = &(*fiducial);

					for (int j=0;j<fid_count;j++) {
						if ( (i!=j) && (fiducials[j].id==fiducial->fiducial_id) && (fiducial->distance(fiducials[j].x,fiducials[j].y)<distance)) {
							//check if there is another fiducial with the same id closer
							existing_fiducial = NULL;
							break;
						}
					}	
										
					if (existing_fiducial!=NULL) {
					for (std::list<FiducialObject>::iterator test = fiducialList.begin(); test!=fiducialList.end(); test++) {
						FiducialObject *test_fiducial = &(*test);
						if ( (test_fiducial!=existing_fiducial) && (test_fiducial->fiducial_id==existing_fiducial->fiducial_id) && (test_fiducial->distance(fiducials[i].x,fiducials[i].y)<distance)) {
							//check if there is another fiducial with the same id closer
							existing_fiducial = NULL;
							break;
						}
					}}
				} /*else if (distance<existing_fiducial->distance(fiducials[i].x,fiducials[i].y)) {
						existing_fiducial = &(*fiducial);
					// is this still necessary?
				} */

			} else if ((distance<average_fiducial_size/1.2) && (abs(fiducials[i].node_count-fiducial->node_count)<=FUZZY_NODE_RANGE)) {
				// do we have a different ID at the same place?
				// this should correct wrong or invalid fiducial IDs
				// assuming that between two frames
				// there can't be a rapid exchange of two symbols
				// at the same place
				
				for (int j=0;j<fid_count;j++) {
					if ( (i!=j) && (fiducial->distance(fiducials[j].x,fiducials[j].y)<distance)) goto fiducialList_loop_end;
				}	
				
				if (fiducials[i].id==INVALID_FIDUCIAL_ID) {
					//printf("corrected invalid ID to %d (%ld)\n", fiducial->fiducial_id,fiducial->session_id);
					
					//two pixel threshold since missing/added leaf nodes result in a slightly different position
					float dx = abs(fiducial->getX() - fiducials[i].x);
					float dy = abs(fiducial->getY() - fiducials[i].y);
					if ((dx<2.0f) && (dy<2.0f)) {
						fiducials[i].x = (short int)fiducial->getX();
						fiducials[i].y = (short int)fiducial->getY();
					}
					
					fiducials[i].angle=fiducial->getAngle();
					fiducials[i].id=fiducial->fiducial_id;
					fiducial->state = FIDUCIAL_INVALID;
					drawObject(fiducials[i].id,(int)(fiducials[i].x),(int)(fiducials[i].y),display,0);
				} else /*if (fiducials[i].id!=fiducial->fiducial_id)*/ {

					if (!fiducial->checkIdConflict(session_id,fiducials[i].id)) {
						//printf("corrected wrong ID from %d to %d (%ld)\n", fiducials[i].id,fiducial->fiducial_id,fiducial->session_id);
						fiducials[i].id=fiducial->fiducial_id;
					} else {
						session_id++;
					}
				}
				
				existing_fiducial = &(*fiducial);
				break;
			}
			
			fiducialList_loop_end:;
		}
		
		if  (existing_fiducial!=NULL) {
			// just update the fiducial from last frame ...
			existing_fiducial->update(fiducials[i].x,fiducials[i].y,fiducials[i].angle,fiducials[i].root_size,fiducials[i].leaf_size);
			if(existing_fiducial->state!=FIDUCIAL_INVALID) drawObject(existing_fiducial->fiducial_id,(int)(existing_fiducial->getX()),(int)(existing_fiducial->getY()),display,1);
		} else if  (fiducials[i].id!=INVALID_FIDUCIAL_ID) {
			// add the newly found object
			session_id++;
			FiducialObject addFiducial(session_id, fiducials[i].id, width, height,fiducials[i].root_colour,fiducials[i].node_count);
			addFiducial.update(fiducials[i].x,fiducials[i].y,fiducials[i].angle,fiducials[i].root_size,fiducials[i].leaf_size);
			drawObject(fiducials[i].id,(int)(fiducials[i].x),(int)(fiducials[i].y),display,1);
			fiducialList.push_back(addFiducial);
#ifndef DISABLE_MIDISERVER
			if (midi_server!=NULL) midi_server->sendAddMessage(fiducials[i].id);
#endif
			if (msg_listener) {
				std::stringstream add_message;
				add_message << "add obj " << session_id << " " << fiducials[i].id;
				msg_listener->setMessage(add_message.str());
			}
		}
			
		//else drawObject(fiducials[i].id,(int)(fiducials[i].x),(int)(fiducials[i].y),display,0);

	}

	if (valid_fiducial_count>0) {
		average_leaf_size = (average_leaf_size + total_leaf_size/(double)valid_fiducial_count)/2;
		average_fiducial_size = (average_fiducial_size +  total_fiducial_size/(double)valid_fiducial_count)/2;
	}
	//std::cout << "leaf size: " << average_leaf_size << std::endl;
	//std::cout << "fiducial size: " << average_fiducial_size << std::endl;
	//std::cout << "finger size: " << average_finger_size << std::endl;

	float min_object_size = average_fiducial_size - average_fiducial_size/4.0f;
	float max_object_size = average_fiducial_size + average_fiducial_size/4.0f;
	
	float min_finger_size = average_finger_size - average_finger_size/1.75f;
	float max_finger_size = average_finger_size + average_finger_size/1.75f;
	
	// plain object tracking
	int min_region_size = min_finger_size;
	int max_region_size = max_object_size;
	if ((average_finger_size==0) || (min_region_size>min_object_size)) min_region_size = min_object_size;
	int reg_count = find_regionsX( regions, MAX_FIDUCIAL_COUNT, &fidtrackerx, &segmenter, width, height, min_region_size, max_region_size);
	//std::cout << reg_count << std::endl;

	//if (average_fiducial_size>width/4) goto send_messages;
	for(int j=0;j< reg_count;j++) {

		//printf("region: %d %d\n", regions[j].x, regions[j].y);
		//printf("region: %d %d\n", regions[j].width, regions[j].height);

/*		
			//reactable specific temporary hack
			//check if object is within the inner circle
		float dx =  width/2 - regions[j].x;
		float dy = height/2 - regions[j].y;
		float distance = sqrt(dx*dx+dy*dy);
		if (distance>(height/2-height/10)) continue;
		
*/
		int diff = abs(regions[j].width - regions[j].height);
		int max_diff = regions[j].width;
		if (regions[j].height > regions[j].width) max_diff = regions[j].height/2.0f;
				
		// plain objects
		if ((regions[j].width>min_object_size) && (regions[j].width<max_object_size) &&
			(regions[j].height>min_object_size) && (regions[j].height<max_object_size) && diff < max_diff) {

			//printf("region: %d %d\n", regions[j].width, regions[j].height);
			FiducialObject *existing_fiducial = NULL;
			for (std::list<FiducialObject>::iterator fiducial = fiducialList.begin(); fiducial!=fiducialList.end(); fiducial++) {
				float distance = fiducial->distance(regions[j].x,regions[j].y);
				if ((distance<average_fiducial_size/1.5f) && (fiducial->root_colour==regions[j].colour)) {
					existing_fiducial = &(*fiducial);
	
					// check if the fiducial was already found anyway
					for (int i=0;i<fid_count;i++) {
						float dx = fiducials[i].x - regions[j].x;
						float dy = fiducials[i].y - regions[j].y;
						distance = sqrt(dx*dx+dy*dy);
						if ( distance<average_fiducial_size/1.5f) {
							existing_fiducial->setBlobOffset(dx,dy);
							existing_fiducial = NULL;
							break;
						}
					}
					if (existing_fiducial != NULL) break;
				}
			}
			if (existing_fiducial!=NULL) {

				FloatPoint offset = existing_fiducial->getBlobOffset();
				float xpos = regions[j].x + offset.x;
				float ypos = regions[j].y + offset.y;
				float angle = existing_fiducial->getAngle();

				//two pixel threshold since root node blobs do not provide a precise position
				float dx = abs(existing_fiducial->getX() - xpos);
				float dy = abs(existing_fiducial->getY() - ypos);
				if ((dx<2.0f) && (dy<2.0f)) {
					xpos = existing_fiducial->getX();
					ypos = existing_fiducial->getY();
				}
				
				existing_fiducial->update(xpos,ypos,angle,(regions[j].width+regions[j].height)/2,0);
				//printf("region: %d %d\n", regions[j].width, regions[j].height);
				//printf("recovered plain fiducial %d (%ld)\n", existing_fiducial->fiducial_id,existing_fiducial->session_id);
				existing_fiducial->state = FIDUCIAL_REGION;
				drawObject(existing_fiducial->fiducial_id,xpos,ypos,display,2);
			} //else goto plain_analysis;
						
		// plain fingers
		} else if (detect_finger && (regions[j].colour==255) && (regions[j].width>min_finger_size) && (regions[j].width<max_finger_size) && 
			(regions[j].height>min_finger_size) && (regions[j].height<max_finger_size) && diff < max_diff) {

			//check first if the finger is valid
			//printf("candidate: %d %d\n", regions[j].width, regions[j].height);
			int finger_match = check_finger(&regions[j],dest,(unsigned char*)(display->pixels));
			if(finger_match<0) continue;//goto plain_analysis;
			//printf("finger: %d %d\n", regions[j].width, regions[j].height);

			FingerObject *existing_finger = NULL;
			float closest = width;

			// ignore fingers within existing fiducials
			for (std::list<FiducialObject>::iterator fiducial = fiducialList.begin(); fiducial!=fiducialList.end(); fiducial++) {
				if (fiducial->distance(regions[j].x, regions[j].y)<fiducial->root_size/2) goto region_loop_end;
			}
			
			// attach to existing fingers in the list
			for (std::list<FingerObject>::iterator finger = fingerList.begin(); finger!=fingerList.end(); finger++) {
		
				float distance = finger->distance(regions[j].x,regions[j].y);
				if ((distance<average_finger_size*2) && (distance<closest)){
					existing_finger = &(*finger);
					closest = distance;
					
					//is there another finger closer than that?
					if (distance>average_finger_size/2) {
					for(int k=0;k< reg_count;k++) {
						if(j==k) continue;
						 if ((regions[k].width>min_finger_size) && (regions[k].width<max_finger_size) && 
							(regions[k].height>min_finger_size) && (regions[k].height<max_finger_size) && diff < max_diff) {
							
							int dx = abs(regions[k].x - regions[j].x);
							int dy = abs(regions[k].y - regions[j].y);
							float dist = sqrt((float)(dx*dx+dy*dy));
							if (dist<=distance) { existing_finger=NULL; closest=dist; break;  }
						}
					}}
					
					if (existing_finger!=NULL) {
						for (std::list<FingerObject>::iterator test = fingerList.begin(); test!=fingerList.end(); test++) {
							FingerObject *test_finger = &(*test);
							if ( (test_finger!=existing_finger) && (test_finger->distance(regions[j].x,regions[j].y)<distance)) {
								//check if there is another fiducial with the same id closer
								existing_finger = NULL;
								break;
							}
						}}
					

				}
			}

			// update or add the finger
			if  (existing_finger!=NULL) {			
				existing_finger->update(regions[j].x,regions[j].y,regions[j].area);
			} else if (finger_match==1) {
				// add the newly found cursor
				FingerObject addFinger(width, height);				
				addFinger.update(regions[j].x,regions[j].y,regions[j].area);
				fingerList.push_back(addFinger);
			} else continue; //goto plain_analysis;
	
			drawObject(FINGER_ID,(int)(regions[j].x),(int)(regions[j].y),display,1);
			region_loop_end:;
		} /*else if (	(regions[j].width>average_leaf_size*2) && (regions[j].height>average_leaf_size*2)) {
			plain_analysis:;
			//do the plain object analysis larger than twice the leaf size.
	
			bool analyse = true;
			// check if object is within any found fiducial
			for (std::list<FiducialObject>::iterator fiducial = fiducialList.begin(); fiducial!=fiducialList.end(); fiducial++) {
				float distance = fiducial->distance(regions[j].x,regions[j].y);
				if (distance<average_fiducial_size/2) { analyse = false; break; }
			}
	
			if (analyse) obj_analyzer->process(&regions[j],src, dest, display);	

		}*/

	}
	
	
	if (tuio_server!=NULL) {
		sendTuioMessages();
		if (detect_finger) sendCursorMessages();
	} else {
#ifndef DISABLE_MIDISERVER    
        if (midi_server!=NULL) sendMidiMessages();
#endif
    } 
	
	if (show_grid) drawGrid(src,dest,display);
	if (show_settings) drawGUI(display);
	//printStatistics(start_time);
}
void moFiducialTrackerModule::applyFilter(IplImage *src) {
	fiducials_data_t *fids = static_cast<fiducials_data_t*>(this->internal);
	moDataGenericContainer *fiducial;
	FiducialX *fdx;
	int fid_count, valid_fiducials = 0;
	bool do_image = this->output->getObserverCount() > 0 ? true : false;
	CvSize size = cvGetSize(src);

	CvFont font, font2;
	cvInitFont(&font, CV_FONT_HERSHEY_DUPLEX, 1.0, 1.0, 0, 2);
	cvInitFont(&font2, CV_FONT_HERSHEY_PLAIN, 1.0, 1.0, 0, 1);

	assert( src != NULL );
	assert( fids != NULL );
	assert( src->imageData != NULL );

	if ( src->nChannels != 1 ) {
		this->setError("FiducialTracker input image must be a single channel binary image.");
		this->stop();
		return;
	}


	// prepare image if we have listener on output
	if ( do_image )
		cvSet(this->output_buffer, CV_RGB(0, 0, 0));

	// libfidtrack
	step_segmenter(&fids->segmenter, (const unsigned char*)src->imageData);
	fid_count = find_fiducialsX(fids->fiducials, MAX_FIDUCIALS,
			&fids->fidtrackerx, &fids->segmenter, src->width, src->height);

	// prepare to refill fiducials
	this->clearFiducials();

	for ( int i = 0; i < fid_count; i++ ) {
		fdx = &fids->fiducials[i];

		// invalid id (INVALID_FIDUCIAL_ID)
		if ( fdx->id < 0 )
			continue;

		// got a valid fiducial ! process...
		valid_fiducials++;

		LOGM(MO_DEBUG, "fid:" << i << " id=" << fdx->id << " pos=" \
			<< fdx->x << "," << fdx->y << " angle=" << fdx->angle);

		fiducial = new moDataGenericContainer();
		fiducial->properties["implements"] = new moProperty("fiducial,pos,tracked");
		fiducial->properties["fiducial_id"] = new moProperty(fdx->id);
		fiducial->properties["blob_id"] = new moProperty(fdx->id);
		fiducial->properties["x"] = new moProperty(fdx->x / size.width);
		fiducial->properties["y"] = new moProperty(fdx->y / size.height);
		fiducial->properties["angle"] = new moProperty(fdx->angle);
		fiducial->properties["leaf_size"] = new moProperty(fdx->leaf_size);
		fiducial->properties["root_size"] = new moProperty(fdx->root_size);
		this->fiducials.push_back(fiducial);

		// draw on output image
		if ( do_image ) {
			std::ostringstream oss;
			oss << fdx->id;
			cvPutText(this->output_buffer, oss.str().c_str(),
				cvPoint(fdx->x, fdx->y - 20), &font, cvScalar(20, 255, 20));

			oss.str("");
			oss << "angle:" << int(fdx->angle * 180 / 3.14159265);
			cvPutText(this->output_buffer, oss.str().c_str(),
				cvPoint(fdx->x - 30, fdx->y), &font2, cvScalar(20, 255, 20));

			oss.str("");
			oss << "l/r:" << fdx->leaf_size << "/" << fdx->root_size;
			cvPutText(this->output_buffer, oss.str().c_str(),
				cvPoint(fdx->x - 50, fdx->y + 20), &font2, cvScalar(20, 255, 20));

		}
	}

	LOGM(MO_DEBUG, "-> Found " << valid_fiducials << " fiducials");
	this->output_data->push(&this->fiducials);
}