Permalink
Fetching contributors…
Cannot retrieve contributors at this time
549 lines (458 sloc) 20.7 KB
//**************************************************************************
//* WARNING: This file was automatically generated. Any changes you make *
//* to this file will be lost if you generate the file again. *
//**************************************************************************
#include <nivision.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#pragma GCC diagnostic ignored "-Wformat-zero-length"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#define BOOL int
// If you call Machine Vision functions in your script, add NIMachineVision.c to the project.
#define IVA_MAX_BUFFERS 20
#define IVA_STORE_RESULT_NAMES
#define VisionErrChk(Function) {if (!(Function)) {success = 0; goto Error;}}
typedef enum IVA_ResultType_Enum {IVA_NUMERIC, IVA_BOOLEAN, IVA_STRING} IVA_ResultType;
typedef union IVA_ResultValue_Struct // A result in Vision Assistant can be of type double, BOOL or string.
{
double numVal;
BOOL boolVal;
char* strVal;
} IVA_ResultValue;
typedef struct IVA_Result_Struct
{
#if defined (IVA_STORE_RESULT_NAMES)
char resultName[256]; // Result name
#endif
IVA_ResultType type; // Result type
IVA_ResultValue resultVal; // Result value
} IVA_Result;
typedef struct IVA_StepResultsStruct
{
#if defined (IVA_STORE_RESULT_NAMES)
char stepName[256]; // Step name
#endif
int numResults; // number of results created by the step
IVA_Result* results; // array of results
} IVA_StepResults;
typedef struct IVA_Data_Struct
{
Image* buffers[IVA_MAX_BUFFERS]; // Vision Assistant Image Buffers
IVA_StepResults* stepResults; // Array of step results
int numSteps; // Number of steps allocated in the stepResults array
CoordinateSystem *baseCoordinateSystems; // Base Coordinate Systems
CoordinateSystem *MeasurementSystems; // Measurement Coordinate Systems
int numCoordSys; // Number of coordinate systems
} IVA_Data;
static IVA_Data* IVA_InitData(int numSteps, int numCoordSys);
static int IVA_DisposeData(IVA_Data* ivaData);
static int IVA_DisposeStepResults(IVA_Data* ivaData, int stepIndex);
static int IVA_CLRThreshold(Image* image, int min1, int max1, int min2, int max2, int min3, int max3, int colorMode);
static int IVA_ParticleFilter(Image* image,
int pParameter[],
float plower[],
float pUpper[],
int pCalibrated[],
int pExclude[],
int criteriaCount,
int rejectMatches,
int connectivity);
static int IVA_Particle(Image* image,
int connectivity,
int pPixelMeasurements[],
int numPixelMeasurements,
int pCalibratedMeasurements[],
int numCalibratedMeasurements,
IVA_Data* ivaData,
int stepIndex);
int IVA_ProcessImage(Image *image)
{
int success = 1;
IVA_Data *ivaData;
int pParameter[1] = {20};
float plower[1] = {50}; // 50
float pUpper[1] = {1500};
int pCalibrated[1] = {0};
int pExclude[1] = {0};
int pKernel[9] = {0,1,0,1,1,1,0,1,0};
StructuringElement structElem;
int pPixelMeasurements[3] = {26,27,51};
int *pCalibratedMeasurements = 0;
ImageType imageType;
// printf("Init\n");
// Initializes internal data (buffers and array of points for caliper measurements)
VisionErrChk(ivaData = IVA_InitData(7, 0));
// printf("Threshold\n");
VisionErrChk(IVA_CLRThreshold(image, 104, 136, 119, 255, 35, 155,
IMAQ_HSI));
//-------------------------------------------------------------------//
// Advanced Morphology: Fill Holes //
//-------------------------------------------------------------------//
// printf("Fill holes\n");
// Fills holes in particles.
VisionErrChk(imaqFillHoles(image, image, FALSE));
// printf("Particle filter\n");
VisionErrChk(IVA_ParticleFilter(image, pParameter, plower, pUpper,
pCalibrated, pExclude, 1, FALSE, TRUE));
//-------------------------------------------------------------------//
// Basic Morphology //
//-------------------------------------------------------------------//
// Sets the structuring element.
structElem.matrixCols = 3;
structElem.matrixRows = 3;
structElem.hexa = FALSE;
structElem.kernel = pKernel;
// printf("Morphology\n");
// Applies a morphological transformation to the binary image.
VisionErrChk(imaqMorphology(image, image, IMAQ_DILATE, &structElem));
// printf("Particle count\n");
VisionErrChk(IVA_Particle(image, TRUE, pPixelMeasurements, 3,
pCalibratedMeasurements, 0, ivaData, 5));
// printf("Equalize\n");
//-------------------------------------------------------------------//
// Lookup Table: Equalize //
//-------------------------------------------------------------------//
// Calculates the histogram of the image and redistributes pixel values across
// the desired range to maintain the same pixel value distribution.
VisionErrChk(imaqGetImageType(image, &imageType));
VisionErrChk(imaqEqualize(image, image, 0, (imageType == IMAQ_IMAGE_U8 ? 255 : 0), NULL));
// printf("Dispose\n");
// Releases the memory allocated in the IVA_Data structure.
IVA_DisposeData(ivaData);
Error:
return success;
}
////////////////////////////////////////////////////////////////////////////////
//
// 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;
int err_code = 0;
//-------------------------------------------------------------------//
// Color Threshold //
//-------------------------------------------------------------------//
// printf("Creating new image\n");
// 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;
// printf("Thresholding\n");
// Thresholds the color image.
VisionErrChk(err_code = imaqColorThreshold(thresholdImage, image, 1, colorMode, &plane1Range, &plane2Range, &plane3Range));
// printf("Duplicating\n");
// Copies the threshold image in the souce image.
VisionErrChk(imaqDuplicate(image, thresholdImage));
Error:
// printf("threshold err_code %d\n", err_code);
// int imaqErr = imaqGetLastError();
// printf("last err code %d\n", imaqErr);
imaqDispose(thresholdImage);
return success;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function Name: IVA_ParticleFilter
//
// Description : Filters particles based on their morphological measurements.
//
// Parameters : image - Input image
// pParameter - Morphological measurement that the function
// uses for filtering.
// plower - Lower bound of the criteria range.
// pUpper - Upper bound of the criteria range.
// pCalibrated - Whether to take a calibrated measurement or not.
// pExclude - TRUE indicates that a match occurs when the
// value is outside the criteria range.
// criteriaCount - number of particle filter criteria.
// rejectMatches - Set this parameter to TRUE to transfer only
// those particles that do not meet all the criteria.
// Set this parameter to FALSE to transfer only those
// particles that meet all the criteria to the destination.
// connectivity - Set this parameter to 1 to use connectivity-8
// to determine whether particles are touching.
// Set this parameter to 0 to use connectivity-4
// to determine whether particles are touching.
//
// Return Value : success
//
////////////////////////////////////////////////////////////////////////////////
static int IVA_ParticleFilter(Image* image,
int pParameter[],
float plower[],
float pUpper[],
int pCalibrated[],
int pExclude[],
int criteriaCount,
int rejectMatches,
int connectivity)
{
int success = 1;
ParticleFilterCriteria2* particleCriteria = NULL;
int i;
ParticleFilterOptions particleFilterOptions;
int numParticles;
//-------------------------------------------------------------------//
// Particle Filter //
//-------------------------------------------------------------------//
if (criteriaCount > 0)
{
// Fill in the ParticleFilterCriteria2 structure.
particleCriteria = (ParticleFilterCriteria2*)malloc(criteriaCount * sizeof(ParticleFilterCriteria2));
for (i = 0 ; i < criteriaCount ; i++)
{
particleCriteria[i].parameter = pParameter[i];
particleCriteria[i].lower = plower[i];
particleCriteria[i].upper = pUpper[i];
particleCriteria[i].calibrated = pCalibrated[i];
particleCriteria[i].exclude = pExclude[i];
}
particleFilterOptions.rejectMatches = rejectMatches;
particleFilterOptions.rejectBorder = 0;
particleFilterOptions.connectivity8 = connectivity;
// Filters particles based on their morphological measurements.
VisionErrChk(imaqParticleFilter3(image, image, particleCriteria, criteriaCount, &particleFilterOptions, NULL, &numParticles));
}
Error:
free(particleCriteria);
return success;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function Name: IVA_Particle
//
// Description : Computes the number of particles detected in a binary image and
// a 2D array of requested measurements about the particle.
//
// Parameters : image - Input image
// connectivity - Set this parameter to 1 to use
// connectivity-8 to determine
// whether particles are touching.
// Set this parameter to 0 to use
// connectivity-4 to determine
// whether particles are touching.
// pixelMeasurements - Array of measuremnets parameters
// numPixelMeasurements - Number of elements in the array
// calibratedMeasurements - Array of measuremnets parameters
// numCalibratedMeasurements - Number of elements in the array
// ivaData - Internal Data structure
// stepIndex - Step index (index at which to store
// the results in the resuts array)
//
// Return Value : success
//
////////////////////////////////////////////////////////////////////////////////
static int IVA_Particle(Image* image,
int connectivity,
int pPixelMeasurements[],
int numPixelMeasurements,
int pCalibratedMeasurements[],
int numCalibratedMeasurements,
IVA_Data* ivaData,
int stepIndex)
{
int success = 1;
int numParticles;
double* pixelMeasurements = NULL;
double* calibratedMeasurements = NULL;
unsigned int visionInfo;
IVA_Result* particleResults;
int i;
int j;
double centerOfMassX;
double centerOfMassY;
//-------------------------------------------------------------------//
// Particle Analysis //
//-------------------------------------------------------------------//
// Counts the number of particles in the image.
VisionErrChk(imaqCountParticles(image, connectivity, &numParticles));
// Allocate the arrays for the measurements.
pixelMeasurements = (double*)malloc(numParticles * numPixelMeasurements * sizeof(double));
calibratedMeasurements = (double*)malloc(numParticles * numCalibratedMeasurements * sizeof(double));
// Delete all the results of this step (from a previous iteration)
IVA_DisposeStepResults(ivaData, stepIndex);
// Check if the image is calibrated.
VisionErrChk(imaqGetVisionInfoTypes(image, &visionInfo));
// If the image is calibrated, we also need to log the calibrated position (x and y)
ivaData->stepResults[stepIndex].numResults = (visionInfo & IMAQ_VISIONINFO_CALIBRATION ?
numParticles * 4 + 1 : numParticles * 2 + 1);
ivaData->stepResults[stepIndex].results = malloc (sizeof(IVA_Result) * ivaData->stepResults[stepIndex].numResults);
particleResults = ivaData->stepResults[stepIndex].results;
#if defined (IVA_STORE_RESULT_NAMES)
sprintf(particleResults->resultName, "Object #");
#endif
particleResults->type = IVA_NUMERIC;
particleResults->resultVal.numVal = numParticles;
particleResults++;
for (i = 0 ; i < numParticles ; i++)
{
// Computes the requested pixel measurements about the particle.
for (j = 0 ; j < numPixelMeasurements ; j++)
{
VisionErrChk(imaqMeasureParticle(image, i, FALSE, pPixelMeasurements[j], &pixelMeasurements[i*numPixelMeasurements + j]));
}
// Computes the requested calibrated measurements about the particle.
for (j = 0 ; j < numCalibratedMeasurements ; j++)
{
VisionErrChk(imaqMeasureParticle(image, i, TRUE, pCalibratedMeasurements[j], &calibratedMeasurements[i*numCalibratedMeasurements + j]));
}
#if defined (IVA_STORE_RESULT_NAMES)
sprintf(particleResults->resultName, "Particle %d.X Position (Pix.)", i + 1);
#endif
particleResults->type = IVA_NUMERIC;
VisionErrChk(imaqMeasureParticle(image, i, FALSE, IMAQ_MT_CENTER_OF_MASS_X, &centerOfMassX));
particleResults->resultVal.numVal = centerOfMassX;
particleResults++;
#if defined (IVA_STORE_RESULT_NAMES)
sprintf(particleResults->resultName, "Particle %d.Y Position (Pix.)", i + 1);
#endif
particleResults->type = IVA_NUMERIC;
VisionErrChk(imaqMeasureParticle(image, i, FALSE, IMAQ_MT_CENTER_OF_MASS_Y, &centerOfMassY));
particleResults->resultVal.numVal = centerOfMassY;
particleResults++;
if (visionInfo & IMAQ_VISIONINFO_CALIBRATION)
{
#if defined (IVA_STORE_RESULT_NAMES)
sprintf(particleResults->resultName, "Particle %d.X Position (Calibrated)", i + 1);
#endif
particleResults->type = IVA_NUMERIC;
VisionErrChk(imaqMeasureParticle(image, i, TRUE, IMAQ_MT_CENTER_OF_MASS_X, &centerOfMassX));
particleResults->resultVal.numVal = centerOfMassX;
particleResults++;
#if defined (IVA_STORE_RESULT_NAMES)
sprintf(particleResults->resultName, "Particle %d.Y Position (Calibrated)", i + 1);
#endif
particleResults->type = IVA_NUMERIC;
VisionErrChk(imaqMeasureParticle(image, i, TRUE, IMAQ_MT_CENTER_OF_MASS_Y, &centerOfMassY));
particleResults->resultVal.numVal = centerOfMassY;
particleResults++;
}
}
Error:
free(pixelMeasurements);
free(calibratedMeasurements);
return success;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function Name: IVA_InitData
//
// Description : Initializes data for buffer management and results.
//
// Parameters : # of steps
// # of coordinate systems
//
// Return Value : success
//
////////////////////////////////////////////////////////////////////////////////
static IVA_Data* IVA_InitData(int numSteps, int numCoordSys)
{
int success = 1;
IVA_Data* ivaData = NULL;
int i;
// Allocate the data structure.
VisionErrChk(ivaData = (IVA_Data*)malloc(sizeof (IVA_Data)));
// Initializes the image pointers to NULL.
for (i = 0 ; i < IVA_MAX_BUFFERS ; i++)
ivaData->buffers[i] = NULL;
// Initializes the steo results array to numSteps elements.
ivaData->numSteps = numSteps;
ivaData->stepResults = (IVA_StepResults*)malloc(ivaData->numSteps * sizeof(IVA_StepResults));
for (i = 0 ; i < numSteps ; i++)
{
#if defined (IVA_STORE_RESULT_NAMES)
sprintf(ivaData->stepResults[i].stepName, "");
#endif
ivaData->stepResults[i].numResults = 0;
ivaData->stepResults[i].results = NULL;
}
// Create the coordinate systems
ivaData->baseCoordinateSystems = NULL;
ivaData->MeasurementSystems = NULL;
if (numCoordSys)
{
ivaData->baseCoordinateSystems = (CoordinateSystem*)malloc(sizeof(CoordinateSystem) * numCoordSys);
ivaData->MeasurementSystems = (CoordinateSystem*)malloc(sizeof(CoordinateSystem) * numCoordSys);
}
ivaData->numCoordSys = numCoordSys;
Error:
return ivaData;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function Name: IVA_DisposeData
//
// Description : Releases the memory allocated in the IVA_Data structure
//
// Parameters : ivaData - Internal data structure
//
// Return Value : success
//
////////////////////////////////////////////////////////////////////////////////
static int IVA_DisposeData(IVA_Data* ivaData)
{
int i;
// Releases the memory allocated for the image buffers.
for (i = 0 ; i < IVA_MAX_BUFFERS ; i++)
imaqDispose(ivaData->buffers[i]);
// Releases the memory allocated for the array of measurements.
for (i = 0 ; i < ivaData->numSteps ; i++)
IVA_DisposeStepResults(ivaData, i);
free(ivaData->stepResults);
// Dispose of coordinate systems
if (ivaData->numCoordSys)
{
free(ivaData->baseCoordinateSystems);
free(ivaData->MeasurementSystems);
}
free(ivaData);
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
//
// Function Name: IVA_DisposeStepResults
//
// Description : Dispose of the results of a specific step.
//
// Parameters : ivaData - Internal data structure
// stepIndex - step index
//
// Return Value : success
//
////////////////////////////////////////////////////////////////////////////////
static int IVA_DisposeStepResults(IVA_Data* ivaData, int stepIndex)
{
int i;
for (i = 0 ; i < ivaData->stepResults[stepIndex].numResults ; i++)
{
if (ivaData->stepResults[stepIndex].results[i].type == IVA_STRING)
free(ivaData->stepResults[stepIndex].results[i].resultVal.strVal);
}
free(ivaData->stepResults[stepIndex].results);
return TRUE;
}