Example #1
0
	/**
	 * Runs the motors with arcade steering. 
	 */
	void OperatorControl(void)
	{
		HSLImage *Himage;
		Threshold targetThreshold(247, 255, 60, 140, 10, 50);
		BinaryImage *matchingPixels;
		vector<ParticleAnalysisReport> *pReport;
		
		//myRobot->SetSafetyEnabled(true);
		Saftey->SetEnabled(false);
		AxisCamera &mycam = AxisCamera::GetInstance("10.15.10.11");
		
		mycam.WriteResolution(AxisCamera::kResolution_640x480);
		mycam.WriteCompression(20);
		mycam.WriteBrightness(25);
		Wait(3.0);
         
		dsLCD = DriverStationLCD::GetInstance();
		dsLCD->Clear();
		
		float X[2];
		float Y[2];
		float Z[2];
		
		while(IsOperatorControl())
		{
			X[1] = Stick1->GetX();
			X[2] = Stick2->GetX();
			Y[1] = Stick1->GetY();
			Y[2] = Stick2->GetY();
			Z[1] = Stick1->GetZ();
			Z[2] = Stick2->GetZ();
			
			Jaguar1->Set(Y[1]);
			Jaguar2->Set(Y[2]);
			
			Wait(0.005);
			if (mycam.IsFreshImage())
						{
							Himage = mycam.GetImage();
							
							matchingPixels = Himage->ThresholdHSL(targetThreshold);
							pReport = matchingPixels->GetOrderedParticleAnalysisReports();
							
							for (unsigned int i = 0; i < pReport->size(); i++)
							{
								printf("Index: %d X Center: %d Y Center: %d \n", i, (*pReport)[i].center_mass_x, (*pReport)[i].center_mass_y);
								
							}
							
							delete Himage;
							delete matchingPixels;
							delete pReport;
						}
			
		}
		
			
			//myRobot->ArcadeDrive(stick); // drive with arcade style (use right stick)
			//Wait(0.005);				// wait for a motor update time
	}
Example #2
0
bool JankyTargeting::DoImageProcessing(void)
{
	bool isSuccessful = false;
	BinaryImage* firstBinaryImage = NULL;
	BinaryImage* readyForConvexHull = NULL;
	
	firstBinaryImage = hsl.ThresholdHSL(120,186,60,255,0,255);
	
	if (firstBinaryImage !=NULL)
	{
		// Prune down # particles by removing all small stuff before convexHull.
		readyForConvexHull = firstBinaryImage->RemoveSmallObjects(false, 2);

		if (readyForConvexHull != NULL)
		{
			samwise = readyForConvexHull->ConvexHull(false);
			
			if (samwise != NULL)
				isSuccessful = true;
		}
	}
	
	if (readyForConvexHull)
		delete readyForConvexHull;

	if (firstBinaryImage)
		delete firstBinaryImage;
	
	return isSuccessful;
}	
Example #3
0
OpenBinaryImage::OpenBinaryImage(const BinaryImage& anImg,
				 unsigned int anOpenSize)

  throw(QgarErrorDomain)

  : BinaryImage(anImg)

{
  int sqsize = (2 * anOpenSize) + 1;  // Effective mask size

  if ((sqsize > anImg.width()) || (sqsize > anImg.height()))
    {
      std::ostringstream os;
      os << "Opening size ["
	 << sqsize
	 << " X "
	 << sqsize
	 << "] too large for image ["
	 << anImg.width()
	 << " X "
	 << anImg.height()
	 << "]";
      throw QgarErrorDomain(__FILE__, __LINE__,
			    "void qgar::OpenBinaryImage::OpenBinaryImage(const qgar::BinaryImage&, unsigned int)",
			    os.str());
    }

  perform(this, anOpenSize);
}
Example #4
0
//简单的测试程序,运行ok,结果ok
int main()
{
	BinaryImage a(4, 5);                //新建一张图片
	a.setIndexValue(0, 0, 1); a.setIndexValue(0, 1, 0); a.setIndexValue(0, 2, 0); a.setIndexValue(0, 3, 1); a.setIndexValue(0, 4, 0);
	a.setIndexValue(1, 0, 1); a.setIndexValue(1, 1, 1); a.setIndexValue(1, 2, 1); a.setIndexValue(1, 3, 0); a.setIndexValue(1, 4, 0);
	a.setIndexValue(2, 0, 1); a.setIndexValue(2, 1, 0); a.setIndexValue(2, 2, 1); a.setIndexValue(2, 3, 1); a.setIndexValue(2, 4, 0);
	a.setIndexValue(3, 0, 1); a.setIndexValue(3, 1, 0); a.setIndexValue(3, 2, 0); a.setIndexValue(3, 3, 0); a.setIndexValue(3, 4, 1);
	

	Element b(2, 2);                    //新建一个结构元素
	b.ptr[0][0] = 1; b.ptr[0][1] = 1;
	b.ptr[1][0] = 1; b.ptr[1][1] = 0;

	b.originX = 1;
	b.originY = 1;

	BinaryImage* k=a.dilation(b);        //dilation
	for (int i = 0; i < k->getRow(); i++)
	{
		for (int j = 0; j < k->getCol(); j++)
			cout << k->getIndexValue(i, j) << " ";
		cout << endl;
	}
	cout << "******************************" << endl;
	BinaryImage* l = a.erosion(b);        //erosion
	for (int i = 0; i < l->getRow(); i++)
	{
		for (int j = 0; j < l->getCol(); j++)
			cout <<l->getIndexValue(i, j) << " ";
		cout << endl;
	}
	cout << "******************************" << endl;
	system("pause");
}
Example #5
0
ErodedBinaryImage::ErodedBinaryImage(BinaryImage& anImg,
				     unsigned int anEroSize)
  throw(QgarErrorDomain)

  : BinaryImage(anImg)

{
  int sqsize = (2 * anEroSize) + 1;  // Effective mask size

  if ((sqsize > anImg.width()) || (sqsize > anImg.height()))
    {
      std::ostringstream os;
      os << "Erosion size ("
	 << sqsize
	 << " X "
	 << sqsize
	 << ") too large for an image "
	 << anImg.width()
	 << " X "
	 << anImg.height();
      throw QgarErrorDomain(__FILE__, __LINE__,
			    "qgar::ErodedBinaryImage::ErodedBinaryImage(qgar::BinaryImage&, unsigned int)",
			    os.str());
    }

  perform(this, anEroSize);
}
Example #6
0
BinaryImage *BinaryImage::RemoveLargeObjects(bool connectivity8, int erosions)
{
	BinaryImage *result = new BinaryImage();
	int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_SMALL, NULL);
	wpi_setImaqErrorWithContext(success, "Error in RemoveLargeObjects");
	return result;
}
Example #7
0
BinaryImage *BinaryImage::ConvexHull(bool connectivity8)
{
	BinaryImage *result = new BinaryImage();
	int success = imaqConvexHull(result->GetImaqImage(), m_imaqImage, connectivity8);
	wpi_setImaqErrorWithContext(success, "Error in convex hull operation");
	return result;
}
Example #8
0
Camera* Camera::calculate(void)
{
	AxisCamera &cam = AxisCamera::GetInstance("10.8.54.11");
	if (!cam.IsFreshImage())
				return this;
			
	take = false;
			
	int i = cam.GetImage(&ci);
	if (i) cerr << "image worked" << endl;
	else cerr << "image didn't work" << endl;
			
	//ci.Write("/colorimage.jpg");
		
	BinaryImage *bi = ci.ThresholdHSL(200, 55,
	                                  0, 255,
	                                  0, 200);
	//BinaryImage *bi = ci.ThresholdHSL(Constants::hueMin, Constants::hueMax, 
	//										  Constants::satMin, Constants::satMax, 
	//									      Constants::lumMin, Constants::lumMax);
	//BinaryImage *biggerObjects = bi->RemoveSmallObjects(false, 2);
	vector <ParticleAnalysisReport> *particleAnalysisList = bi->GetOrderedParticleAnalysisReports();
	Rect biggestRectangle = particleAnalysisList->at(0).boundingRect;
	
	int x = biggestRectangle.left + biggestRectangle.width/2;
	int y = biggestRectangle.top + biggestRectangle.height/2;
	
	cerr << "T: (" << x << "," << y << ")" << endl;
	
	bi->Write("/image.bmp");
	//delete bi;
	//delete particleAnalysisList;
	return this;
}
static bool checkAlignedImage(
	ConnCompEraserExt const& eraser, BinaryImage const& nonaligned)
{
	BinaryImage const aligned(eraser.computeConnCompImageAligned());
	int const pad = aligned.width() - nonaligned.width();
	if (pad < 0) {
		return false;
	}
	
	BinaryImage test1(nonaligned);
	BinaryImage empty1(test1.size());
	empty1.fill(WHITE);
	rasterOp<RopXor<RopSrc, RopDst> >(test1, test1.rect(), aligned, QPoint(pad, 0));
	if (test1 != empty1) {
		return false;
	}
	
	if (pad > 0) {
		// Check that padding is white.
		BinaryImage test2(pad, nonaligned.height());
		BinaryImage empty2(test2.size());
		empty2.fill(WHITE);
		rasterOp<RopSrc>(test2, test2.rect(), aligned, QPoint(0, 0));
		if (test2 != empty2) {
			return false;
		}
	}
	
	return true;
}
	double CameraHandler::GetDistanceToBall ()
    {
		unsigned x;

		int ballNum;
		double objAngle;
		double largestArea;
		double sizeRatio;

		BinaryImage* binImg;
		vector<ParticleAnalysisReport>* particles;

		// ----- Get Image -----
		camera->GetImage(img);

		// ----- Filter out background -----
		if (m_ds->GetAlliance() == DriverStation::kBlue)
					binImg = img->ThresholdHSV(160, 184, 120, 255, 14, 233);
				else
					binImg = img->ThresholdRGB(88, 255, 0, 74, 0, 31);

		// Make picture clear
		frcMorphology(binImg->GetImaqImage(),binImg->GetImaqImage(),IMAQ_PCLOSE);
		frcMorphology(binImg->GetImaqImage(),binImg->GetImaqImage(),IMAQ_ERODE);

		particles = binImg->GetOrderedParticleAnalysisReports();

		SmartDashboard::PutNumber("DEBUG Particle size: ", particles->size());

		if (particles->size() > 0 && particles->size() < 30)
		{
			sort(particles->begin(),particles->end(),particleSort);

			//Find ball

			largestArea = 25.0;
			ballNum = -1;

			for (x = 0; ((x < particles->size()) && x < 5); x++)
			{
				sizeRatio = (double)(*particles)[x].boundingRect.height/(*particles)[x].boundingRect.width;

				if (((*particles)[x].particleArea > largestArea) && (sizeRatio > 0.75 && sizeRatio < 1.25))
				{
					largestArea = (*particles)[x].particleArea;
					ballNum = x;
				}
			}
		}

		if (ballNum >= 0)
		{
            objAngle = 0.5*((*particles)[ballNum].boundingRect.width)*(CAMERA_ANGLE/(*particles)[ballNum].imageWidth);

            return 1/tan(objAngle);
		}
		else
			return -1.0;
    }
Example #11
0
BinaryImage*
ConnectedComponents::makeBinaryImg
  (const std::vector<Component::label_type>& aLabSet)
{
  // Create the resulting image
  BinaryImage* pImgBin = new BinaryImage(componentImg_.width(),
					 componentImg_.height());

  // Pointers to pixel maps
  Component::label_type* pMapCC  = componentImg_.pPixMap();
  BinaryImage::pointer   pMapBin = pImgBin->pPixMap();

  // Current label and color
  Component::label_type currLab   = Component::LABEL_NO_;
  QGEbw                 currColor = QGE_BW_WHITE;

  // Number of pixels of both images
  int size = componentImg_.width() * componentImg_.height();


  // For each pixel of the component image

  for (int iCnt = 0 ; iCnt< size ; ++iCnt, ++pMapCC, ++pMapBin)
    {

      if (*pMapCC != currLab)
	{
	  // The new pixel belongs to a new component
	  
	  currLab = *pMapCC;

	  std::vector<Component::label_type>::const_iterator it =
	    find(aLabSet.begin(), aLabSet.end(), currLab);

	  if (   (it == aLabSet.end())
	      || ((*this)[currLab].color() == QGE_BW_WHITE))
	    {
	      // Current label does not belong to the given set
	      // or belongs to a WHITE component
	      currColor = QGE_BW_WHITE;
	    }
	  else
	    {
	      // Current label belongs to a BLACK component
	      currColor = QGE_BW_BLACK;
	    }
	}

      // Set the corresponding pixel of the resulting image
      // to current color
      *pMapBin = currColor;

    } // END for iCnt


  // Return a pointer to the resulting image
  return pImgBin;
}
Example #12
0
BinaryImage *BinaryImage::ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount)
{
	BinaryImage *result = new BinaryImage();
	int numParticles;
	ParticleFilterOptions2 filterOptions = {0, 0, 0, 1};
	int success = imaqParticleFilter4(result->GetImaqImage(), m_imaqImage, criteria, criteriaCount, &filterOptions, NULL, &numParticles);
	wpi_setImaqErrorWithContext(success, "Error in particle filter operation");
	return result;
}
Example #13
0
BinaryImage BinaryImage::GetBlock(int iS, int iE, int jS, int jE)
{
	BinaryImage mat;
	mat.MM = iE - iS + 1;
	mat.NN = jE - jS + 1;
	mat.data = new double[mat.MM * mat.NN];

	for (int i = 0; i < mat.MM; i++)
	for (int j = 0; j < mat.NN; j++)
		mat.Set(i, j, Get(i + iS, j + jS));

	return mat;
}
Example #14
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
 * @returns a pointer to a binary image
 */
BinaryImage *ColorImage::ComputeThreshold(ColorMode colorMode,
		int low1, int high1,
		int low2, int high2,
		int low3, int high3)
{
	BinaryImage *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;
}
Example #15
0
BinaryImage::BinaryImage(const BinaryImage& rhs)
{
	//cout<<"BinaryImage::BinaryImage(const BinaryImage&) is invoked...";

	m = rhs.getm();
	n = rhs.getn();

	data = new double[m * n];
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			data[i * n + j] = rhs.get(i, j);
		}
	}
}
void
TextLineTracer::sanitizeBinaryImage(BinaryImage& image, QRect const& content_rect)
{
	// Kill connected components touching the borders.
	BinaryImage seed(image.size(), WHITE);
	seed.fillExcept(seed.rect().adjusted(1, 1, -1, -1), BLACK);

	BinaryImage touching_border(seedFill(seed.release(), image, CONN8));
	rasterOp<RopSubtract<RopDst, RopSrc> >(image, touching_border.release());

	// Poor man's despeckle.
	BinaryImage content_seeds(openBrick(image, QSize(2, 3), WHITE));
	rasterOp<RopOr<RopSrc, RopDst> >(content_seeds, openBrick(image, QSize(3, 2), WHITE));
	image = seedFill(content_seeds.release(), image, CONN8);

	// Clear margins.
	image.fillExcept(content_rect, WHITE);
}
Example #17
0
void
PolynomialSurface::prepareEquationsAndDataPoints(
	GrayImage const& image, BinaryImage const& mask,
	std::vector<double>& equations,
	std::vector<double>& data_points) const
{
	int const width = image.width();
	int const height = image.height();
	
	double const xscale = calcScale(width);
	double const yscale = calcScale(height);
	
	uint8_t const* image_line = image.data();
	int const image_bpl = image.stride();
	
	uint32_t const* mask_line = mask.data();
	int const mask_wpl = mask.wordsPerLine();
	int const last_word_idx = (width - 1) >> 5;
	int const last_word_mask = ~uint32_t(0) << (31 - ((width - 1) & 31));
	
	for (int y = 0; y < height; ++y) {
		double const y_adjusted = y * yscale;
		int idx = 0;
		
		// Full words.
		for (; idx < last_word_idx; ++idx) {
			processMaskWord(
				image_line, mask_line[idx], idx, y,
				y_adjusted, xscale, equations, data_points
			);
		}
		
		// Last word.
		processMaskWord(
			image_line, mask_line[idx] & last_word_mask,
			idx, y, y_adjusted, xscale, equations, data_points
		);
		
		image_line += image_bpl;
		mask_line += mask_wpl;
	}
}
Example #18
0
BinaryImage::BinaryImage(const BinaryImage& bin)
{
	MM = bin.MM;
	NN = bin.NN;
	data = new double[MM*NN];

	for (int i = 0; i < MM; i++)
	{
		for (int j = 0; j < NN; j++)
		{
			this->Set(i, j, bin.Get(i, j));
		}
	}
}
Example #19
0
double BinaryImage::SSD(const BinaryImage& T)
{
	Matrix Diff(32, 32, 1);
	double sum = 0;
	for (int i = 0; i < 32; i++)
	{
		for (int j = 0; j < 32; j++)
		{
			Diff.Set(i, j, (Get(i, j) - T.Get(i, j)));
			sum += Diff.Get(i, j)*Diff.Get(i, j);
		}
	}
	return sum;
}
Example #20
0
BinaryImage BinaryImage::operator=(const BinaryImage& bin)
{
	this->MM = bin.MM;
	this->NN = bin.NN;
	this->data = new double[this->MM*this->NN];
	for (int i = 0; i < this->MM; i++)
	{
		for (int j = 0; j < this->NN; j++)
		{
			this->Set(i, j, bin.Get(i, j));
		}
	}

	return *this;
}
Example #21
0
BinaryImage BinaryImage::operator-(BinaryImage& in)
{
	BinaryImage out(this->getWidth(), this->getHeight());
	
	for(int i = 0; i < this->getHeight(); i ++)
	{
		for(int j = 0; j < this->getWidth(); j ++)
		{
			// XOR
			bool a = this->pixel(i, j) > 0;
			bool b = in.pixel(i, j)    > 0;
			
			// Result
			bool r = (a && !b) || (!a && b);
			
			out(i, j) = r ? 1 : 0;
		} 
	}
	
	return out;
}
Example #22
0
int main()
{
    PngImage Png;
    Png.Read("./cballs.png");

    GrayImage GrayOriginal, GrayBlured, GrayAdjusted;
    // Convert original PNG to gray-level image
    GrayOriginal.Convert(Png);

    // Blur PNG image
    FastGaussianBlur::Blur<3>(Png, 4.0);
    Png.Write("./cballs_blured.png");
    
    // Convert Blured PNG image to gray-level image
    GrayBlured.Convert(Png);
    GrayAdjusted.CopyFrom(GrayBlured);

    // Adjust color
    GrayAdjusted.AdjustColor(1.5, -250);

    Png.Write(GrayOriginal, "./cballs_gray.png");
    Png.Write(GrayBlured, "./cballs_grayblured.png");
    Png.Write(GrayAdjusted, "./cballs_grayadjusted.png");

    BinaryImage Bin;

    // Example of Otsu binarization
    Bin.Otsu(GrayAdjusted);
    Png.Write(Bin, "./cballs_otsu.png");

    // Example of Niblack binarization
    Bin.Niblack(GrayAdjusted, 150, 1.5);
    Png.Write(Bin, "./cballs_niblack.png");

    // Example of Sauvola binarization
    Bin.Sauvola(GrayAdjusted, 20, 0.2);
    Png.Write(Bin, "./cballs_sauvola.png");

    Png.Read("./cballs.png");
    Cluster Objects;
    // Clusterize white objects (glowing white balls)
    uint16_t ClusterAmount = Objects.Clusterize(Bin);
    for (int i = 0; i < ClusterAmount; ++i)
    {
        const ClusterItem &item = Objects.GetCluster(i);
        Png.DrawCross(item.Cx, item.Cy, 20, PixelType::RGB24(0,255,0));
    }
    Png.Write("./cballs_clusterized.png");


    Png.Read("./cballs.png");
    
    PngImage Png2;
    Png2.Read("./cballs.png");
    AffineTransformation Affine;
    AffineTransformation Affine2;

    GrayImage Gray1, Gray2;
    Gray1.Convert(Png);

    //Affine.Shift(20, 50);
    Affine.RotateDeg(22.5);
    Affine2.Scale(2, 2);
    //Affine.Scale(0.5, 0.5);

    Affine.Transform(Affine2);

    AffineTransformationTable AffineTable;
    AffineTable.Calculate(Gray1.GetWidth(), Gray1.GetHeight(), Affine, true);
    AffineTable.Apply<InterpolationType::NearestNeighbour>(Gray1, Gray2);
    Png.Write(Gray2, "./cballs_affine.png");
    
    PngImage testPng;
    testPng.Read("./cballs.png");
    GrayImage testGray, testGray2;
    testGray.Convert(testPng);
    testGray2.CopyFrom(testGray);
    
    Sobel sobel;
    

    sobel.Calculate(testGray);
    const GenericImage<GenericPixel<int32_t , 1>> *magn = sobel.GetMagnitude();
    
    int32_t min_ = min(*magn);
    int32_t max_ = max(*magn);
    int32_t factor = max_ - min_;
    printf("%d %d %d\n", min_, max_, factor);
    auto it_src = magn->begin();
    auto it_dst = testGray.begin();
    for (; it_src != magn->end(); ++it_src, ++it_dst)
    {
        if (factor > 0)
        {
            int32_t p = it_src[0];
            p -= min_;
            it_dst[0] = (unsigned char) min(255, max(0, (255 * p) / factor));
        }
        else
        {
            it_dst[0] = (unsigned char) min(255, max(0, it_src[0]));
        }
    }
    testPng.Write(testGray, "./cballs_sobel.png");
    
    BinaryImage testBin;
    //GrayImage testGray3;
    Canny canny;
    FastGaussianBlur::Blur<3>(testGray2, 1.3);
    canny.Calculate(testGray2, testBin, 0, 0, 0.33, 0.33);
    testPng.Write(testBin, "./cballs_canny.png");
    
    HoughLine hough;
    hough.Calculate(testBin, -30, 30, 0.5, 0, 100, 1, 255);
    int32_t W = hough.GetWidth();
    int32_t H = hough.GetHeight();
    printf("%d %d\n", W,H);
    testGray2.Create(W,H,PixelType::Mono8(0));
    printf("%d %d\n", testGray2.GetWidth(), testGray2.GetHeight());
    {
        auto it_src = hough.begin();
        auto it_dst = testGray2.begin();
        for (; it_src != hough.end(); ++it_src, ++it_dst)
        {
            it_dst[0] = it_src[0];
        }
    }
    
    testPng.Write(testGray2, "./cballs_hough.png");
    return 0;
}
Example #23
0
void
Despeckle::despeckleInPlace(
	BinaryImage& image, Dpi const& dpi, Level const level,
	TaskStatus const& status, DebugImages* const dbg)
{
	Settings const settings(Settings::get(level, dpi));

	ConnectivityMap cmap(image, CONN8);
	if (cmap.maxLabel() == 0) {
		// Completely white image?
		return;
	}

	status.throwIfCancelled();
	
	std::vector<Component> components(cmap.maxLabel() + 1);
	std::vector<BoundingBox> bounding_boxes(cmap.maxLabel() + 1);

	int const width = image.width();
	int const height = image.height();

	uint32_t* const cmap_data = cmap.data();
	
	// Count the number of pixels and a bounding rect of each component.
	uint32_t* cmap_line = cmap_data;
	int const cmap_stride = cmap.stride();
	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			uint32_t const label = cmap_line[x];
			++components[label].num_pixels;
			bounding_boxes[label].extend(x, y);
		}
		cmap_line += cmap_stride;
	}
	
	status.throwIfCancelled();

	// Unify big components into one.
	std::vector<uint32_t> remapping_table(components.size());
	uint32_t unified_big_component = 0;
	uint32_t next_avail_component = 1;
	for (uint32_t label = 1; label <= cmap.maxLabel(); ++label) {
		if (bounding_boxes[label].width() < settings.bigObjectThreshold &&
				bounding_boxes[label].height() < settings.bigObjectThreshold) {
			components[next_avail_component] = components[label];
			remapping_table[label] = next_avail_component;
			++next_avail_component;
		} else {
			if (unified_big_component == 0) {
				unified_big_component = next_avail_component;
				++next_avail_component;
				components[unified_big_component] = components[label];
				// Set num_pixels to a large value so that canBeAttachedTo()
				// always allows attaching to any such component.
				components[unified_big_component].num_pixels = width * height;
			}
			remapping_table[label] = unified_big_component;
		}
	}
	components.resize(next_avail_component);
	std::vector<BoundingBox>().swap(bounding_boxes); // We don't need them any more.
	
	status.throwIfCancelled();

	uint32_t const max_label = next_avail_component - 1;
	
	// Remapping individual pixels.
	cmap_line = cmap_data;
	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			cmap_line[x] = remapping_table[cmap_line[x]];
		}
		cmap_line += cmap_stride;
	}
	if (dbg) {
		dbg->add(cmap.visualized(), "big_components_unified");
	}

	status.throwIfCancelled();
	
	// Build a Voronoi diagram.
	std::vector<Distance> distance_matrix;
	voronoi(cmap, distance_matrix);
	if (dbg) {
		dbg->add(cmap.visualized(), "voronoi");
	}
	
	status.throwIfCancelled();

	Distance* const distance_data = &distance_matrix[0] + width + 3;
	
	// Now build a bidirectional map of distances between neighboring
	// connected components.
	
	typedef std::map<Connection, uint32_t> Connections; // conn -> sqdist
	Connections conns;
	
	voronoiDistances(cmap, distance_matrix, conns);
	
	status.throwIfCancelled();

	// Tag connected components with ANCHORED_TO_BIG or ANCHORED_TO_SMALL.
	BOOST_FOREACH(Connections::value_type const& pair, conns) {
		Connection const conn(pair.first);
		uint32_t const sqdist = pair.second;
		Component& comp1 = components[conn.lesser_label];
		Component& comp2 = components[conn.greater_label];
		tagSourceComponent(comp1, comp2, sqdist, settings);
		tagSourceComponent(comp2, comp1, sqdist, settings);
	}
Example #24
0
NiblackBinaryImage::NiblackBinaryImage(const GreyLevelImage& anImg,
				       const int aLowThres,
				       const int aHighThres,
				       const int aMaskSize,
				       const float aK,
				       const float aPostThres)

  : BinaryImage(anImg.width(), anImg.height())

{
  // Pointer to mean image
  FloatImage* pMeanImg = 0;

  // Compute standard deviation and mean
  StandardDeviationImage stdImg(FloatImage(anImg), pMeanImg, aMaskSize);

  // Rows to exchange data
  GreyLevelImage::pointer bRow = new GreyLevelImage::value_type [_width];
  GreyLevelImage::pointer gRow = new GreyLevelImage::value_type [_width];

  float* mRow = new float [_width];
  float* sRow = new float [_width];
  
  // Binarize
  for (int i = 0 ; i < _height ; ++i)
    {
      // Read means
      pMeanImg->row(i, mRow);
      // Read deviations
      stdImg.row(i, sRow);
      // Read original
      anImg.row(i, gRow);

      // Pointers
      float* m = mRow;
      float* s = sRow;
      GreyLevelImage::pointer g = gRow;
      GreyLevelImage::pointer b = bRow;

      // Dynamic thresholding
      for (int j = 0 ; j < _width ; ++j, ++b, ++g)
	{
	  if (*g < aLowThres)
	    {
	      *b = 1;
	    }
	  else if (*g > aHighThres)
	    {
	      *b = 0;
	    }
	  else if (*g < (GreyLevelImage::value_type) (*m++ + aK * *s++))
	    {
	      *b = 1;
	    }
	  else
	    {
	      *b = 0;
	    }
	}

      // Save line
      setRow(i, bRow);
    }

  // Post-processing
  if (aPostThres > 0)
    {
      // Copy reference image
      BinaryImage* contours = new BinaryImage(*this);

      // Extract connected components
      ConnectedComponents* compConnexes = new ConnectedComponents(*contours);

      // Prepare tables
      int labCnt = compConnexes->componentCnt();
      // Tables for the sums of the means of the gradient
      float* gsum = new float [labCnt];
      qgFill(gsum, labCnt, 0.f);
      // Tables for the numbers of points -- for the mean
      int* psum = new int [labCnt];
      qgFill(psum, labCnt, 0);

      // Table of labels
      Component::label_type* labRow = new Component::label_type[_width];
      // By construction, first and last pixels are always WHITE
      labRow[1] = 0;
      labRow[_width - 1] = 0;

      // Compute the module of Canny gradient
      CannyGradientImage* gradImg = new CannyGradientImage(anImg);
      GradientModuleImage gradModImg(*gradImg);
      delete gradImg;

      // Construct the image of the contours of the black components
      // which thus includes the interesting pixels
      ErodedBinaryImage* eroImg = new ErodedBinaryImage(*contours);
      (*contours) -= (*eroImg);
      delete eroImg;

      // Create a line of floats
      float* fRow = new float [_width];

      // Pointer to the pixel map of the component image
      Component::label_type* pMapCCImg =
	(compConnexes->accessComponentImage()).pPixMap() + _width;

      for (int i = 1 ; i < (_height - 1) ; ++i)
	{
	  // Get a line of labels from the component image
	  // and set pixels from white components to 0
	  pMapCCImg += 2;
	  PRIVATEgetBlackLabels(pMapCCImg, labRow);

	  // Read the corresponding line in the contours
	  contours->row(i, bRow);

	  // Read the corresponding line in the module of the gradient
	  gradModImg.row(i, fRow);
	  Component::label_type* p = labRow;
	  GreyLevelImage::pointer q = bRow;
	  float* r = fRow;
	  for (int j = 0 ; j < _width ; ++j, ++p, ++q, ++r)
	    {
	      if (*q != 0)  // We are on a contour
		{
		  gsum[(int)(*p)] += *r;
		  psum[(int)(*p)] += 1;
		}
	    } // END for j
	} // END for i

      delete contours;
 
     // Compute the means
      for (int i = 0 ; i < labCnt ; ++i)
	{
	  if (psum[i] != 0)
	    {
	      gsum[i] /= psum[i];
	    }
	} // END for
  
      // Pointer to the pixel map of the component image
      pMapCCImg = (compConnexes->accessComponentImage()).pPixMap() + _width;
      // Delete fake black components
      for (int i = 1 ; i < _height - 1 ; ++i)
	{
	  // Read the current line of components
	  pMapCCImg += 2;
	  PRIVATEgetBlackLabels(pMapCCImg, labRow);

	  // Read the corresponding line in the binary image
	  row(i, bRow);

	  // Examine components and delete
	  Component::label_type* p = labRow;
	  GreyLevelImage::pointer pb = bRow;
	  for (int j = 0 ; j < _width ; ++j, ++p, ++pb)
	    {
	      if (((*pb) != 0) && (gsum[(int)(*p)] < aPostThres))
		{
		  *pb = 0;
		}
	    }

	  // Save this line
	  setRow(i, bRow);
	} // END for

      // Clean up
      delete [] fRow;
      delete [] psum;
      delete [] gsum;
      delete compConnexes;
    }

  // And clean up
  delete [] bRow;
  delete [] gRow;
  delete [] mRow;
  delete [] sRow;
}
Example #25
0
ConnectedComponents::ConnectedComponents(const BinaryImage& aBinImg)

  : componentImg_(ConnectedComponents::image_type(aBinImg.width(),
						  aBinImg.height()))

{
  // Initialize offset tables used during contour following
  // to get 4- and 8-connected neighbors in a 3X3 neighborhood.
  // See class qgar::Component for full details.

  int w = aBinImg.width();

  // 4-CONNECTIVITY
  //
  //   current (contour) direction
  //   N       E       S       W
  //   0   1   2   3   4   5   6   7   8   9  10  11  12 
  // +---+---+---+---+---+---+---+---+---+---+---+---+---+
  // | -1| * | -w| * | 1 | * | w | * | -1| * |-w | * | 1 |
  // +---+---+---+---+---+---+---+---+---+---+---+---+---+

  int tmpOff4[13] =
    {
      -1, 0, -w, 0, 1, 0, w, 0, -1, 0, -w, 0, 1
    };

  offset3X3_4_ = new int[13];
  memcpy(offset3X3_4_, tmpOff4, 13 * sizeof(int));

  // 8-CONNECTIVITY
  //
  //                      search rank
  //                      0    1    2    3    4    5  
  //                   +----+----+----+----+----+----+
  //            / N  0 | -1 | -w |-w-1|  1 |-w+1|  w |
  //            |      +----+----+----+----+----+----+
  //            | NE 1 | -w |-w-1|  1 |-w+1| w+1| w-1|
  //            |      +----+----+----+----+----+----+
  //            | E  2 | -w |  1 |-w+1|  w | w+1| -1 |
  //            |      +----+----+----+----+----+----+
  //  current   | SE 3 |  1 |-w+1|  w | w+1| w-1|-w-1|
  //  contour  <       +----+----+----+----+----+----+
  // direction  | S  4 |  1 |  w | w+1| -1 | w-1| -w |
  //            |      +----+----+----+----+----+----+
  //            | SW 5 |  w | w+1| -1 | w-1|-w-1|-w+1|
  //            |      +----+----+----+----+----+----+
  //            | W  6 |  w | -1 | w-1| -w |-w-1|  1 |
  //            |      +----+----+----+----+----+----+
  //            \ NW 7 | -1 | w-1| -w |-w-1|-w+1| w+1|
  //                   +----+----+----+----+----+----+

  int tmpOff8[48] =
    {
      -1,   -w, -w-1,    1, -w+1,    w,
      -w, -w-1,    1, -w+1,  w+1,  w-1,
      -w,    1, -w+1,    w,  w+1,   -1,
       1, -w+1,    w,  w+1,  w-1, -w-1,
       1,    w,  w+1,   -1,  w-1,   -w,
       w,  w+1,   -1,  w-1, -w-1, -w+1,
       w,   -1,  w-1,   -w, -w-1,    1,
      -1,  w-1,   -w, -w-1, -w+1,  w+1 
   };

  offset3X3_8_ = new int[48];
  memcpy(offset3X3_8_, tmpOff8, 48 * sizeof(int));

  // Initialize data in order to run the construction of components
  ConnectedComponentsImpl ccImpl(aBinImg,
				 &componentImg_,
				 componentTree_,
				 componentTab_,
				 offset3X3_4_,
				 offset3X3_8_);

   // Run the construction of connected components
  ccImpl.run();
}
	CameraHandler::state_t CameraHandler::getHotGoal ()
	{
		unsigned x;

		int largestWidth;		// Index of Particle
		int largestHeight;		// Index of Particle
		int largestWidthVal;	// Actual Width
		int largestHeightVal;	// Actual Height

		BinaryImage* binImg;
		ColorImage* colImg;
		vector<ParticleAnalysisReport>* particles;

		// Get Camera Image
		camera->GetImage(img);
		img->Write("bobnormal.bmp");
		// Filter out Background
		binImg = img->ThresholdHSL(103, 156, 252, 255, 33, 109);
		binImg->Write("bobbin.bmp");

		// Make picture clear
		frcMorphology(binImg->GetImaqImage(),binImg->GetImaqImage(),IMAQ_PCLOSE);
		frcMorphology(binImg->GetImaqImage(),binImg->GetImaqImage(),IMAQ_DILATE);

		// Get Particle Analysis
		particles = binImg->GetOrderedParticleAnalysisReports();
		SmartDashboard::PutNumber("Num of Particles: ",particles->size());
		if (particles->size() == 1) {
			// Find Only One Particle
			return CameraHandler::kNone;
		} else if (particles->size() > 0 && particles->size() < 30) {
			// Sort by size
			sort(particles->begin(), particles->end(), particleSort);

			// Initialize
			largestWidth = 0;
			largestHeight = 0;
			largestWidthVal = 0;
			largestHeightVal = 0;

			for (x=0; (x < 3 &&  x < particles->size()); x++) {
				// Find tallest
				if ((*particles)[x].boundingRect.height > largestHeightVal) {
					largestHeight = x;
					largestHeightVal = (*particles)[x].boundingRect.height;
				}

				// Find Fattest
				if ((*particles)[x].boundingRect.width > largestWidthVal) {
					largestWidth = x;
					largestWidthVal = (*particles)[x].boundingRect.width;
				}
			}

			if ((*particles)[largestWidth].center_mass_x < (*particles)[largestHeight].center_mass_x) {
				return kLeft;
			}
			else if ((*particles)[largestWidth].center_mass_x > (*particles)[largestHeight].center_mass_x) {
				return kRight;
			}
			else {
				return kNone;
			}

		} else {
			// Find Too Many Particles or None
			return kError;
		}
	}
	double CameraHandler::getCenter()
	{
		unsigned x,y;

		int largestWidth;
		int largestHeight[2];
		int largestWidthVal, largestHeightVal;

		BinaryImage* binImg;
		vector<ParticleAnalysisReport>* particles;

		//m_dsLCD->Printf(DriverStationLCD::kUser_Line1, 1, "Test");
		//m_dsLCD->UpdateLCD();
		//Get new camera image
		camera->GetImage(img);

		//img.Write("bob2.jpg");  //Cannot work with non-RGB images

		//int Wid = img->GetWidth();  //Sanity Check: Check width of image
		//Prints width of image from camera
		//m_dsLCD->Printf(DriverStationLCD::kUser_Line1, 1,"Width of Image: %d",Wid);

		//Perform HSLThreshold to pull out only blue LED reflection of targets into BinaryImage
		//BinaryImage* binImg = img->ThresholdHSL(202, 255, 55, 255, 55, 129);      //RED LED WORKS TERRRIBLY!!!!
		binImg = img->ThresholdHSL(52, 255, 71, 188, 76, 219);      //RED LED WORKS TERRRIBLY!!!!
		//BinaryImage* binImg = img->ThresholdHSL(57, 255, 79, 255, 51, 255);  //BLUE LED
		//BinaryImage* binImg = img->ThresholdHSL(159, 255, 0, 255, 71, 255);  //RED LED
		//Perform Morphology on image to remove noise/unwanted particles.  Also fills in incomplete particles.
		frcMorphology(binImg->GetImaqImage(),binImg->GetImaqImage(),IMAQ_PCLOSE);

		frcMorphology(binImg->GetImaqImage(),binImg->GetImaqImage(),IMAQ_DILATE);
		//Perform particle analysis on BinaryImage, creates vector with all particles found
		particles = binImg->GetOrderedParticleAnalysisReports();

		printf("Particles found: %d",(int)particles->size());

		//Print numbers of particles found to driver station
		//m_dsLCD->Printf(DriverStationLCD::kUser_Line4, 1, "# Parts:%d    ",particles->size());
		//m_dsLCD->UpdateLCD();
		if(particles->size() > 1 || particles->size() < 30)
		{// Sort by size
			sort(particles->begin(), particles->end(), particleSort);

			// Initialize
			y=0;

			largestWidth = 0;
			largestHeight[0] = -1;
			largestHeight[1] = -1;
			largestHeightVal = 0;
			largestWidthVal = 0;
			largestHeightVal = 10;

			for (x=0; (x < 3 &&  x < particles->size()); x++) {
				// Find tallest
				if ((*particles)[x].boundingRect.height > largestHeightVal) {
					largestHeight[y] = x;
					largestHeightVal = (*particles)[x].boundingRect.height;
					y++;
				}

				// Find Fattest
				if ((*particles)[x].boundingRect.width > largestWidthVal) {
					largestWidth = x;
					largestWidthVal = (*particles)[x].boundingRect.width;
				}
			}

			// Detect Which Is Hot And Return Normalized Value of X (-1.0 - 1.0)
			if (fabs((*particles)[largestHeight[0]].center_mass_x - (*particles)[largestWidth].center_mass_x) < fabs((*particles)[largestHeight[1]].center_mass_x - (*particles)[largestWidth].center_mass_x)) {
				return (*particles)[largestHeight[0]].center_mass_x_normalized;
			} else {
				return (*particles)[largestHeight[1]].center_mass_x_normalized;
			}
		}
		else{
			return 0;
		}
	}
Example #28
0
int
main(int argc, char* argv[])
{
  QgarApp app;

  // PARAMETERS DESCRIPTION
  // ======================

  //
  app.addParameter("-in",
		   QgarArgs::REQPARAM,
		   QgarArgs::FILEIN,
		   "Source image:");

  //
  app.addParameter("-size",
		   QgarArgs::REQPARAM,
		   QgarArgs::INT,
		   "Maximum width:",
		   0,
		   "6");

  //
  app.addParameter("-outhick",
		   QgarArgs::REQPARAM,
		   QgarArgs::FILEOUTD,
		   "Image of thick lines:",
		   ".thick.pbm");

  //
  app.addParameter("-outhin",
		   QgarArgs::REQPARAM,
		   QgarArgs::FILEOUTD,
		   "Image of thin lines:",
		   ".thin.pbm");

  app.setDescription("Thick-thin separation", QgarArgs::PBM);

  // COMMAND LINE ANALYSIS
  // =====================

  app.analyzeLine(argc, argv);

  // Error while parsing parameters?
  if (app.isError())
    {
      return app._CODE_ERROR;
    }

  // Application invoked with flag '-gui'?
  if (app.isExit())
    {
      return app._CODE_GUI;
    }

  app.showProgressBar();

  // GET SOURCE IMAGE
  // ================

  cout << "Loading source image..." << endl;

  PbmFile sourceFile((char*) app.getStringOption("-in"));
  BinaryImage sourceImg = sourceFile.read();

  app.setProgressBar(20);

  // EXTRACT THICK LINES
  // ===================

  cout << "Extracting thick lines..." << endl;

  OpenBinaryImage thickImg(sourceImg, atoi(app.getStringOption("-size")) / 2);
  DilatedBinaryImage::perform(&thickImg);

  BinaryImage::value_type* pMapSource = sourceImg.pPixMap();
  BinaryImage::value_type* pMapThick  = thickImg.pPixMap();

  int size = thickImg.width() * thickImg.height();
  for (int iCnt = 0 ; iCnt < size; ++iCnt, ++pMapThick, ++pMapSource)
    {
      *pMapThick &= *pMapSource;
    }

  app.setProgressBar(50);

  // SAVE THICK LINES
  // ================

  cout << "Saving thick lines..." << endl;

  PbmFile thickFile((char*) app.getStringOption("-outhick"));
  thickFile.write(thickImg);

  app.setProgressBar(60);

  // EXTRACT THIN LINES
  // ==================

  cout << "Extracting thin lines..." << endl;

  sourceImg -= thickImg;  

  app.setProgressBar(90);

  // SAVE THIN LINES
  // ===============

  cout <<"Saving thin lines..."  << endl;

  PbmFile thinFile((char*) app.getStringOption("-outhin"));
  thinFile.write(sourceImg);

  app.setProgressBar(100);

  // DISPLAY RESULTS
  // ===============

  cout << "Thick-thin separation done." << endl;
  app.closeProgressBar();

  app.showPicture((char*)app.getStringOption("-outhick"));
  app.showPicture((char*)app.getStringOption("-outhin"));

  // NORMAL TERMINATION
  // ==================

  return app._CODE_END;

}
Example #29
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;
		}
	}
Example #30
0
inline void processTaskFunc(UINT32 hotGoalPtr...)
{
			bool hotGoal = (bool *) hotGoalPtr;
			Scores *scores;
			TargetReport target;
			int verticalTargets[MAX_PARTICLES];
			int horizontalTargets[MAX_PARTICLES];
			int verticalTargetCount, horizontalTargetCount;
			Threshold threshold(0, 255, 0, 255, 220, 255);	//HSV threshold criteria, ranges are in that order ie. Hue is 60-100
			ParticleFilterCriteria2 criteria[] = {
					{IMAQ_MT_AREA, AREA_MINIMUM, 65535, false, false}
			};												//Particle filter criteria, used to filter out small particles
			//AxisCamera &camera = AxisCamera::GetInstance();	//To use the Axis camera uncomment this line
			
	            /**
	             * Do the image capture with the camera and apply the algorithm described above. This
	             * sample will either get images from the camera or from an image file stored in the top
	             * level directory in the flash memory on the cRIO. The file name in this case is "testImage.jpg"
	             */
				ColorImage *image;
				image = new RGBImage("/testImage.jpg");		// get the sample image from the cRIO flash

				//image = camera.GetImage();				//To get the images from the camera comment the line above and uncomment this one
				BinaryImage *thresholdImage = image->ThresholdHSV(threshold);	// get just the green target pixels
				//thresholdImage->Write("/threshold.bmp");
				BinaryImage *filteredImage = thresholdImage->ParticleFilter(criteria, 1);	//Remove small particles
				//filteredImage->Write("Filtered.bmp");

				vector<ParticleAnalysisReport> *reports = filteredImage->GetOrderedParticleAnalysisReports();  //get a particle analysis report for each particle

				verticalTargetCount = horizontalTargetCount = 0;
				//Iterate through each particle, scoring it and determining whether it is a target or not
				if(reports->size() > 0)
				{
					scores = new Scores[reports->size()];
					for (unsigned int i = 0; i < MAX_PARTICLES && i < reports->size(); i++) {
						ParticleAnalysisReport *report = &(reports->at(i));
						
						//Score each particle on rectangularity and aspect ratio
						scores[i].rectangularity = scoreRectangularity(report);
						scores[i].aspectRatioVertical = scoreAspectRatio(filteredImage, report, true);
						scores[i].aspectRatioHorizontal = scoreAspectRatio(filteredImage, report, false);			
						
						//Check if the particle is a horizontal target, if not, check if it's a vertical target
						if(scoreCompare(scores[i], false))
						{
							printf("particle: %d  is a Horizontal Target centerX: %d  centerY: %d \n", i, report->center_mass_x, report->center_mass_y);
							horizontalTargets[horizontalTargetCount++] = i; //Add particle to target array and increment count
						} else if (scoreCompare(scores[i], true)) {
							printf("particle: %d  is a Vertical Target centerX: %d  centerY: %d \n", i, report->center_mass_x, report->center_mass_y);
							verticalTargets[verticalTargetCount++] = i;  //Add particle to target array and increment count
						} else {
							printf("particle: %d  is not a Target centerX: %d  centerY: %d \n", i, report->center_mass_x, report->center_mass_y);
						}
						printf("Scores rect: %f  ARvert: %f \n", scores[i].rectangularity, scores[i].aspectRatioVertical);
						printf("ARhoriz: %f  \n", scores[i].aspectRatioHorizontal);	
					}

					//Zero out scores and set verticalIndex to first target in case there are no horizontal targets
					target.totalScore = target.leftScore = target.rightScore = target.tapeWidthScore = target.verticalScore = 0;
					target.verticalIndex = verticalTargets[0];
					for (int i = 0; i < verticalTargetCount; i++)
					{
						ParticleAnalysisReport *verticalReport = &(reports->at(verticalTargets[i]));
						for (int j = 0; j < horizontalTargetCount; j++)
						{
							ParticleAnalysisReport *horizontalReport = &(reports->at(horizontalTargets[j]));
							double horizWidth, horizHeight, vertWidth, leftScore, rightScore, tapeWidthScore, verticalScore, total;
		
							//Measure equivalent rectangle sides for use in score calculation
							imaqMeasureParticle(filteredImage->GetImaqImage(), horizontalReport->particleIndex, 0, IMAQ_MT_EQUIVALENT_RECT_LONG_SIDE, &horizWidth);
							imaqMeasureParticle(filteredImage->GetImaqImage(), verticalReport->particleIndex, 0, IMAQ_MT_EQUIVALENT_RECT_SHORT_SIDE, &vertWidth);
							imaqMeasureParticle(filteredImage->GetImaqImage(), horizontalReport->particleIndex, 0, IMAQ_MT_EQUIVALENT_RECT_SHORT_SIDE, &horizHeight);
							
							//Determine if the horizontal target is in the expected location to the left of the vertical target
							leftScore = ratioToScore(1.2*(verticalReport->boundingRect.left - horizontalReport->center_mass_x)/horizWidth);
							//Determine if the horizontal target is in the expected location to the right of the  vertical target
							rightScore = ratioToScore(1.2*(horizontalReport->center_mass_x - verticalReport->boundingRect.left - verticalReport->boundingRect.width)/horizWidth);
							//Determine if the width of the tape on the two targets appears to be the same
							tapeWidthScore = ratioToScore(vertWidth/horizHeight);
							//Determine if the vertical location of the horizontal target appears to be correct
							verticalScore = ratioToScore(1-(verticalReport->boundingRect.top - horizontalReport->center_mass_y)/(4*horizHeight));
							total = leftScore > rightScore ? leftScore:rightScore;
							total += tapeWidthScore + verticalScore;
							
							//If the target is the best detected so far store the information about it
							if(total > target.totalScore)
							{
								target.horizontalIndex = horizontalTargets[j];
								target.verticalIndex = verticalTargets[i];
								target.totalScore = total;
								target.leftScore = leftScore;
								target.rightScore = rightScore;
								target.tapeWidthScore = tapeWidthScore;
								target.verticalScore = verticalScore;
							}
						}
						//Determine if the best target is a Hot target
						target.Hot = hotOrNot(target);
					}
					
					if(verticalTargetCount > 0)
					{
						//Information about the target is contained in the "target" structure
						//To get measurement information such as sizes or locations use the
						//horizontal or vertical index to get the particle report as shown below
						ParticleAnalysisReport *distanceReport = &(reports->at(target.verticalIndex));
						double distance = computeDistance(filteredImage, distanceReport);
						if(target.Hot)
						{
							printf("Hot target located \n");
							printf("Distance: %f \n", distance);
							hotGoal = true;
						} else {
							printf("No hot target present \n");
							printf("Distance: %f \n", distance);
							hotGoal = false;
						}
					}
				}

				// be sure to delete images after using them
				delete filteredImage;
				delete thresholdImage;
				delete image;
				
				//delete allocated reports and Scores objects also
				delete scores;
				delete reports;
}