int CVICALLBACK Thresholding (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { int threshold = 0; int histogram[256] = {0}; HistogramReport *report = NULL; switch (event) { case EVENT_COMMIT: GetCtrlVal (mypanel, MYPANEL_THRESHOLD_SLIDE, &threshold); imaqThreshold (destimage, sourimage, threshold, 255, TRUE, 255); imaqSetWindowTitle (1, "Picture after binaryzation"); imaqMoveWindow (1, imaqMakePoint (150, 260)); imaqDisplayImage (destimage, 1, TRUE); report = imaqHistogram (destimage, 256, 0, 255, IMAQ_IMAGE_U8); DeleteGraphPlot (mypanel, MYPANEL_MYGRAPH, -1, VAL_IMMEDIATE_DRAW); PlotY (mypanel, MYPANEL_MYGRAPH, (*report).histogram, 256, VAL_UNSIGNED_INTEGER, VAL_THIN_LINE, VAL_EMPTY_SQUARE, VAL_SOLID, 1, VAL_RED); break; } return 0; }
/** * @brief Converts a grayscale image to a binary image for Particle Analysis based on a fixed threshold. * The function sets pixels values outside of the given range to 0. The function sets * pixel values within the range to the given value. * Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16. * * @param dest The destination image. * @param source The image to threshold * @param rangeMin The lower boundary of the range of pixel values to keep * @param rangeMax The upper boundary of the range of pixel values to keep. * @param newValue The replacement value for pixels within the range. Use the simplified call to leave the pixel values unchanged * * @return int - error code: 0 = error. To get extended error information, call GetLastError(). */ int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax, float newValue) { int useNewValue = TRUE; return imaqThreshold(dest, source, rangeMin, rangeMax, useNewValue, newValue); }
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; }