void RobotDemo::camera_test()
{
#if CAMERA
	image = camera->GetImage();

	cout << image << endl;
	delete image;
#endif
}
Beispiel #2
0
	bool tracking (bool use_alternate_score) //camera tracking function
	{
		//takes one camera frame and turns towards tallest target
		//returns true if target is within deadzone, returns false otherwise
		Threshold tapeThreshold(0, 255, 0, 90, 220, 255); //red hsl as of 20110303, this is the hue, saturation and luminosicity ranges that we want
		BinaryImage *tapePixels;//
		Image *convexHull;
		BinaryImage *convexHullBinaryImage;
		ParticleAnalysisReport par;//analyzed blob (pre convex hull)
		ParticleAnalysisReport convexpar;// ONE filled-in blob
		vector<ParticleAnalysisReport>* pars;//where many analyzed blob goes (pre)
		vector<ParticleAnalysisReport>* convexpars; //where MANY  filled-in blobs go
		
		bool foundAnything = false;	
		double best_score = 120;
		double best_speed;
		double particle_score;
		
		ImageType t;
		int bs;
		img = cam->GetImage(); 
		printf("cam->GetImage() returned frame %d x %d\n",img->GetWidth(),img->GetHeight());
		tapePixels = img->ThresholdHSL(tapeThreshold);
		imaqGetBorderSize(tapePixels->GetImaqImage(),&bs);
		imaqGetImageType(tapePixels->GetImaqImage(),&t);
		convexHull = imaqCreateImage(t,bs);
		convexHullBinaryImage = new BinaryImageWrapper(convexHull);
		convexHullBinaryImage->GetOrderedParticleAnalysisReports();
		//tapePixels = img->ThresholdHSL(int 0,int 50,int -100,int -50,int luminenceLow,int luminanceHigh);
		pars = tapePixels->GetOrderedParticleAnalysisReports();
		imaqConvexHull(convexHull,tapePixels->GetImaqImage(),true);
		convexHullBinaryImage = new BinaryImageWrapper(convexHull);
		convexpars = convexHullBinaryImage->GetOrderedParticleAnalysisReports();
		//imaqGetParticleInfo()
		
		//convexpars = convexHull->GetOrderedParticleAnalysisReports();
		for (int i=0;i < convexHullBinaryImage->GetNumberParticles();i++)
		{
			//par = (*pars)[0];
			//convexpar = (*convexpars)[i];
			convexpar = convexHullBinaryImage->GetParticleAnalysisReport(i);
			par = tapePixels->GetParticleAnalysisReport(i);
			

			if((convexpar.boundingRect.width < 10) || (convexpar.boundingRect.height < 7))
			{									
				continue;
		    }
//				printf("%d  par:%f convex:%f particle area\n",i,par.particleArea,convexpar.particleArea);
			
			if ((par.particleArea/convexpar.particleArea > 0.4))
			{
				printf("%d skip max fillness ratio\n",i);
				continue;
			}
			if ((par.particleArea/convexpar.particleArea < 0.10))
			{
				printf("%d skip min fillness ratio\n",i);
				continue;
			}
			
			if((double)(convexpar.boundingRect.width)/(double)(convexpar.boundingRect.height)>1.8)
			{
				printf("%d skip max aspect ratio\n",i);
				continue;
			}
			
			if((double)(convexpar.boundingRect.width)/(double)(convexpar.boundingRect.height)<.8)
			{
				printf("%d skip min aspect ratio\n",i);
				continue;
			}
			
			
						
			//printf("%f center of mass x\n",par.center_mass_x_normalized);
			//printf("%f center of mass y\n",par.center_mass_y_normalized);
			distanceInInches = (18.0*179.3)/(convexpar.boundingRect.height);
			double pwidth = convexpar.boundingRect.width;
			double mwidth = ((double)convexpar.boundingRect.left+(double)convexpar.boundingRect.width*0.5);
			double angle = ((180.0/3.14159)*acos     (pwidth * distanceInInches/179.3/24.0)  );
			if(angle != angle) angle = 0.0; // if angle is NaN, set to zero
			printf("%f distance in inches\n",distanceInInches);
			//printf("%f angle\n",(180.0/3.14159)*acos     (pwidth * distanceInInches/415.0/24.0)  );
			printf("%d BBctrX:%f CMX:%f\n", i, (double)convexpar.boundingRect.left + (double)convexpar.boundingRect.width*0.5, (double)par.center_mass_x);		
			//printf("%f angle2\n",(((pwidth * distanceInInches)/415.0)/24.0));
			//printf("%f center of mass x\n",par.center_mass_x_normalized);
			printf("%d %f %f center of mass x\n",i,convexpar.center_mass_x_normalized,par.center_mass_x_normalized);
			printf("%d %f %f center of mass y\n",i,convexpar.center_mass_y_normalized,par.center_mass_y_normalized);
			printf("%d %f %f rectangle score\n",i,(convexpar.particleArea)/((convexpar.boundingRect.width)*(convexpar.boundingRect.height))*(100),(par.particleArea)/((par.boundingRect.width)*(par.boundingRect.height))*(100));
			printf("%d %f fillness ratio\n",i,par.particleArea/convexpar.particleArea);
			printf("%d %d %d width and height\n",i,(convexpar.boundingRect.width),(convexpar.boundingRect.height));
			printf("%d %f aspect ratio\n",i,((convexpar.boundingRect.width)/(double)(convexpar.boundingRect.height)));
			

			if ((double)(par.center_mass_x)>mwidth)
				{
				 angle=angle*(-1.0);
				}
			 printf("%f true angle\n",angle);
			 //Wait(1.0);
			 
			 double aiming_target_offset = 0.0; 
			 //aiming_target_offset = pwidth * angle * (-0.5 / 45.0); numbers are iffy -> NaN
			 
			 
			 double speed = trackingFeedbackFunction(mwidth + aiming_target_offset - 80.0);
			 printf("%f aiming_target_offset due to %f degree angle\n", aiming_target_offset, angle);
			 printf("%f x offset \n",mwidth + aiming_target_offset - 80.0);
			 printf("%f speed \n", speed);
			foundAnything = true;
			
			if (use_alternate_score == false){
				particle_score = convexpar.center_mass_y;
			}
			else{
				particle_score = 2.0*fabs((double)convexpar.center_mass_y - 60.0) + fabs((double)convexpar.center_mass_x - 80.0);
			}
			
			// keep track of the *lowest* score
			if (best_score > particle_score)
			{
				best_score = particle_score;
				best_speed = speed;
			}
		}
		
		if(foundAnything == false) {
			myRobot->TankDrive(0.0, 0.0);	
		}
		else
		{
			myRobot->TankDrive(-best_speed,best_speed);
		}
		
		 
	    delete img;
		delete tapePixels;
		delete pars;				
		delete convexHullBinaryImage;
		delete convexpars;
		//imaqDispose(convexHull);
		
		if (foundAnything && best_speed == 0.0){
			return true;
		}
		
		else
		{
			return false;
		}
	}
	Vision_Out Run(Vision_In in)
	{
		Vision_Out out;

		//read file in from disk. For this example to run you need to copy image.jpg from the SampleImages folder to the
		//directory shown below using FTP or SFTP: http://wpilib.screenstepslive.com/s/4485/m/24166/l/282299-roborio-ftp
		//imaqError = imaqReadFile(frame, "//home//lvuser//SampleImages//image.jpg", NULL, NULL);

		imaqError = camera->GetImage(frame);

		//Update threshold values from SmartDashboard. For performance reasons it is recommended to remove this after calibration is finished.
		/*
					RING_HUE_RANGE.minValue = SmartDashboard::GetNumber("Tote hue min", RING_HUE_RANGE.minValue);
					RING_HUE_RANGE.maxValue = SmartDashboard::GetNumber("Tote hue max", RING_HUE_RANGE.maxValue);
					RING_SAT_RANGE.minValue = SmartDashboard::GetNumber("Tote sat min", RING_SAT_RANGE.minValue);
					RING_SAT_RANGE.maxValue = SmartDashboard::GetNumber("Tote sat max", RING_SAT_RANGE.maxValue);
					RING_VAL_RANGE.minValue = SmartDashboard::GetNumber("Tote val min", RING_VAL_RANGE.minValue);
					RING_VAL_RANGE.maxValue = SmartDashboard::GetNumber("Tote val max", RING_VAL_RANGE.maxValue);
		 */

		if(in.shouldProcess)
		{
			//Threshold the image looking for ring light color
			imaqError = imaqColorThreshold(binaryFrame, frame, 255, IMAQ_HSV, &RING_HUE_RANGE, &RING_SAT_RANGE, &RING_VAL_RANGE);

			//Send particle count to dashboard
			int numParticles = 0;
			imaqError = imaqCountParticles(binaryFrame, 1, &numParticles);
			SmartDashboard::PutNumber("Masked particles", numParticles);

			//Send masked image to dashboard to assist in tweaking mask.
			SendToDashboard(binaryFrame, imaqError);

			//filter out small particles
			float areaMin = SmartDashboard::GetNumber("Area min %", AREA_MINIMUM);
			criteria[0] = {IMAQ_MT_AREA_BY_IMAGE_AREA, areaMin, 100, false, false};
			imaqError = imaqParticleFilter4(binaryFrame, binaryFrame, criteria, 1, &filterOptions, NULL, NULL);

			//Send particle count after filtering to dashboard
			imaqError = imaqCountParticles(binaryFrame, 1, &numParticles);
			SmartDashboard::PutNumber("Filtered particles", numParticles);

			if(numParticles > 0)
			{
				//Measure particles and sort by particle size
				std::vector<ParticleReport> particles;
				for(int particleIndex = 0; particleIndex < numParticles; particleIndex++)
				{
					ParticleReport par;
					imaqMeasureParticle(binaryFrame, particleIndex, 0, IMAQ_MT_AREA_BY_IMAGE_AREA, &(par.PercentAreaToImageArea));
					imaqMeasureParticle(binaryFrame, particleIndex, 0, IMAQ_MT_AREA, &(par.Area));
					imaqMeasureParticle(binaryFrame, particleIndex, 0, IMAQ_MT_BOUNDING_RECT_TOP, &(par.BoundingRectTop));
					imaqMeasureParticle(binaryFrame, particleIndex, 0, IMAQ_MT_BOUNDING_RECT_LEFT, &(par.BoundingRectLeft));
					imaqMeasureParticle(binaryFrame, particleIndex, 0, IMAQ_MT_BOUNDING_RECT_BOTTOM, &(par.BoundingRectBottom));
					imaqMeasureParticle(binaryFrame, particleIndex, 0, IMAQ_MT_BOUNDING_RECT_RIGHT, &(par.BoundingRectRight));
					particles.push_back(par);
				}
				sort(particles.begin(), particles.end(), CompareParticleSizes);

				//This example only scores the largest particle. Extending to score all particles and choosing the desired one is left as an exercise
				//for the reader. Note that this scores and reports information about a single particle (single L shaped target). To get accurate information
				//about the location of the tote (not just the distance) you will need to correlate two adjacent targets in order to find the true center of the tote.
				scores.Aspect = AspectScore(particles.at(0));
				SmartDashboard::PutNumber("Aspect", scores.Aspect);
				scores.Area = AreaScore(particles.at(0));
				SmartDashboard::PutNumber("Area", scores.Area);
				bool isTarget = scores.Area > SCORE_MIN && scores.Aspect > SCORE_MIN;

				//Send distance and tote status to dashboard. The bounding rect, particularly the horizontal center (left - right) may be useful for rotating/driving towards a tote
				SmartDashboard::PutBoolean("IsTarget", isTarget);
				double distance = computeDistance(binaryFrame, particles.at(0));
				SmartDashboard::PutNumber("Distance", computeDistance(binaryFrame, particles.at(0)));

				out.returnDistanceToTote = distance;
				out.returnIsTote = true;
				return out;
			}
			else
			{
				out.returnIsTote = false;
				SmartDashboard::PutBoolean("IsTarget", false);
			}
		}
		return out;
	}