/** * Extract a color plane from the image. * * @param mode The ColorMode to use for the plane extraction * @param planeNumber Which plane is to be extracted * @return A pointer to a MonoImage that represents the extracted plane. */ MonoImage* ColorImage::ExtractColorPlane(ColorMode mode, int planeNumber) { auto result = new MonoImage(); if (m_imaqImage == nullptr) wpi_setWPIError(NullParameter); int success = imaqExtractColorPlanes( m_imaqImage, mode, (planeNumber == 1) ? result->GetImaqImage() : nullptr, (planeNumber == 2) ? result->GetImaqImage() : nullptr, (planeNumber == 3) ? result->GetImaqImage() : nullptr); wpi_setImaqErrorWithContext(success, "Imaq ExtractColorPlanes failed"); return result; }
/* * Applies a colour plane extraction operation to the source image. * * @param textOut Pointer to a 512-character buffer that is displayed beneath the processed image. */ Image* ColorPlaneExtraction::ProcessImage(Image* image, char* textOut) { Image* output = imaqCreateImage(IMAQ_IMAGE_U8, 3); // Extract the red plane only by setting the other two to NULL. imaqExtractColorPlanes(image, IMAQ_RGB, output, NULL, NULL); // No text to display. textOut[0] = 0; return output; }
/** * @brief Extracts the Red, Green, Blue, or Hue, Saturation or Luminance information from a color image. * Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64. * * @param image The source image that the function extracts the planes from. * @param mode The color space that the function extracts the planes from. Valid values are IMAQ_RGB, IMAQ_HSL, IMAQ_HSV, IMAQ_HSI. * @param plane1 On return, the first extracted plane. Set this parameter to NULL if you do not need this information. RGB-Red, HSL/HSV/HSI-Hue. * @param plane2 On return, the second extracted plane. Set this parameter to NULL if you do not need this information. RGB-Green, HSL/HSV/HSI-Saturation. * @param plane3 On return, the third extracted plane. Set this parameter to NULL if you do not need this information. RGB-Blue, HSL-Luminance, HSV-Value, HSI-Intensity. * * @return error code: 0 = error. To get extended error information, call GetLastError(). */ int frcExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1, Image* plane2, Image* plane3) { return imaqExtractColorPlanes(image, mode, plane1, plane2, plane3); }
bool Target::FindParticles() { printf("Target::FindParticles\n"); long then = (long) GetFPGATime(); // extract the blue plane if (!imaqExtractColorPlanes(m_cameraImage.GetImaqImage(), IMAQ_RGB, NULL, NULL, m_monoImage.GetImaqImage())) { printf("%s: imaqExtractColorPlanes FAILED\n", __FUNCTION__); return false; } // select interesting particles if (!imaqThreshold(m_threshold.GetImaqImage(), m_monoImage.GetImaqImage(), /*rangeMin*/ THRESHOLD, /*rangeMax*/ 255, /*useNewValue*/ 1, /*newValue */ 1)) { printf("%s: imaqThreshold FAILED\n", __FUNCTION__); return false; } if (!imaqConvexHull(m_convexHull.GetImaqImage(), m_threshold.GetImaqImage(), /*connectivity8*/ 1)) { printf("%s: imaqConvexHull FAILED\n", __FUNCTION__); return false; } if (!imaqSizeFilter(m_filtered.GetImaqImage(), m_convexHull.GetImaqImage(), /*connectivity8*/ 1, /*erosions*/ 2, /*keepSize*/ IMAQ_KEEP_LARGE, /*structuringElement*/ NULL)) { printf("%s: imaqSizeFilter FAILED\n", __FUNCTION__); return false; } int particleCount = 0; if (!imaqCountParticles(m_filtered.GetImaqImage(), 1, &particleCount)) { printf("%s: imaqCountParticles FAILED\n", __FUNCTION__); return false; } // select the four largest particles (insertion sort) // for now, keep track of only the particle number (index) and size memset((void *)m_particles, 0, sizeof m_particles); for (int i = 0; i < particleCount; i++) { double size; if (!imaqMeasureParticle(m_filtered.GetImaqImage(), i, FALSE, IMAQ_MT_PARTICLE_AND_HOLES_AREA, &size)) { printf("%s: imaqMeasureParticle %d FAILED\n", __FUNCTION__, i); break; } for (int j = 0; j < 4; j++) { if (size > m_particles[j].size) { for (int k = 3; k > j; k--) { m_particles[k].index = m_particles[k-1].index; m_particles[k].size = m_particles[k-1].size; } m_particles[j].index = i; m_particles[j].size = size; break; } } } // fill in the rest of the measured data for (m_numParticles = 0; m_numParticles < 4 && m_particles[m_numParticles].size > 0; m_numParticles++) { Particle* p = &m_particles[m_numParticles]; imaqMeasureParticle(m_filtered.GetImaqImage(), p->index, FALSE, IMAQ_MT_CENTER_OF_MASS_X, &(p->xCenter)); imaqMeasureParticle(m_filtered.GetImaqImage(), p->index, FALSE, IMAQ_MT_CENTER_OF_MASS_Y, &(p->yCenter)); imaqMeasureParticle(m_filtered.GetImaqImage(), p->index, FALSE, IMAQ_MT_BOUNDING_RECT_LEFT, &(p->leftBound)); imaqMeasureParticle(m_filtered.GetImaqImage(), p->index, FALSE, IMAQ_MT_BOUNDING_RECT_RIGHT, &(p->rightBound)); imaqMeasureParticle(m_filtered.GetImaqImage(), p->index, FALSE, IMAQ_MT_BOUNDING_RECT_TOP, &(p->topBound)); imaqMeasureParticle(m_filtered.GetImaqImage(), p->index, FALSE, IMAQ_MT_BOUNDING_RECT_BOTTOM, &(p->bottomBound)); // calculate height/width from bounding box p->height = p->bottomBound - p->topBound; p->width = p->rightBound - p->leftBound; } long now = (long) GetFPGATime(); printf("%s: particle detection took %ld microseconds\n", __FUNCTION__, (now - then)); printf("%s: found %d particles\n", __FUNCTION__, particleCount); printf("%s: returning %d particles\n", __FUNCTION__, m_numParticles); for (int i = 0; i < m_numParticles; i++) { Particle *p = &m_particles[i]; printf(" particle %d index %d top %g bottom %g left %g right %g size %g x %g y %g\n", i, p->index, p->topBound, p->bottomBound, p->leftBound, p->rightBound, p->size, p->xCenter, p->yCenter); } return true; }