Ejemplo n.º 1
0
/**
* @brief Applies a threshold to the Red, Green, and Blue values of a RGB image
* or the Hue,
* Saturation, Luminance values for a HSL image.
* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL.
* This simpler version filters based on a hue range in the HSL mode.
*
* @param dest The destination image. This must be a IMAQ_IMAGE_U8 image.
* @param source The image to threshold
* @param mode The color space to perform the threshold in. valid values are:
* IMAQ_RGB, IMAQ_HSL.
* @param plane1Range The selection range for the first plane of the image. Set
* this parameter to nullptr to use a selection range from 0 to 255.
* @param plane2Range The selection range for the second plane of the image. Set
* this parameter to nullptr to use a selection range from 0 to 255.
* @param plane3Range The selection range for the third plane of the image. Set
* this parameter to nullptr to use a selection range from 0 to 255.
*
* @return On success: 1. On failure: 0. To get extended error information, call
* GetLastError().
* */
int frcColorThreshold(Image* dest, const Image* source, ColorMode mode,
                      const Range* plane1Range, const Range* plane2Range,
                      const Range* plane3Range) {
  int replaceValue = 1;
  return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range,
                            plane2Range, plane3Range);
}
////////////////////////////////////////////////////////////////////////////////
//
// Function Name: IVA_CLRThreshold
//
// Description  : Thresholds a color image.
//
// Parameters   : image      -  Input image
//                min1       -  Minimum range for the first plane
//                max1       -  Maximum range for the first plane
//                min2       -  Minimum range for the second plane
//                max2       -  Maximum range for the second plane
//                min3       -  Minimum range for the third plane
//                max3       -  Maximum range for the third plane
//                colorMode  -  Color space in which to perform the threshold
//
// Return Value : success
//
////////////////////////////////////////////////////////////////////////////////
static int IVA_CLRThreshold(Image* image, int min1, int max1, int min2, int max2, int min3, int max3, int colorMode)
{
    int success = 1;
    Image* thresholdImage;
    Range plane1Range;
    Range plane2Range;
    Range plane3Range;


    //-------------------------------------------------------------------//
    //                          Color Threshold                          //
    //-------------------------------------------------------------------//

    // Creates an 8 bit image for the thresholded image.
    VisionErrChk(thresholdImage = imaqCreateImage(IMAQ_IMAGE_U8, 7));

    // Set the threshold range for the 3 planes.
    plane1Range.minValue = min1;
    plane1Range.maxValue = max1;
    plane2Range.minValue = min2;
    plane2Range.maxValue = max2;
    plane3Range.minValue = min3;
    plane3Range.maxValue = max3;

    // Thresholds the color image.
    VisionErrChk(imaqColorThreshold(thresholdImage, image, 1, colorMode, &plane1Range, &plane2Range, &plane3Range));

    // Copies the threshold image in the souce image.
    VisionErrChk(imaqDuplicate(image, thresholdImage));

Error:
    imaqDispose(thresholdImage);

    return success;
}
Ejemplo n.º 3
0
/**
 * Perform a threshold operation on a ColorImage.
 *
 * Perform a threshold operation on a ColorImage using the ColorMode supplied
 * as a parameter.
 *
 * @param colorMode The type of colorspace this operation should be performed in
 * @return a pointer to a binary image
 */
BinaryImage* ColorImage::ComputeThreshold(ColorMode colorMode, int low1,
                                          int high1, int low2, int high2,
                                          int low3, int high3) {
  auto result = new BinaryImage();
  Range range1 = {low1, high1}, range2 = {low2, high2}, range3 = {low3, high3};

  int success = imaqColorThreshold(result->GetImaqImage(), m_imaqImage, 1,
                                   colorMode, &range1, &range2, &range3);
  wpi_setImaqErrorWithContext(success, "ImaqThreshold error");
  return result;
}
Ejemplo n.º 4
0
int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange, int minSaturation)
{
	// assume HSL mode
	ColorMode mode = IMAQ_HSL;  
	// Set saturation 100 - 255
	Range satRange;  satRange.minValue = minSaturation; satRange.maxValue = 255;
	// Set luminance 100 - 255
	Range lumRange;  lumRange.minValue = 100; lumRange.maxValue = 255;
	// Replace pixels with 1 if pass threshold filter
	int replaceValue = 1;
	return imaqColorThreshold(dest, source, replaceValue, mode, hueRange, &satRange, &lumRange);
}
Ejemplo n.º 5
0
	void Autonomous() override {
		while (IsAutonomous() && IsEnabled())
		{
			//read file in from disk. For this example to run you need to copy image20.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, "//NewDir//image2.jpg", NULL, NULL);

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

			//Threshold the image looking for yellow (tote color)
			imaqError = imaqColorThreshold(binaryFrame, frame, 255, IMAQ_HSV, &TOTE_HUE_RANGE, &TOTE_SAT_RANGE, &TOTE_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_CONVEX_HULL_AREA, &(par.ConvexHullArea));
					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 the long and short side scores expect a single tote and will not work for a stack of 2 or more totes.
				//Modification of the code to accommodate 2 or more stacked totes is left as an exercise for the reader.
				scores.Trapezoid = TrapezoidScore(particles.at(0));
				SmartDashboard::PutNumber("Trapezoid", scores.Trapezoid);
				scores.LongAspect = LongSideScore(particles.at(0));
				SmartDashboard::PutNumber("Long Aspect", scores.LongAspect);
				scores.ShortAspect = ShortSideScore(particles.at(0));
				SmartDashboard::PutNumber("Short Aspect", scores.ShortAspect);
				scores.AreaToConvexHullArea = ConvexHullAreaScore(particles.at(0));
				SmartDashboard::PutNumber("Convex Hull Area", scores.AreaToConvexHullArea);
				bool isTote = scores.Trapezoid > SCORE_MIN && (scores.LongAspect > SCORE_MIN || scores.ShortAspect > SCORE_MIN) && scores.AreaToConvexHullArea > SCORE_MIN;
				bool isLong = scores.LongAspect > scores.ShortAspect;

				//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("IsTote", isTote);
				SmartDashboard::PutNumber("Distance", computeDistance(binaryFrame, particles.at(0), isLong));
			} else {
				SmartDashboard::PutBoolean("IsTote", false);
			}

			Wait(0.005);				// wait for a motor update time
		}
	}
Ejemplo n.º 6
0
	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;
	}
Ejemplo n.º 7
0
void Camera::GetInfo() {

	Image* binFrame;

	binFrame = imaqCreateImage(IMAQ_IMAGE_U8, 0);

	Range Hue = {hueMin, hueMax};
	Range Sat = {satMin, satMax};
	Range Val = {valMin, valMax};

	ParticleFilterCriteria2 criteria[1];

	//ParticleFilterOptions2 filterOptions = {0, 0, 1, 1};


	criteria[0] = {IMAQ_MT_AREA, 0, (float) aireMin, false, true};


	int nbParticles(0);

	IMAQdxGrab(session, frame, true, NULL);
	imaqScale(frame, frame, 2, 2, ScalingMode::IMAQ_SCALE_SMALLER, IMAQ_NO_RECT);
	imaqColorThreshold(binFrame, frame, 255, IMAQ_HSV, &Hue, &Sat, &Val);
	imaqMorphology(binFrame, binFrame, IMAQ_DILATE, NULL);

	//imaqParticleFilter4(binFrame, binFrame, &criteria[0], 1, &filterOptions, NULL, &nbParticles);

	imaqCountParticles(binFrame, 0, &nbParticles);


	CameraServer::GetInstance()->SetImage(binFrame);

	int indexMax(0);
	double aireMax(0);

	if(nbParticles > 0) {

		for(int particleIndex = 0; particleIndex < nbParticles; particleIndex++){

			double aire (0);
			imaqMeasureParticle(binFrame, particleIndex, 0, IMAQ_MT_AREA, &aire);

			if (aire > aireMax){
				aireMax = aire;
				indexMax = particleIndex;
			}
		}


		double hypothenuse(0);

		int hauteurImage(0);
		int largeurImage(0);

		double centreX(0);
		double centreY(0);
		double angleX(0);
		double angleY(0);
		double offset(0);


		imaqMeasureParticle(binFrame, indexMax, 0, IMAQ_MT_CENTER_OF_MASS_X, &centreX);
		imaqMeasureParticle(binFrame, indexMax, 0, IMAQ_MT_CENTER_OF_MASS_Y, &centreY);

		imaqGetImageSize(binFrame, &largeurImage, &hauteurImage);
		double dHauteurImage(hauteurImage);
		double dLargeurImage(largeurImage);


		//Normalisation
		centreX = ((2 * centreX) / dLargeurImage) - 1;
		centreY = ((-2 * centreY) / dHauteurImage) + 1;


		angleX = atan(centreX * tan(FOV_X * acos(-1) / 180.0));
		angleY = atan(centreY * tan(FOV_Y * acos(-1) / 180.0));

		distance = (TARGET_HEIGHT - CAMERA_HEIGHT) / tan(CAMERA_ANGLE * acos(-1) / 180 + angleY);
		hypothenuse = sqrt(pow(distance, 2) + pow(TARGET_HEIGHT - CAMERA_HEIGHT, 2));

		offset = hypothenuse * tan(angleX);

		ecart = offset - CAMERA_OFFSET;



		SmartDashboard::PutNumber("Distance Cible", distance);
		SmartDashboard::PutNumber("Angle Cible", ecart);
		SmartDashboard::PutNumber("Aire Particule", aireMax);
		SmartDashboard::PutNumber("Nombre Particules", nbParticles);
		SmartDashboard::PutNumber("Hypothenuse", hypothenuse);
		SmartDashboard::PutNumber("Largeur image", largeurImage);
	}


}