From 53473e21bea9df4cdb4be7492cdded8969076e03 Mon Sep 17 00:00:00 2001 From: Thomas Clark Date: Tue, 23 Dec 2014 15:55:36 -0500 Subject: [PATCH] Add the 2014 C++ vision classes back in Most of the old vision code still compiles with minimal changes. I haven't tested it extensively, since the AxisCamera class isn't done, but it should work, as it was barely modified. Java bindings are still TODO, since they used some JNA stuff that probably won't work now. Change-Id: I8edf991410cb30b932379f277cee9d329ee35009 --- .../include/Vision/BaeUtilities.h | 57 + .../include/Vision/BinaryImage.h | 39 + .../include/Vision/ColorImage.h | 65 + .../include/Vision/FrcError.h | 30 + .../include/Vision/HSLImage.h | 22 + .../include/Vision/ImageBase.h | 27 + .../include/Vision/MonoImage.h | 25 + .../include/Vision/RGBImage.h | 21 + .../include/Vision/Threshold.h | 28 + .../include/Vision/VisionAPI.h | 148 ++ wpilibc/wpilibC++Devices/include/WPILib.h | 7 + .../src/Vision/BaeUtilities.cpp | 385 ++++++ .../src/Vision/BinaryImage.cpp | 222 +++ .../src/Vision/ColorImage.cpp | 465 +++++++ .../wpilibC++Devices/src/Vision/FrcError.cpp | 1227 +++++++++++++++++ .../wpilibC++Devices/src/Vision/HSLImage.cpp | 28 + .../wpilibC++Devices/src/Vision/ImageBase.cpp | 73 + .../wpilibC++Devices/src/Vision/MonoImage.cpp | 55 + .../wpilibC++Devices/src/Vision/RGBImage.cpp | 28 + .../wpilibC++Devices/src/Vision/Threshold.cpp | 18 + .../wpilibC++Devices/src/Vision/VisionAPI.cpp | 665 +++++++++ 21 files changed, 3635 insertions(+) create mode 100644 wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/ColorImage.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/FrcError.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/HSLImage.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/ImageBase.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/MonoImage.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/RGBImage.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/Threshold.h create mode 100644 wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h create mode 100644 wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/BinaryImage.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp create mode 100644 wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp diff --git a/wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h b/wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h new file mode 100644 index 0000000000..a684b0785b --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/BaeUtilities.h @@ -0,0 +1,57 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +/* Constants */ +#define LOG_DEBUG __FILE__,__FUNCTION__,__LINE__,DEBUG_TYPE +#define LOG_INFO __FILE__,__FUNCTION__,__LINE__,INFO_TYPE +#define LOG_ERROR __FILE__,__FUNCTION__,__LINE__,ERROR_TYPE +#define LOG_CRITICAL __FILE__,__FUNCTION__,__LINE__,CRITICAL_TYPE +#define LOG_FATAL __FILE__,__FUNCTION__,__LINE__,FATAL_TYPE +#define LOG_DEBUG __FILE__,__FUNCTION__,__LINE__,DEBUG_TYPE + +/* Enumerated Types */ + +/** debug levels */ +enum dprint_type {DEBUG_TYPE, INFO_TYPE, ERROR_TYPE, CRITICAL_TYPE, FATAL_TYPE}; + +/** debug output setting */ +typedef enum DebugOutputType_enum { + DEBUG_OFF, DEBUG_MOSTLY_OFF, DEBUG_SCREEN_ONLY, DEBUG_FILE_ONLY, DEBUG_SCREEN_AND_FILE +}DebugOutputType; + +/* Enumerated Types */ + +/* Utility functions */ + +/* debug */ +void SetDebugFlag ( DebugOutputType flag ); +void dprintf ( const char * tempString, ... ); /* Variable argument list */ + +/* set FRC ranges for drive */ +double RangeToNormalized(double pixel, int range); +/* change normalized value to any range - used for servo */ +float NormalizeToRange(float normalizedValue, float minRange, float maxRange); +float NormalizeToRange(float normalizedValue); + +/* system utilities */ +void ShowActivity (char *fmt, ...); +double ElapsedTime (double startTime); + +/* servo panning utilities */ +class Servo; +double SinPosition (double *period, double sinStart); +void panInit(); +void panInit(double period); +void panForTarget(Servo *panServo); +void panForTarget(Servo *panServo, double sinStart); + +/* config file read utilities */ +int processFile(char *inputFile, char *outputString, int lineNumber); +int emptyString(char *string); +void stripString(char *string); + diff --git a/wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h b/wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h new file mode 100644 index 0000000000..7c33f54cb2 --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/BinaryImage.h @@ -0,0 +1,39 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "MonoImage.h" +/** + * Included for ParticleAnalysisReport definition + * TODO: Eliminate this dependency! + */ +#include "Vision/VisionAPI.h" + +#include +#include + +class BinaryImage : public MonoImage +{ +public: + BinaryImage(); + virtual ~BinaryImage(); + int GetNumberParticles(); + ParticleAnalysisReport GetParticleAnalysisReport(int particleNumber); + void GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par); + std::vector* GetOrderedParticleAnalysisReports(); + BinaryImage *RemoveSmallObjects(bool connectivity8, int erosions); + BinaryImage *RemoveLargeObjects(bool connectivity8, int erosions); + BinaryImage *ConvexHull(bool connectivity8); + BinaryImage *ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount); + virtual void Write(const char *fileName); +private: + bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result); + bool ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result); + static double NormalizeFromRange(double position, int range); + static bool CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2); +}; + diff --git a/wpilibc/wpilibC++Devices/include/Vision/ColorImage.h b/wpilibc/wpilibC++Devices/include/Vision/ColorImage.h new file mode 100644 index 0000000000..595ed83ca5 --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/ColorImage.h @@ -0,0 +1,65 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "ImageBase.h" +#include "BinaryImage.h" +#include "Threshold.h" + +class ColorImage : public ImageBase +{ +public: + ColorImage(ImageType type); + virtual ~ColorImage(); + BinaryImage *ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh); + BinaryImage *ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh); + BinaryImage *ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueHigh, int valueLow); + BinaryImage *ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh); + BinaryImage *ThresholdRGB(Threshold &threshold); + BinaryImage *ThresholdHSL(Threshold &threshold); + BinaryImage *ThresholdHSV(Threshold &threshold); + BinaryImage *ThresholdHSI(Threshold &threshold); + MonoImage *GetRedPlane(); + MonoImage *GetGreenPlane(); + MonoImage *GetBluePlane(); + MonoImage *GetHSLHuePlane(); + MonoImage *GetHSVHuePlane(); + MonoImage *GetHSIHuePlane(); + MonoImage *GetHSLSaturationPlane(); + MonoImage *GetHSVSaturationPlane(); + MonoImage *GetHSISaturationPlane(); + MonoImage *GetLuminancePlane(); + MonoImage *GetValuePlane(); + MonoImage *GetIntensityPlane(); + void ReplaceRedPlane(MonoImage *plane); + void ReplaceGreenPlane(MonoImage *plane); + void ReplaceBluePlane(MonoImage *plane); + void ReplaceHSLHuePlane(MonoImage *plane); + void ReplaceHSVHuePlane(MonoImage *plane); + void ReplaceHSIHuePlane(MonoImage *plane); + void ReplaceHSLSaturationPlane(MonoImage *plane); + void ReplaceHSVSaturationPlane(MonoImage *plane); + void ReplaceHSISaturationPlane(MonoImage *plane); + void ReplaceLuminancePlane(MonoImage *plane); + void ReplaceValuePlane(MonoImage *plane); + void ReplaceIntensityPlane(MonoImage *plane); + void ColorEqualize(); + void LuminanceEqualize(); + +private: + BinaryImage *ComputeThreshold(ColorMode colorMode, int low1, int high1, int low2, int high2, int low3, int high3); + void Equalize(bool allPlanes); + MonoImage * ExtractColorPlane(ColorMode mode, int planeNumber); + MonoImage * ExtractFirstColorPlane(ColorMode mode); + MonoImage * ExtractSecondColorPlane(ColorMode mode); + MonoImage * ExtractThirdColorPlane(ColorMode mode); + void ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber); + void ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane); + void ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane); + void ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane); +}; + diff --git a/wpilibc/wpilibC++Devices/include/Vision/FrcError.h b/wpilibc/wpilibC++Devices/include/Vision/FrcError.h new file mode 100644 index 0000000000..9bd47f49f5 --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/FrcError.h @@ -0,0 +1,30 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +/* Error Codes */ +#define ERR_VISION_GENERAL_ERROR 166000 // +#define ERR_COLOR_NOT_FOUND 166100 // TrackAPI.cpp +#define ERR_PARTICLE_TOO_SMALL 166101 // TrackAPI.cpp + +#define ERR_CAMERA_FAILURE 166200 // AxisCamera.cpp +#define ERR_CAMERA_SOCKET_CREATE_FAILED 166201 // AxisCamera.cpp +#define ERR_CAMERA_CONNECT_FAILED 166202 // AxisCamera.cpp +#define ERR_CAMERA_STALE_IMAGE 166203 // AxisCamera.cpp +#define ERR_CAMERA_NOT_INITIALIZED 166204 // AxisCamera.cpp +#define ERR_CAMERA_NO_BUFFER_AVAILABLE 166205 // AxisCamera.cpp +#define ERR_CAMERA_HEADER_ERROR 166206 // AxisCamera.cpp +#define ERR_CAMERA_BLOCKING_TIMEOUT 166207 // AxisCamera.cpp +#define ERR_CAMERA_AUTHORIZATION_FAILED 166208 // AxisCamera.cpp +#define ERR_CAMERA_TASK_SPAWN_FAILED 166209 // AxisCamera.cpp +#define ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE 166210 // AxisCamera.cpp +#define ERR_CAMERA_COMMAND_FAILURE 166211 // AxisCamera.cpp + +/* error handling functions */ +int GetLastVisionError(); +const char* GetVisionErrorText(int errorCode); + diff --git a/wpilibc/wpilibC++Devices/include/Vision/HSLImage.h b/wpilibc/wpilibC++Devices/include/Vision/HSLImage.h new file mode 100644 index 0000000000..71428aa7ee --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/HSLImage.h @@ -0,0 +1,22 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "ColorImage.h" + +/** + * A color image represented in HSL color space at 3 bytes per pixel. + */ +class HSLImage : public ColorImage +{ +public: + HSLImage(); + HSLImage(const char *fileName); + virtual ~HSLImage(); +}; + + diff --git a/wpilibc/wpilibC++Devices/include/Vision/ImageBase.h b/wpilibc/wpilibC++Devices/include/Vision/ImageBase.h new file mode 100644 index 0000000000..ee5e895f3d --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/ImageBase.h @@ -0,0 +1,27 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include "nivision.h" +#include "ErrorBase.h" + +#define DEFAULT_BORDER_SIZE 3 + +class ImageBase : public ErrorBase +{ +public: + ImageBase(ImageType type); + virtual ~ImageBase(); + virtual void Write(const char *fileName); + int GetHeight(); + int GetWidth(); + Image *GetImaqImage(); +protected: + Image *m_imaqImage; +}; + diff --git a/wpilibc/wpilibC++Devices/include/Vision/MonoImage.h b/wpilibc/wpilibC++Devices/include/Vision/MonoImage.h new file mode 100644 index 0000000000..e0e35eba2d --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/MonoImage.h @@ -0,0 +1,25 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "ImageBase.h" + +#include + +class MonoImage : public ImageBase +{ +public: + MonoImage(); + virtual ~MonoImage(); + + std::vector *DetectEllipses(EllipseDescriptor *ellipseDescriptor, + CurveOptions *curveOptions, + ShapeDetectionOptions *shapeDetectionOptions, + ROI *roi); + std::vector * DetectEllipses(EllipseDescriptor *ellipseDescriptor); +}; + diff --git a/wpilibc/wpilibC++Devices/include/Vision/RGBImage.h b/wpilibc/wpilibC++Devices/include/Vision/RGBImage.h new file mode 100644 index 0000000000..0ef2d722bb --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/RGBImage.h @@ -0,0 +1,21 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "ColorImage.h" + +/** + * A color image represented in RGB color space at 3 bytes per pixel. + */ +class RGBImage : public ColorImage +{ +public: + RGBImage(); + RGBImage(const char *fileName); + virtual ~RGBImage(); +}; + diff --git a/wpilibc/wpilibC++Devices/include/Vision/Threshold.h b/wpilibc/wpilibC++Devices/include/Vision/Threshold.h new file mode 100644 index 0000000000..9070cbfee3 --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/Threshold.h @@ -0,0 +1,28 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +/** + * Color threshold values. + * This object represnts the threshold values for any type of color object + * that is used in a threshhold operation. It simplifies passing values + * around in a program for color detection. + */ +class Threshold +{ +public: + int plane1Low; + int plane1High; + int plane2Low; + int plane2High; + int plane3Low; + int plane3High; + Threshold(int plane1Low, int plane1High, + int plane2Low, int plane2High, + int plane3Low, int plane3High); +}; + diff --git a/wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h b/wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h new file mode 100644 index 0000000000..ce291bf734 --- /dev/null +++ b/wpilibc/wpilibC++Devices/include/Vision/VisionAPI.h @@ -0,0 +1,148 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "nivision.h" + +/* Constants */ + +#define DEFAULT_BORDER_SIZE 3 //VisionAPI.frcCreateImage +#define DEFAULT_SATURATION_THRESHOLD 40 //TrackAPI.FindColor + +/* Forward Declare Data Structures */ +typedef struct FindEdgeOptions_struct FindEdgeOptions; +typedef struct CircularEdgeReport_struct CircularEdgeReport; + +/* Data Structures */ + +/** frcParticleAnalysis returns this structure */ +typedef struct ParticleAnalysisReport_struct { + int imageHeight; + int imageWidth; + double imageTimestamp; + int particleIndex; // the particle index analyzed + /* X-coordinate of the point representing the average position of the + * total particle mass, assuming every point in the particle has a constant density */ + int center_mass_x; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_X + /* Y-coordinate of the point representing the average position of the + * total particle mass, assuming every point in the particle has a constant density */ + int center_mass_y; // MeasurementType: IMAQ_MT_CENTER_OF_MASS_Y + double center_mass_x_normalized; //Center of mass x value normalized to -1.0 to +1.0 range + double center_mass_y_normalized; //Center of mass y value normalized to -1.0 to +1.0 range + /* Area of the particle */ + double particleArea; // MeasurementType: IMAQ_MT_AREA + /* Bounding Rectangle */ + Rect boundingRect; // left/top/width/height + /* Percentage of the particle Area covering the Image Area. */ + double particleToImagePercent; // MeasurementType: IMAQ_MT_AREA_BY_IMAGE_AREA + /* Percentage of the particle Area in relation to its Particle and Holes Area */ + double particleQuality; // MeasurementType: IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA +} ParticleAnalysisReport; + +/** Tracking functions return this structure */ +typedef struct ColorReport_struct { + int numberParticlesFound; // Number of particles found for this color + int largestParticleNumber; // The particle index of the largest particle + /* Color information */ + float particleHueMax; // HistogramReport: hue max + float particleHueMin; // HistogramReport: hue max + float particleHueMean; // HistogramReport: hue mean + float particleSatMax; // HistogramReport: saturation max + float particleSatMin; // HistogramReport: saturation max + float particleSatMean; // HistogramReport: saturation mean + float particleLumMax; // HistogramReport: luminance max + float particleLumMin; // HistogramReport: luminance max + float particleLumMean; // HistogramReport: luminance mean +} ColorReport; + + +/* Image Management functions */ + +/* Create: calls imaqCreateImage. Border size is set to some default value */ +Image* frcCreateImage( ImageType type ); + +/* Dispose: calls imaqDispose */ +int frcDispose( void* object ); +int frcDispose( const char* filename, ... ) ; + +/* Copy: calls imaqDuplicateImage */ +int frcCopyImage( Image* dest, const Image* source ); + +/* Image Extraction: Crop: calls imaqScale */ +int frcCrop( Image* dest, const Image* source, Rect rect ); + +/* Image Extraction: Scale: calls imaqScale. Scales entire image */ +int frcScale(Image* dest, const Image* source, int xScale, int yScale, ScalingMode scaleMode ); + +/* Read Image : calls imaqReadFile */ +int frcReadImage( Image* image, const char* fileName ); +/* Write Image : calls imaqWriteFile */ +int frcWriteImage( const Image* image, const char* fileName); + +/* Measure Intensity functions */ + +/* Histogram: calls imaqHistogram */ +HistogramReport* frcHistogram( const Image* image, int numClasses, float min, float max, Rect rect ); +/* Color Histogram: calls imaqColorHistogram2 */ +ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode, Image* mask); + +/* Get Pixel Value: calls imaqGetPixel */ +int frcGetPixelValue( const Image* image, Point pixel, PixelValue* value ); + +/* Particle Analysis functions */ + +/* Particle Filter: calls imaqParticleFilter3 */ +int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, + int criteriaCount, const ParticleFilterOptions* options, Rect rect, int* numParticles); +int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, + int criteriaCount, const ParticleFilterOptions* options, int* numParticles); +/* Morphology: calls imaqMorphology */ +int frcMorphology(Image* dest, Image* source, MorphologyMethod method); +int frcMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement); +/* Reject Border: calls imaqRejectBorder */ +int frcRejectBorder(Image* dest, Image* source); +int frcRejectBorder(Image* dest, Image* source, int connectivity8); +/* Count Particles: calls imaqCountParticles */ +int frcCountParticles(Image* image, int* numParticles); +/* Particle Analysis Report: calls imaqMeasureParticle */ +int frcParticleAnalysis(Image* image, int particleNumber, ParticleAnalysisReport* par); + +/* Image Enhancement functions */ + +/* Equalize: calls imaqEqualize */ +int frcEqualize(Image* dest, const Image* source, float min, float max); +int frcEqualize(Image* dest, const Image* source, float min, float max, const Image* mask); + +/* Color Equalize: calls imaqColorEqualize */ +int frcColorEqualize(Image* dest, const Image* source); +int frcColorEqualize(Image* dest, const Image* source, int colorEqualization); + +/* Image Thresholding & Conversion functions */ + +/* Smart Threshold: calls imaqLocalThreshold */ +int frcSmartThreshold(Image* dest, const Image* source, unsigned int windowWidth, unsigned int windowHeight, + LocalThresholdMethod method, double deviationWeight, ObjectType type); +int frcSmartThreshold(Image* dest, const Image* source, unsigned int windowWidth, unsigned int windowHeight, + LocalThresholdMethod method, double deviationWeight, ObjectType type, float replaceValue); + +/* Simple Threshold: calls imaqThreshold */ +int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax, float newValue); +int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax); + +/* Color/Hue Threshold: calls imaqColorThreshold */ +int frcColorThreshold(Image* dest, const Image* source, ColorMode mode, + const Range* plane1Range, const Range* plane2Range, const Range* plane3Range); +int frcColorThreshold(Image* dest, const Image* source, int replaceValue, ColorMode mode, + const Range* plane1Range, const Range* plane2Range, const Range* plane3Range); +int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange); +int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange, int minSaturation); + +/* Extract ColorHue Plane: calls imaqExtractColorPlanes */ +int frcExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1, Image* plane2, Image* plane3); +int frcExtractHuePlane(const Image* image, Image* huePlane); +int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation); + diff --git a/wpilibc/wpilibC++Devices/include/WPILib.h b/wpilibc/wpilibC++Devices/include/WPILib.h index d02720efad..f72b0ebc1c 100644 --- a/wpilibc/wpilibC++Devices/include/WPILib.h +++ b/wpilibc/wpilibC++Devices/include/WPILib.h @@ -85,5 +85,12 @@ #include "Utility.h" #include "Victor.h" #include "VictorSP.h" +#include "Vision/BinaryImage.h" +#include "Vision/ColorImage.h" +#include "Vision/HSLImage.h" +#include "Vision/ImageBase.h" +#include "Vision/MonoImage.h" +#include "Vision/RGBImage.h" +#include "Vision/Threshold.h" // XXX: #include "Vision/AxisCamera.h" #include "WPIErrors.h" diff --git a/wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp b/wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp new file mode 100644 index 0000000000..8804411aad --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/BaeUtilities.cpp @@ -0,0 +1,385 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Vision/BaeUtilities.h" +#include "Servo.h" +#include "Timer.h" + +/** + * Utility functions + */ + +/** + * debug output flag options: + * DEBUG_OFF, DEBUG_MOSTLY_OFF, DEBUG_SCREEN_ONLY, DEBUG_FILE_ONLY, DEBUG_SCREEN_AND_FILE + */ +static DebugOutputType dprintfFlag = DEBUG_OFF; + +/** + * Set the debug flag to print to screen, file on cRIO, both or neither + * @param tempString The format string. + */ +void SetDebugFlag ( DebugOutputType flag ) +{ dprintfFlag = flag; } + +/** + * Debug print to a file and/or a terminal window. + * Call like you would call printf. + * Set functionName in the function if you want the correct function name to print out. + * The file line number will also be printed. + * @param tempString The format string. + */ +void dprintf ( const char * tempString, ... ) /* Variable argument list */ +{ + va_list args; /* Input argument list */ + int line_number; /* Line number passed in argument */ + int type; + const char *functionName; /* Format passed in argument */ + const char *fmt; /* Format passed in argument */ + char text[512]; /* Text string */ + char outtext[512]; /* Text string */ + FILE *outfile_fd; /* Output file pointer */ + char filepath[128]; /* Text string */ + int fatalFlag=0; + const char *filename; + int index; + int tempStringLen; + + if (dprintfFlag == DEBUG_OFF) { return; } + + va_start (args, tempString); + + tempStringLen = strlen(tempString); + filename = tempString; + for (index=0;indexSet( newServoPosition ); + //ShowActivity ("pan x: normalized %f newServoPosition = %f" , + // normalizedSinPosition, newServoPosition ); +} + + +/** @brief Read a file and return non-comment output string + +Call the first time with 0 lineNumber to get the number of lines to read +Then call with each lineNumber to get one camera parameter. There should +be one property=value entry on each line, i.e. "exposure=auto" + + * @param inputFile filename to read + * @param outputString one string + * @param lineNumber if 0, return number of lines; else return that line number + * @return int number of lines or -1 if error + **/ +int processFile(char *inputFile, char *outputString, int lineNumber) +{ + FILE *infile; + int stringSize = 80; // max size of one line in file + char inputStr[stringSize]; + int lineCount=0; + + if (lineNumber < 0) + return (-1); + + if ((infile = fopen (inputFile, "r")) == NULL) { + printf ("Fatal error opening file %s\n",inputFile); + return (0); + } + + while (!feof(infile)) { + if (fgets (inputStr, stringSize, infile) != NULL) { + // Skip empty lines + if (emptyString(inputStr)) + continue; + // Skip comment lines + if (inputStr[0] == '#' || inputStr[0] == '!') + continue; + + lineCount++; + if (lineNumber == 0) + continue; + else + { + if (lineCount == lineNumber) + break; + } + } + } + + // close file + fclose (infile); + // if number lines requested return the count + if (lineNumber == 0) + return (lineCount); + // check for input out of range + if (lineNumber > lineCount) + return (-1); + // return the line selected + if (lineCount) { + stripString(inputStr); + strcpy(outputString, inputStr); + return(lineCount); + } + else { + return(-1); + } +} + +/** Ignore empty string + * @param string to check if empty + **/ +int emptyString(char *string) +{ + int i,len; + + if(string == NULL) + return(1); + + len = strlen(string); + for(i=0; i + +using namespace std; + + +BinaryImage::BinaryImage() : MonoImage() +{ +} + +BinaryImage::~BinaryImage() +{ +} + +/** + * Get then number of particles for the image. + * @returns the number of particles found for the image. + */ +int BinaryImage::GetNumberParticles() +{ + int numParticles = 0; + int success = imaqCountParticles(m_imaqImage, 1, &numParticles); + wpi_setImaqErrorWithContext(success, "Error counting particles"); + return numParticles; +} + +/** + * Get a single particle analysis report. + * Get one (of possibly many) particle analysis reports for an image. + * @param particleNumber Which particle analysis report to return. + * @returns the selected particle analysis report + */ +ParticleAnalysisReport BinaryImage::GetParticleAnalysisReport(int particleNumber) +{ + ParticleAnalysisReport par; + GetParticleAnalysisReport(particleNumber, &par); + return par; +} + +/** + * Get a single particle analysis report. + * Get one (of possibly many) particle analysis reports for an image. + * This version could be more efficient when copying many reports. + * @param particleNumber Which particle analysis report to return. + * @param par the selected particle analysis report + */ +void BinaryImage::GetParticleAnalysisReport(int particleNumber, ParticleAnalysisReport *par) +{ + int success; + int numParticles = 0; + + success = imaqGetImageSize(m_imaqImage, &par->imageWidth, &par->imageHeight); + wpi_setImaqErrorWithContext(success, "Error getting image size"); + if (StatusIsFatal()) + return; + + success = imaqCountParticles(m_imaqImage, 1, &numParticles); + wpi_setImaqErrorWithContext(success, "Error counting particles"); + if (StatusIsFatal()) + return; + + if (particleNumber >= numParticles) + { + wpi_setWPIErrorWithContext(ParameterOutOfRange, "particleNumber"); + return; + } + + par->particleIndex = particleNumber; + // Don't bother measuring the rest of the particle if one fails + bool good = ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_X, &par->center_mass_x); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_Y, &par->center_mass_y); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA, &par->particleArea); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_TOP, &par->boundingRect.top); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_LEFT, &par->boundingRect.left); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_HEIGHT, &par->boundingRect.height); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_WIDTH, &par->boundingRect.width); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_IMAGE_AREA, &par->particleToImagePercent); + good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &par->particleQuality); + + if (good) + { + /* normalized position (-1 to 1) */ + par->center_mass_x_normalized = NormalizeFromRange(par->center_mass_x, par->imageWidth); + par->center_mass_y_normalized = NormalizeFromRange(par->center_mass_y, par->imageHeight); + } +} + + +/** + * Get an ordered vector of particles for the image. + * Create a vector of particle analysis reports sorted by size for an image. + * The vector contains the actual report structures. + * @returns a pointer to the vector of particle analysis reports. The caller must delete the + * vector when finished using it. + */ +vector* BinaryImage::GetOrderedParticleAnalysisReports() +{ + vector* particles = new vector; + int particleCount = GetNumberParticles(); + for(int particleIndex = 0; particleIndex < particleCount; particleIndex++) + { + particles->push_back(GetParticleAnalysisReport(particleIndex)); + } + // TODO: This is pretty inefficient since each compare in the sort copies + // both reports being compared... do it manually instead... while we're + // at it, we should provide a version that allows a preallocated buffer of + // ParticleAnalysisReport structures + sort(particles->begin(), particles->end(), CompareParticleSizes); + return particles; +} + +/** + * Write a binary image to flash. + * Writes the binary image to flash on the cRIO for later inspection. + * @param fileName the name of the image file written to the flash. + */ +void BinaryImage::Write(const char *fileName) +{ + RGBValue colorTable[256]; + memset(colorTable, 0, sizeof(colorTable)); + colorTable[0].R = 0; + colorTable[1].R = 255; + colorTable[0].G = colorTable[1].G = 0; + colorTable[0].B = colorTable[1].B = 0; + colorTable[0].alpha = colorTable[1].alpha = 0; + imaqWriteFile(m_imaqImage, fileName, colorTable); +} + +/** + * Measure a single parameter for an image. + * Get the measurement for a single parameter about an image by calling the imaqMeasureParticle + * function for the selected parameter. + * @param particleNumber which particle in the set of particles + * @param whatToMeasure the imaq MeasurementType (what to measure) + * @param result the value of the measurement + * @returns false on failure, true on success + */ +bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result) +{ + double resultDouble; + bool success = ParticleMeasurement(particleNumber, whatToMeasure, &resultDouble); + *result = (int)resultDouble; + return success; +} + +/** + * Measure a single parameter for an image. + * Get the measurement for a single parameter about an image by calling the imaqMeasureParticle + * function for the selected parameter. + * @param particleNumber which particle in the set of particles + * @param whatToMeasure the imaq MeasurementType (what to measure) + * @param result the value of the measurement + * @returns true on failure, false on success + */ +bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result) +{ + int success; + success = imaqMeasureParticle(m_imaqImage, particleNumber, 0, whatToMeasure, result); + wpi_setImaqErrorWithContext(success, "Error measuring particle"); + return !StatusIsFatal(); +} + +//Normalizes to [-1,1] +double BinaryImage::NormalizeFromRange(double position, int range) +{ + return (position * 2.0 / (double)range) - 1.0; +} + +/** + * The compare helper function for sort. + * This function compares two particle analysis reports as a helper for the sort function. + * @param particle1 The first particle to compare + * @param particle2 the second particle to compare + * @returns true if particle1 is greater than particle2 + */ +bool BinaryImage::CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2) +{ + //we want descending sort order + return particle1.particleToImagePercent > particle2.particleToImagePercent; +} + +BinaryImage *BinaryImage::RemoveSmallObjects(bool connectivity8, int erosions) +{ + BinaryImage *result = new BinaryImage(); + int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_LARGE, NULL); + wpi_setImaqErrorWithContext(success, "Error in RemoveSmallObjects"); + return result; +} + +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; +} + +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; +} + +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; +} + diff --git a/wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp b/wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp new file mode 100644 index 0000000000..aa72da31c7 --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/ColorImage.cpp @@ -0,0 +1,465 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "Vision/ColorImage.h" + +#include "WPIErrors.h" + +ColorImage::ColorImage(ImageType type) : ImageBase(type) +{ +} + +ColorImage::~ColorImage() +{ +} + +/** + * 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; +} + +/** + * Perform a threshold in RGB space. + * @param redLow Red low value + * @param redHigh Red high value + * @param greenLow Green low value + * @param greenHigh Green high value + * @param blueLow Blue low value + * @param blueHigh Blue high value + * @returns A pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdRGB(int redLow, int redHigh, int greenLow, int greenHigh, int blueLow, int blueHigh) +{ + return ComputeThreshold(IMAQ_RGB, redLow, redHigh, greenLow, greenHigh, blueLow, blueHigh); +} + +/** + * Perform a threshold in RGB space. + * @param threshold a reference to the Threshold object to use. + * @returns A pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdRGB(Threshold &t) +{ + return ComputeThreshold(IMAQ_RGB, t.plane1Low, t.plane1High, + t.plane2Low, t.plane2High, + t.plane3Low, t.plane3High); +} + +/** + * Perform a threshold in HSL space. + * @param hueLow Low value for hue + * @param hueHigh High value for hue + * @param saturationLow Low value for saturation + * @param saturationHigh High value for saturation + * @param luminenceLow Low value for luminence + * @param luminenceHigh High value for luminence + * @returns a pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdHSL(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int luminenceLow, int luminenceHigh) +{ + return ComputeThreshold(IMAQ_HSL, hueLow, hueHigh, saturationLow, saturationHigh, luminenceLow, luminenceHigh); +} + +/** + * Perform a threshold in HSL space. + * @param threshold a reference to the Threshold object to use. + * @returns A pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdHSL(Threshold &t) +{ + return ComputeThreshold(IMAQ_HSL, t.plane1Low, t.plane1High, + t.plane2Low, t.plane2High, + t.plane3Low, t.plane3High); +} + +/** + * Perform a threshold in HSV space. + * @param hueLow Low value for hue + * @param hueHigh High value for hue + * @param saturationLow Low value for saturation + * @param saturationHigh High value for saturation + * @param valueLow Low value + * @param valueHigh High value + * @returns a pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdHSV(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int valueLow, int valueHigh) +{ + return ComputeThreshold(IMAQ_HSV, hueLow, hueHigh, saturationLow, saturationHigh, valueLow, valueHigh); +} + +/** + * Perform a threshold in HSV space. + * @param threshold a reference to the Threshold object to use. + * @returns A pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdHSV(Threshold &t) +{ + return ComputeThreshold(IMAQ_HSV, t.plane1Low, t.plane1High, + t.plane2Low, t.plane2High, + t.plane3Low, t.plane3High); +} + +/** + * Perform a threshold in HSI space. + * @param hueLow Low value for hue + * @param hueHigh High value for hue + * @param saturationLow Low value for saturation + * @param saturationHigh High value for saturation + * @param valueLow Low intensity + * @param valueHigh High intensity + * @returns a pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdHSI(int hueLow, int hueHigh, int saturationLow, int saturationHigh, int intensityLow, int intensityHigh) +{ + return ComputeThreshold(IMAQ_HSI, hueLow, hueHigh, saturationLow, saturationHigh, intensityLow, intensityHigh); +} + +/** + * Perform a threshold in HSI space. + * @param threshold a reference to the Threshold object to use. + * @returns A pointer to a BinaryImage that represents the result of the threshold operation. + */ +BinaryImage *ColorImage::ThresholdHSI(Threshold &t) +{ + return ComputeThreshold(IMAQ_HSI, t.plane1Low, t.plane1High, + t.plane2Low, t.plane2High, + t.plane3Low, t.plane3High); +} + +/** + * 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 + * @returns A pointer to a MonoImage that represents the extracted plane. + */ +MonoImage *ColorImage::ExtractColorPlane(ColorMode mode, int planeNumber) +{ + MonoImage *result = new MonoImage(); + if (m_imaqImage == NULL) + wpi_setWPIError(NullParameter); + int success = imaqExtractColorPlanes(m_imaqImage, + mode, + (planeNumber == 1) ? result->GetImaqImage() : NULL, + (planeNumber == 2) ? result->GetImaqImage() : NULL, + (planeNumber == 3) ? result->GetImaqImage() : NULL); + wpi_setImaqErrorWithContext(success, "Imaq ExtractColorPlanes failed"); + return result; +} + +/* + * Extract the first color plane for an image. + * @param mode The color mode in which to operate + * @returns a pointer to a MonoImage that is the extracted plane. + */ +MonoImage *ColorImage::ExtractFirstColorPlane(ColorMode mode) +{ + return ExtractColorPlane(mode, 1); +} + +/* + * Extract the second color plane for an image. + * @param mode The color mode in which to operate + * @returns a pointer to a MonoImage that is the extracted plane. + */ +MonoImage *ColorImage::ExtractSecondColorPlane(ColorMode mode) +{ + return ExtractColorPlane(mode, 2); +} + +/* + * Extract the third color plane for an image. + * @param mode The color mode in which to operate + * @returns a pointer to a MonoImage that is the extracted plane. + */ +MonoImage *ColorImage::ExtractThirdColorPlane(ColorMode mode) +{ + return ExtractColorPlane(mode, 3); +} + +/* + * Extract the red plane from an RGB image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetRedPlane() +{ + return ExtractFirstColorPlane(IMAQ_RGB); +} + +/* + * Extract the green plane from an RGB image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetGreenPlane() +{ + return ExtractSecondColorPlane(IMAQ_RGB); +} + +/* + * Extract the blue plane from an RGB image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetBluePlane() +{ + return ExtractThirdColorPlane(IMAQ_RGB); +} + +/* + * Extract the Hue plane from an HSL image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetHSLHuePlane() +{ + return ExtractFirstColorPlane(IMAQ_HSL); +} + +/* + * Extract the Hue plane from an HSV image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetHSVHuePlane() +{ + return ExtractFirstColorPlane(IMAQ_HSV); +} + +/* + * Extract the Hue plane from an HSI image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetHSIHuePlane() +{ + return ExtractFirstColorPlane(IMAQ_HSI); +} + +/* + * Extract the Luminance plane from an HSL image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetLuminancePlane() +{ + return ExtractThirdColorPlane(IMAQ_HSL); +} + +/* + * Extract the Value plane from an HSV image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetValuePlane() +{ + return ExtractThirdColorPlane(IMAQ_HSV); +} + +/* + * Extract the Intensity plane from an HSI image. + * @returns a pointer to a MonoImage that is the extraced plane. + */ +MonoImage *ColorImage::GetIntensityPlane() +{ + return ExtractThirdColorPlane(IMAQ_HSI); +} + +/** + * Replace a plane in the ColorImage with a MonoImage + * Replaces a single plane in the image with a MonoImage + * @param mode The ColorMode in which to operate + * @param plane The pointer to the replacement plane as a MonoImage + * @param planeNumber The plane number (1, 2, 3) to replace + */ +void ColorImage::ReplacePlane(ColorMode mode, MonoImage *plane, int planeNumber) { + int success = imaqReplaceColorPlanes(m_imaqImage, + (const Image*) m_imaqImage, + mode, + (planeNumber == 1) ? plane->GetImaqImage() : NULL, + (planeNumber == 2) ? plane->GetImaqImage() : NULL, + (planeNumber == 3) ? plane->GetImaqImage() : NULL); + wpi_setImaqErrorWithContext(success, "Imaq ReplaceColorPlanes failed"); +} + +/** + * Replace the first color plane with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceFirstColorPlane(ColorMode mode, MonoImage *plane) +{ + ReplacePlane(mode, plane, 1); +} + +/** + * Replace the second color plane with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceSecondColorPlane(ColorMode mode, MonoImage *plane) +{ + ReplacePlane(mode, plane, 2); +} + +/** + * Replace the third color plane with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceThirdColorPlane(ColorMode mode, MonoImage *plane) +{ + ReplacePlane(mode, plane, 3); +} + +/** + * Replace the red color plane with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceRedPlane(MonoImage *plane) +{ + ReplaceFirstColorPlane(IMAQ_RGB, plane); +} + +/** + * Replace the green color plane with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceGreenPlane(MonoImage *plane) +{ + ReplaceSecondColorPlane(IMAQ_RGB, plane); +} + +/** + * Replace the blue color plane with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceBluePlane(MonoImage *plane) +{ + ReplaceThirdColorPlane(IMAQ_RGB, plane); +} + + +/** + * Replace the Hue color plane in a HSL image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceHSLHuePlane(MonoImage *plane) +{ + return ReplaceFirstColorPlane(IMAQ_HSL, plane); +} + +/** + * Replace the Hue color plane in a HSV image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceHSVHuePlane(MonoImage *plane) +{ + return ReplaceFirstColorPlane(IMAQ_HSV, plane); +} + +/** + * Replace the first Hue plane in a HSI image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceHSIHuePlane(MonoImage *plane) +{ + return ReplaceFirstColorPlane(IMAQ_HSI, plane); +} + +/** + * Replace the Saturation color plane in an HSL image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceHSLSaturationPlane(MonoImage *plane) +{ + return ReplaceSecondColorPlane(IMAQ_HSL, plane); +} + +/** + * Replace the Saturation color plane in a HSV image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceHSVSaturationPlane(MonoImage *plane) +{ + return ReplaceSecondColorPlane(IMAQ_HSV, plane); +} + +/** + * Replace the Saturation color plane in a HSI image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceHSISaturationPlane(MonoImage *plane) +{ + return ReplaceSecondColorPlane(IMAQ_HSI, plane); +} + +/** + * Replace the Luminance color plane in an HSL image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceLuminancePlane(MonoImage *plane) +{ + return ReplaceThirdColorPlane(IMAQ_HSL, plane); +} + +/** + * Replace the Value color plane in an HSV with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceValuePlane(MonoImage *plane) +{ + return ReplaceThirdColorPlane(IMAQ_HSV, plane); +} + +/** + * Replace the Intensity color plane in a HSI image with a MonoImage. + * @param mode The color mode in which to operate. + * @param plane A pointer to a MonoImage that will replace the specified color plane. + */ +void ColorImage::ReplaceIntensityPlane(MonoImage *plane) +{ + return ReplaceThirdColorPlane(IMAQ_HSI, plane); +} + +//TODO: frcColorEqualize(Image* dest, const Image* source, int colorEqualization) needs to be modified +//The colorEqualization parameter is discarded and is set to TRUE in the call to imaqColorEqualize. +void ColorImage::Equalize(bool allPlanes) +{ + // Note that this call uses NI-defined TRUE and FALSE + int success = imaqColorEqualize(m_imaqImage, (const Image*) m_imaqImage, (allPlanes) ? TRUE : FALSE); + wpi_setImaqErrorWithContext(success, "Imaq ColorEqualize error"); +} + +void ColorImage::ColorEqualize() +{ + Equalize(true); +} + +void ColorImage::LuminanceEqualize() +{ + Equalize(false); +} diff --git a/wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp b/wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp new file mode 100644 index 0000000000..109dea6db3 --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/FrcError.cpp @@ -0,0 +1,1227 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "nivision.h" +#include "Vision/FrcError.h" + +/** + * Get the error code returned from the NI Vision library + * @return The last error code. + */ +int GetLastVisionError() +{ + //int errorCode = imaqGetLastVisionError(); // error code: 0 = no error + //char* errorText = GetVisionErrorText(errorCode); + //dprintf (LOG_DEBUG, "Error = %i %s ", errorCode, errorText); + return imaqGetLastError(); +} + +/** +* Get the error text for an NI Vision error code. +* Note: imaqGetErrorText() is not supported on real time system, so +* so relevant strings are hardcoded here - the maintained version is +* in the LabWindows/CVI help file. +* @param errorCode The error code to find the text for. +* @return The error text +*/ +const char* GetVisionErrorText(int errorCode) +{ + const char* errorText; + + switch (errorCode) + { + default: + { errorText = "UNKNOWN_ERROR";break;} + case -1074395138: + { errorText = "ERR_OCR_REGION_TOO_SMALL";break;} + case -1074395139: + { errorText = "ERR_IMAQ_QR_DIMENSION_INVALID";break;} + case -1074395140: + { errorText = "ERR_OCR_CHAR_REPORT_CORRUPTED";break;} + case -1074395141: + { errorText = "ERR_OCR_NO_TEXT_FOUND";break;} + case -1074395142: + { errorText = "ERR_QR_DETECTION_MODELTYPE";break;} + case -1074395143: + { errorText = "ERR_QR_DETECTION_MODE";break;} + case -1074395144: + { errorText = "ERR_QR_INVALID_BARCODE";break;} + case -1074395145: + { errorText = "ERR_QR_INVALID_READ";break;} + case -1074395146: + { errorText = "ERR_QR_DETECTION_VERSION";break;} + case -1074395147: + { errorText = "ERR_BARCODE_RSSLIMITED";break;} + case -1074395148: + { errorText = "ERR_OVERLAY_GROUP_NOT_FOUND";break;} + case -1074395149: + { errorText = "ERR_DUPLICATE_TRANSFORM_TYPE";break;} + case -1074395151: + { errorText = "ERR_OCR_CORRECTION_FAILED";break;} + case -1074395155: + { errorText = "ERR_OCR_ORIENT_DETECT_FAILED";break;} + case -1074395156: + { errorText = "ERR_OCR_SKEW_DETECT_FAILED";break;} + case -1074395158: + { errorText = "ERR_OCR_INVALID_CONTRASTMODE";break;} + case -1074395159: + { errorText = "ERR_OCR_INVALID_TOLERANCE";break;} + case -1074395160: + { errorText = "ERR_OCR_INVALID_MAXPOINTSIZE";break;} + case -1074395161: + { errorText = "ERR_OCR_INVALID_CORRECTIONLEVEL";break;} + case -1074395162: + { errorText = "ERR_OCR_INVALID_CORRECTIONMODE";break;} + case -1074395163: + { errorText = "ERR_OCR_INVALID_CHARACTERPREFERENCE";break;} + case -1074395164: + { errorText = "ERR_OCR_ADD_WORD_FAILED";break;} + case -1074395165: + { errorText = "ERR_OCR_WTS_DIR_NOT_FOUND";break;} + case -1074395166: + { errorText = "ERR_OCR_BIN_DIR_NOT_FOUND";break;} + case -1074395167: + { errorText = "ERR_OCR_INVALID_OUTPUTDELIMITER";break;} + case -1074395168: + { errorText = "ERR_OCR_INVALID_AUTOCORRECTIONMODE";break;} + case -1074395169: + { errorText = "ERR_OCR_INVALID_RECOGNITIONMODE";break;} + case -1074395170: + { errorText = "ERR_OCR_INVALID_CHARACTERTYPE";break;} + case -1074395171: + { errorText = "ERR_OCR_INI_FILE_NOT_FOUND";break;} + case -1074395172: + { errorText = "ERR_OCR_INVALID_CHARACTERSET";break;} + case -1074395173: + { errorText = "ERR_OCR_INVALID_LANGUAGE";break;} + case -1074395174: + { errorText = "ERR_OCR_INVALID_AUTOORIENTMODE";break;} + case -1074395175: + { errorText = "ERR_OCR_BAD_USER_DICTIONARY";break;} + case -1074395178: + { errorText = "ERR_OCR_RECOGNITION_FAILED";break;} + case -1074395179: + { errorText = "ERR_OCR_PREPROCESSING_FAILED";break;} + case -1074395200: + { errorText = "ERR_OCR_INVALID_PARAMETER";break;} + case -1074395201: + { errorText = "ERR_OCR_LOAD_LIBRARY";break;} + case -1074395203: + { errorText = "ERR_OCR_LIB_INIT";break;} + case -1074395210: + { errorText = "ERR_OCR_CANNOT_MATCH_TEXT_TEMPLATE";break;} + case -1074395211: + { errorText = "ERR_OCR_BAD_TEXT_TEMPLATE";break;} + case -1074395212: + { errorText = "ERR_OCR_TEMPLATE_WRONG_SIZE";break;} + case -1074395233: + { errorText = "ERR_TEMPLATE_IMAGE_TOO_LARGE";break;} + case -1074395234: + { errorText = "ERR_TEMPLATE_IMAGE_TOO_SMALL";break;} + case -1074395235: + { errorText = "ERR_TEMPLATE_IMAGE_CONTRAST_TOO_LOW";break;} + case -1074395237: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_SHIFT_1";break;} + case -1074395238: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_NOSHIFT";break;} + case -1074395239: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_SHIFT";break;} + case -1074395240: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_ROTATION_1";break;} + case -1074395241: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_NOROTATION";break;} + case -1074395242: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_ROTATION";break;} + case -1074395243: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_4";break;} + case -1074395244: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_3";break;} + case -1074395245: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_2";break;} + case -1074395246: + { errorText = "ERR_TEMPLATE_DESCRIPTOR_1";break;} + case -1074395247: + { errorText = "ERR_TEMPLATE_DESCRIPTOR";break;} + case -1074395248: + { errorText = "ERR_TOO_MANY_ROTATION_ANGLE_RANGES";break;} + case -1074395249: + { errorText = "ERR_ROTATION_ANGLE_RANGE_TOO_LARGE";break;} + case -1074395250: + { errorText = "ERR_MATCH_SETUP_DATA";break;} + case -1074395251: + { errorText = "ERR_INVALID_MATCH_MODE";break;} + case -1074395252: + { errorText = "ERR_LEARN_SETUP_DATA";break;} + case -1074395253: + { errorText = "ERR_INVALID_LEARN_MODE";break;} + case -1074395256: + { errorText = "ERR_EVEN_WINDOW_SIZE";break;} + case -1074395257: + { errorText = "ERR_INVALID_EDGE_DIR";break;} + case -1074395258: + { errorText = "ERR_BAD_FILTER_WIDTH";break;} + case -1074395260: + { errorText = "ERR_HEAP_TRASHED";break;} + case -1074395261: + { errorText = "ERR_GIP_RANGE";break;} + case -1074395262: + { errorText = "ERR_LCD_BAD_MATCH";break;} + case -1074395263: + { errorText = "ERR_LCD_NO_SEGMENTS";break;} + case -1074395265: + { errorText = "ERR_BARCODE";break;} + case -1074395267: + { errorText = "ERR_COMPLEX_ROOT";break;} + case -1074395268: + { errorText = "ERR_LINEAR_COEFF";break;} + case -1074395269: + { errorText = "ERR_NULL_POINTER";break;} + case -1074395270: + { errorText = "ERR_DIV_BY_ZERO";break;} + case -1074395275: + { errorText = "ERR_INVALID_BROWSER_IMAGE";break;} + case -1074395276: + { errorText = "ERR_LINES_PARALLEL";break;} + case -1074395277: + { errorText = "ERR_BARCODE_CHECKSUM";break;} + case -1074395278: + { errorText = "ERR_LCD_NOT_NUMERIC";break;} + case -1074395279: + { errorText = "ERR_ROI_NOT_POLYGON";break;} + case -1074395280: + { errorText = "ERR_ROI_NOT_RECT";break;} + case -1074395281: + { errorText = "ERR_IMAGE_SMALLER_THAN_BORDER";break;} + case -1074395282: + { errorText = "ERR_CANT_DRAW_INTO_VIEWER";break;} + case -1074395283: + { errorText = "ERR_INVALID_RAKE_DIRECTION";break;} + case -1074395284: + { errorText = "ERR_INVALID_EDGE_PROCESS";break;} + case -1074395285: + { errorText = "ERR_INVALID_SPOKE_DIRECTION";break;} + case -1074395286: + { errorText = "ERR_INVALID_CONCENTRIC_RAKE_DIRECTION";break;} + case -1074395287: + { errorText = "ERR_INVALID_LINE";break;} + case -1074395290: + { errorText = "ERR_SHAPEMATCH_BADTEMPLATE";break;} + case -1074395291: + { errorText = "ERR_SHAPEMATCH_BADIMAGEDATA";break;} + case -1074395292: + { errorText = "ERR_POINTS_ARE_COLLINEAR";break;} + case -1074395293: + { errorText = "ERR_CONTOURID_NOT_FOUND";break;} + case -1074395294: + { errorText = "ERR_CONTOUR_INDEX_OUT_OF_RANGE";break;} + case -1074395295: + { errorText = "ERR_INVALID_INTERPOLATIONMETHOD_INTERPOLATEPOINTS";break;} + case -1074395296: + { errorText = "ERR_INVALID_BARCODETYPE";break;} + case -1074395297: + { errorText = "ERR_INVALID_PARTICLEINFOMODE";break;} + case -1074395298: + { errorText = "ERR_COMPLEXPLANE_NOT_REAL_OR_IMAGINARY";break;} + case -1074395299: + { errorText = "ERR_INVALID_COMPLEXPLANE";break;} + case -1074395300: + { errorText = "ERR_INVALID_METERARCMODE";break;} + case -1074395301: + { errorText = "ERR_ROI_NOT_2_LINES";break;} + case -1074395302: + { errorText = "ERR_INVALID_THRESHOLDMETHOD";break;} + case -1074395303: + { errorText = "ERR_INVALID_NUM_OF_CLASSES";break;} + case -1074395304: + { errorText = "ERR_INVALID_MATHTRANSFORMMETHOD";break;} + case -1074395305: + { errorText = "ERR_INVALID_REFERENCEMODE";break;} + case -1074395306: + { errorText = "ERR_INVALID_TOOL";break;} + case -1074395307: + { errorText = "ERR_PRECISION_NOT_GTR_THAN_0";break;} + case -1074395308: + { errorText = "ERR_INVALID_COLORSENSITIVITY";break;} + case -1074395309: + { errorText = "ERR_INVALID_WINDOW_THREAD_POLICY";break;} + case -1074395310: + { errorText = "ERR_INVALID_PALETTE_TYPE";break;} + case -1074395311: + { errorText = "ERR_INVALID_COLOR_SPECTRUM";break;} + case -1074395312: + { errorText = "ERR_LCD_CALIBRATE";break;} + case -1074395313: + { errorText = "ERR_WRITE_FILE_NOT_SUPPORTED";break;} + case -1074395316: + { errorText = "ERR_INVALID_KERNEL_CODE";break;} + case -1074395317: + { errorText = "ERR_UNDEF_POINT";break;} + case -1074395318: + { errorText = "ERR_INSF_POINTS";break;} + case -1074395319: + { errorText = "ERR_INVALID_SUBPIX_TYPE";break;} + case -1074395320: + { errorText = "ERR_TEMPLATE_EMPTY";break;} + case -1074395321: + { errorText = "ERR_INVALID_MORPHOLOGYMETHOD";break;} + case -1074395322: + { errorText = "ERR_INVALID_TEXTALIGNMENT";break;} + case -1074395323: + { errorText = "ERR_INVALID_FONTCOLOR";break;} + case -1074395324: + { errorText = "ERR_INVALID_SHAPEMODE";break;} + case -1074395325: + { errorText = "ERR_INVALID_DRAWMODE";break;} + case -1074395326: + { errorText = "ERR_INVALID_DRAWMODE_FOR_LINE";break;} + case -1074395327: + { errorText = "ERR_INVALID_SCALINGMODE";break;} + case -1074395328: + { errorText = "ERR_INVALID_INTERPOLATIONMETHOD";break;} + case -1074395329: + { errorText = "ERR_INVALID_OUTLINEMETHOD";break;} + case -1074395330: + { errorText = "ERR_INVALID_BORDER_SIZE";break;} + case -1074395331: + { errorText = "ERR_INVALID_BORDERMETHOD";break;} + case -1074395332: + { errorText = "ERR_INVALID_COMPAREFUNCTION";break;} + case -1074395333: + { errorText = "ERR_INVALID_VERTICAL_TEXT_ALIGNMENT";break;} + case -1074395334: + { errorText = "ERR_INVALID_CONVERSIONSTYLE";break;} + case -1074395335: + { errorText = "ERR_DISPATCH_STATUS_CONFLICT";break;} + case -1074395336: + { errorText = "ERR_UNKNOWN_ALGORITHM";break;} + case -1074395340: + { errorText = "ERR_INVALID_SIZETYPE";break;} + case -1074395343: + { errorText = "ERR_FILE_FILENAME_NULL";break;} + case -1074395345: + { errorText = "ERR_INVALID_FLIPAXIS";break;} + case -1074395346: + { errorText = "ERR_INVALID_INTERPOLATIONMETHOD_FOR_ROTATE";break;} + case -1074395347: + { errorText = "ERR_INVALID_3DDIRECTION";break;} + case -1074395348: + { errorText = "ERR_INVALID_3DPLANE";break;} + case -1074395349: + { errorText = "ERR_INVALID_SKELETONMETHOD";break;} + case -1074395350: + { errorText = "ERR_INVALID_VISION_INFO";break;} + case -1074395351: + { errorText = "ERR_INVALID_RECT";break;} + case -1074395352: + { errorText = "ERR_INVALID_FEATURE_MODE";break;} + case -1074395353: + { errorText = "ERR_INVALID_SEARCH_STRATEGY";break;} + case -1074395354: + { errorText = "ERR_INVALID_COLOR_WEIGHT";break;} + case -1074395355: + { errorText = "ERR_INVALID_NUM_MATCHES_REQUESTED";break;} + case -1074395356: + { errorText = "ERR_INVALID_MIN_MATCH_SCORE";break;} + case -1074395357: + { errorText = "ERR_INVALID_COLOR_IGNORE_MODE";break;} + case -1074395360: + { errorText = "ERR_COMPLEX_PLANE";break;} + case -1074395361: + { errorText = "ERR_INVALID_STEEPNESS";break;} + case -1074395362: + { errorText = "ERR_INVALID_WIDTH";break;} + case -1074395363: + { errorText = "ERR_INVALID_SUBSAMPLING_RATIO";break;} + case -1074395364: + { errorText = "ERR_IGNORE_COLOR_SPECTRUM_SET";break;} + case -1074395365: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSPECTRUM";break;} + case -1074395366: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSHAPE";break;} + case -1074395367: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_5";break;} + case -1074395368: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_4";break;} + case -1074395369: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_3";break;} + case -1074395370: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_2";break;} + case -1074395371: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION_1";break;} + case -1074395372: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOROTATION";break;} + case -1074395373: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_ROTATION";break;} + case -1074395374: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT_2";break;} + case -1074395375: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT_1";break;} + case -1074395376: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_NOSHIFT";break;} + case -1074395377: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_SHIFT";break;} + case -1074395378: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_6";break;} + case -1074395379: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_5";break;} + case -1074395380: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_4";break;} + case -1074395381: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_3";break;} + case -1074395382: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_2";break;} + case -1074395383: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR_1";break;} + case -1074395384: + { errorText = "ERR_COLOR_TEMPLATE_DESCRIPTOR";break;} + case -1074395385: + { errorText = "ERR_COLOR_ROTATION_REQUIRES_SHAPE_FEATURE";break;} + case -1074395386: + { errorText = "ERR_COLOR_MATCH_SETUP_DATA_SHAPE";break;} + case -1074395387: + { errorText = "ERR_COLOR_MATCH_SETUP_DATA";break;} + case -1074395388: + { errorText = "ERR_COLOR_LEARN_SETUP_DATA_SHAPE";break;} + case -1074395389: + { errorText = "ERR_COLOR_LEARN_SETUP_DATA";break;} + case -1074395390: + { errorText = "ERR_COLOR_TEMPLATE_IMAGE_LUMINANCE_CONTRAST_TOO_LOW";break;} + case -1074395391: + { errorText = "ERR_COLOR_TEMPLATE_IMAGE_HUE_CONTRAST_TOO_LOW";break;} + case -1074395392: + { errorText = "ERR_COLOR_TEMPLATE_IMAGE_TOO_LARGE";break;} + case -1074395393: + { errorText = "ERR_COLOR_TEMPLATE_IMAGE_TOO_SMALL";break;} + case -1074395394: + { errorText = "ERR_COLOR_SPECTRUM_MASK";break;} + case -1074395395: + { errorText = "ERR_COLOR_IMAGE_REQUIRED";break;} + case -1074395397: + { errorText = "ERR_COMPLEX_IMAGE_REQUIRED";break;} + case -1074395399: + { errorText = "ERR_MULTICORE_INVALID_ARGUMENT";break;} + case -1074395400: + { errorText = "ERR_MULTICORE_OPERATION";break;} + case -1074395401: + { errorText = "ERR_INVALID_MATCHFACTOR";break;} + case -1074395402: + { errorText = "ERR_INVALID_MAXPOINTS";break;} + case -1074395403: + { errorText = "ERR_EXTRAINFO_VERSION";break;} + case -1074395404: + { errorText = "ERR_INVALID_INTERPOLATIONMETHOD_FOR_UNWRAP";break;} + case -1074395405: + { errorText = "ERR_INVALID_TEXTORIENTATION";break;} + case -1074395406: + { errorText = "ERR_COORDSYS_NOT_FOUND";break;} + case -1074395407: + { errorText = "ERR_INVALID_CONTRAST";break;} + case -1074395408: + { errorText = "ERR_INVALID_DETECTION_MODE";break;} + case -1074395409: + { errorText = "ERR_INVALID_SUBPIXEL_DIVISIONS";break;} + case -1074395410: + { errorText = "ERR_INVALID_ICONS_PER_LINE";break;} + case -1074395549: + { errorText = "ERR_NIOCR_INVALID_NUMBER_OF_OBJECTS_TO_VERIFY";break;} + case -1074395550: + { errorText = "ERR_NIOCR_INVALID_CHARACTER_VALUE";break;} + case -1074395551: + { errorText = "ERR_NIOCR_RENAME_REFCHAR";break;} + case -1074395552: + { errorText = "ERR_NIOCR_NOT_A_VALID_CHARACTER_SET";break;} + case -1074395553: + { errorText = "ERR_NIOCR_INVALID_MIN_BOUNDING_RECT_HEIGHT";break;} + case -1074395554: + { errorText = "ERR_NIOCR_INVALID_READ_RESOLUTION";break;} + case -1074395555: + { errorText = "ERR_NIOCR_INVALID_SPACING_RANGE";break;} + case -1074395556: + { errorText = "ERR_NIOCR_INVALID_BOUNDING_RECT_HEIGHT_RANGE";break;} + case -1074395557: + { errorText = "ERR_NIOCR_INVALID_BOUNDING_RECT_WIDTH_RANGE";break;} + case -1074395558: + { errorText = "ERR_NIOCR_INVALID_CHARACTER_SIZE_RANGE";break;} + case -1074395559: + { errorText = "ERR_NIOCR_INVALID_READ_OPTION";break;} + case -1074395560: + { errorText = "ERR_NIOCR_INVALID_OBJECT_INDEX";break;} + case -1074395561: + { errorText = "ERR_NIOCR_INVALID_NUMBER_OF_CHARACTERS";break;} + case -1074395562: + { errorText = "ERR_NIOCR_BOOLEAN_VALUE_FOR_STRING_ATTRIBUTE";break;} + case -1074395563: + { errorText = "ERR_NIOCR_UNLICENSED";break;} + case -1074395564: + { errorText = "ERR_NIOCR_INVALID_PREDEFINED_CHARACTER";break;} + case -1074395565: + { errorText = "ERR_NIOCR_MUST_BE_SINGLE_CHARACTER";break;} + case -1074395566: + { errorText = "ERR_NIOCR_BOOLEAN_VALUE_FOR_INTEGER_ATTRIBUTE";break;} + case -1074395567: + { errorText = "ERR_NIOCR_STRING_VALUE_FOR_BOOLEAN_ATTRIBUTE";break;} + case -1074395568: + { errorText = "ERR_NIOCR_STRING_VALUE_FOR_INTEGER_ATTRIBUTE";break;} + case -1074395569: + { errorText = "ERR_NIOCR_INVALID_ATTRIBUTE";break;} + case -1074395570: + { errorText = "ERR_NIOCR_INTEGER_VALUE_FOR_BOOLEAN_ATTRIBUTE";break;} + case -1074395571: + { errorText = "ERR_NIOCR_GET_ONLY_ATTRIBUTE";break;} + case -1074395572: + { errorText = "ERR_NIOCR_INTEGER_VALUE_FOR_STRING_ATTRIBUTE";break;} + case -1074395573: + { errorText = "ERR_NIOCR_INVALID_CHARACTER_SET_FILE_VERSION";break;} + case -1074395574: + { errorText = "ERR_NIOCR_CHARACTER_SET_DESCRIPTION_TOO_LONG";break;} + case -1074395575: + { errorText = "ERR_NIOCR_INVALID_NUMBER_OF_EROSIONS";break;} + case -1074395576: + { errorText = "ERR_NIOCR_CHARACTER_VALUE_TOO_LONG";break;} + case -1074395577: + { errorText = "ERR_NIOCR_CHARACTER_VALUE_CANNOT_BE_EMPTYSTRING";break;} + case -1074395578: + { errorText = "ERR_NIOCR_INVALID_CHARACTER_SET_FILE";break;} + case -1074395579: + { errorText = "ERR_NIOCR_INVALID_ASPECT_RATIO";break;} + case -1074395580: + { errorText = "ERR_NIOCR_INVALID_MIN_BOUNDING_RECT_WIDTH";break;} + case -1074395581: + { errorText = "ERR_NIOCR_INVALID_MAX_VERT_ELEMENT_SPACING";break;} + case -1074395582: + { errorText = "ERR_NIOCR_INVALID_MAX_HORIZ_ELEMENT_SPACING";break;} + case -1074395583: + { errorText = "ERR_NIOCR_INVALID_MIN_CHAR_SPACING";break;} + case -1074395584: + { errorText = "ERR_NIOCR_INVALID_THRESHOLD_LIMITS";break;} + case -1074395585: + { errorText = "ERR_NIOCR_INVALID_UPPER_THRESHOLD_LIMIT";break;} + case -1074395586: + { errorText = "ERR_NIOCR_INVALID_LOWER_THRESHOLD_LIMIT";break;} + case -1074395587: + { errorText = "ERR_NIOCR_INVALID_THRESHOLD_RANGE";break;} + case -1074395588: + { errorText = "ERR_NIOCR_INVALID_HIGH_THRESHOLD_VALUE";break;} + case -1074395589: + { errorText = "ERR_NIOCR_INVALID_LOW_THRESHOLD_VALUE";break;} + case -1074395590: + { errorText = "ERR_NIOCR_INVALID_NUMBER_OF_VALID_CHARACTER_POSITIONS";break;} + case -1074395591: + { errorText = "ERR_NIOCR_INVALID_CHARACTER_INDEX";break;} + case -1074395592: + { errorText = "ERR_NIOCR_INVALID_READ_STRATEGY";break;} + case -1074395593: + { errorText = "ERR_NIOCR_INVALID_NUMBER_OF_BLOCKS";break;} + case -1074395594: + { errorText = "ERR_NIOCR_INVALID_SUBSTITUTION_CHARACTER";break;} + case -1074395595: + { errorText = "ERR_NIOCR_INVALID_THRESHOLD_MODE";break;} + case -1074395596: + { errorText = "ERR_NIOCR_INVALID_CHARACTER_SIZE";break;} + case -1074395597: + { errorText = "ERR_NIOCR_NOT_A_VALID_SESSION";break;} + case -1074395598: + { errorText = "ERR_NIOCR_INVALID_ACCEPTANCE_LEVEL";break;} + case -1074395600: + { errorText = "ERR_INFO_NOT_FOUND";break;} + case -1074395601: + { errorText = "ERR_INVALID_EDGE_THRESHOLD";break;} + case -1074395602: + { errorText = "ERR_INVALID_MINIMUM_CURVE_LENGTH";break;} + case -1074395603: + { errorText = "ERR_INVALID_ROW_STEP";break;} + case -1074395604: + { errorText = "ERR_INVALID_COLUMN_STEP";break;} + case -1074395605: + { errorText = "ERR_INVALID_MAXIMUM_END_POINT_GAP";break;} + case -1074395606: + { errorText = "ERR_INVALID_MINIMUM_FEATURES_TO_MATCH";break;} + case -1074395607: + { errorText = "ERR_INVALID_MAXIMUM_FEATURES_PER_MATCH";break;} + case -1074395608: + { errorText = "ERR_INVALID_SUBPIXEL_ITERATIONS";break;} + case -1074395609: + { errorText = "ERR_INVALID_SUBPIXEL_TOLERANCE";break;} + case -1074395610: + { errorText = "ERR_INVALID_INITIAL_MATCH_LIST_LENGTH";break;} + case -1074395611: + { errorText = "ERR_INVALID_MINIMUM_RECTANGLE_DIMENSION";break;} + case -1074395612: + { errorText = "ERR_INVALID_MINIMUM_FEATURE_RADIUS";break;} + case -1074395613: + { errorText = "ERR_INVALID_MINIMUM_FEATURE_LENGTH";break;} + case -1074395614: + { errorText = "ERR_INVALID_MINIMUM_FEATURE_ASPECT_RATIO";break;} + case -1074395615: + { errorText = "ERR_INVALID_MINIMUM_FEATURE_STRENGTH";break;} + case -1074395616: + { errorText = "ERR_INVALID_EDGE_FILTER_SIZE";break;} + case -1074395617: + { errorText = "ERR_INVALID_NUMBER_OF_FEATURES_RANGE";break;} + case -1074395618: + { errorText = "ERR_TOO_MANY_SCALE_RANGES";break;} + case -1074395619: + { errorText = "ERR_TOO_MANY_OCCLUSION_RANGES";break;} + case -1074395620: + { errorText = "ERR_INVALID_CURVE_EXTRACTION_MODE";break;} + case -1074395621: + { errorText = "ERR_INVALID_LEARN_GEOMETRIC_PATTERN_SETUP_DATA";break;} + case -1074395622: + { errorText = "ERR_INVALID_MATCH_GEOMETRIC_PATTERN_SETUP_DATA";break;} + case -1074395623: + { errorText = "ERR_INVALID_SCALE_RANGE";break;} + case -1074395624: + { errorText = "ERR_INVALID_OCCLUSION_RANGE";break;} + case -1074395625: + { errorText = "ERR_INVALID_MATCH_CONSTRAINT_TYPE";break;} + case -1074395626: + { errorText = "ERR_NOT_ENOUGH_TEMPLATE_FEATURES";break;} + case -1074395627: + { errorText = "ERR_NOT_ENOUGH_TEMPLATE_FEATURES_1";break;} + case -1074395628: + { errorText = "ERR_INVALID_GEOMETRIC_MATCHING_TEMPLATE";break;} + case -1074395629: + { errorText = "ERR_INVALID_MAXIMUM_PIXEL_DISTANCE_FROM_LINE";break;} + case -1074395630: + { errorText = "ERR_INVALID_MAXIMUM_FEATURES_LEARNED";break;} + case -1074395631: + { errorText = "ERR_INVALID_MIN_MATCH_SEPARATION_DISTANCE";break;} + case -1074395632: + { errorText = "ERR_INVALID_MIN_MATCH_SEPARATION_ANGLE";break;} + case -1074395633: + { errorText = "ERR_INVALID_MIN_MATCH_SEPARATION_SCALE";break;} + case -1074395634: + { errorText = "ERR_INVALID_MAX_MATCH_OVERLAP";break;} + case -1074395635: + { errorText = "ERR_INVALID_SHAPE_DESCRIPTOR";break;} + case -1074395636: + { errorText = "ERR_DIRECTX_NOT_FOUND";break;} + case -1074395637: + { errorText = "ERR_HARDWARE_DOESNT_SUPPORT_NONTEARING";break;} + case -1074395638: + { errorText = "ERR_INVALID_FILL_STYLE";break;} + case -1074395639: + { errorText = "ERR_INVALID_HATCH_STYLE";break;} + case -1074395640: + { errorText = "ERR_TOO_MANY_ZONES";break;} + case -1074395641: + { errorText = "ERR_DUPLICATE_LABEL";break;} + case -1074395642: + { errorText = "ERR_LABEL_NOT_FOUND";break;} + case -1074395643: + { errorText = "ERR_INVALID_NUMBER_OF_MATCH_OPTIONS";break;} + case -1074395644: + { errorText = "ERR_LABEL_TOO_LONG";break;} + case -1074395645: + { errorText = "ERR_INVALID_NUMBER_OF_LABELS";break;} + case -1074395646: + { errorText = "ERR_NO_TEMPLATE_TO_LEARN";break;} + case -1074395647: + { errorText = "ERR_INVALID_MULTIPLE_GEOMETRIC_TEMPLATE";break;} + case -1074395648: + { errorText = "ERR_TEMPLATE_NOT_LEARNED";break;} + case -1074395649: + { errorText = "ERR_INVALID_GEOMETRIC_FEATURE_TYPE";break;} + case -1074395650: + { errorText = "ERR_CURVE_EXTRACTION_MODE_MUST_BE_SAME";break;} + case -1074395651: + { errorText = "ERR_EDGE_FILTER_SIZE_MUST_BE_SAME";break;} + case -1074395652: + { errorText = "ERR_OPENING_NEWER_GEOMETRIC_MATCHING_TEMPLATE";break;} + case -1074395653: + { errorText = "ERR_OPENING_NEWER_MULTIPLE_GEOMETRIC_TEMPLATE";break;} + case -1074395654: + { errorText = "ERR_GRADING_INFORMATION_NOT_FOUND";break;} + case -1074395655: + { errorText = "ERR_ENABLE_CALIBRATION_SUPPORT_MUST_BE_SAME";break;} + case -1074395656: + { errorText = "ERR_SMOOTH_CONTOURS_MUST_BE_SAME";break;} + case -1074395700: + { errorText = "ERR_REQUIRES_WIN2000_OR_NEWER";break;} + case -1074395701: + { errorText = "ERR_INVALID_MATRIX_SIZE_RANGE";break;} + case -1074395702: + { errorText = "ERR_INVALID_LENGTH";break;} + case -1074395703: + { errorText = "ERR_INVALID_TYPE_OF_FLATTEN";break;} + case -1074395704: + { errorText = "ERR_INVALID_COMPRESSION_TYPE";break;} + case -1074395705: + { errorText = "ERR_DATA_CORRUPTED";break;} + case -1074395706: + { errorText = "ERR_AVI_SESSION_ALREADY_OPEN";break;} + case -1074395707: + { errorText = "ERR_AVI_WRITE_SESSION_REQUIRED";break;} + case -1074395708: + { errorText = "ERR_AVI_READ_SESSION_REQUIRED";break;} + case -1074395709: + { errorText = "ERR_AVI_UNOPENED_SESSION";break;} + case -1074395710: + { errorText = "ERR_TOO_MANY_PARTICLES";break;} + case -1074395711: + { errorText = "ERR_NOT_ENOUGH_REGIONS";break;} + case -1074395712: + { errorText = "ERR_WRONG_REGION_TYPE";break;} + case -1074395713: + { errorText = "ERR_VALUE_NOT_IN_ENUM";break;} + case -1074395714: + { errorText = "ERR_INVALID_AXIS_ORIENTATION";break;} + case -1074395715: + { errorText = "ERR_INVALID_CALIBRATION_UNIT";break;} + case -1074395716: + { errorText = "ERR_INVALID_SCALING_METHOD";break;} + case -1074395717: + { errorText = "ERR_INVALID_RANGE";break;} + case -1074395718: + { errorText = "ERR_LAB_VERSION";break;} + case -1074395719: + { errorText = "ERR_BAD_ROI_BOX";break;} + case -1074395720: + { errorText = "ERR_BAD_ROI";break;} + case -1074395721: + { errorText = "ERR_INVALID_BIT_DEPTH";break;} + case -1074395722: + { errorText = "ERR_CLASSIFIER_CLASSIFY_IMAGE_WITH_CUSTOM_SESSION";break;} + case -1074395723: + { errorText = "ERR_CUSTOMDATA_KEY_NOT_FOUND";break;} + case -1074395724: + { errorText = "ERR_CUSTOMDATA_INVALID_SIZE";break;} + case -1074395725: + { errorText = "ERR_DATA_VERSION";break;} + case -1074395726: + { errorText = "ERR_MATCHFACTOR_OBSOLETE";break;} + case -1074395727: + { errorText = "ERR_UNSUPPORTED_2D_BARCODE_SEARCH_MODE";break;} + case -1074395728: + { errorText = "ERR_INVALID_2D_BARCODE_SEARCH_MODE";break;} + case -1074395754: + { errorText = "ERR_TRIG_TIMEOUT";break;} + case -1074395756: + { errorText = "ERR_DLL_FUNCTION_NOT_FOUND";break;} + case -1074395757: + { errorText = "ERR_DLL_NOT_FOUND";break;} + case -1074395758: + { errorText = "ERR_BOARD_NOT_OPEN";break;} + case -1074395760: + { errorText = "ERR_BOARD_NOT_FOUND";break;} + case -1074395762: + { errorText = "ERR_INVALID_NIBLACK_DEVIATION_FACTOR";break;} + case -1074395763: + { errorText = "ERR_INVALID_NORMALIZATION_METHOD";break;} + case -1074395766: + { errorText = "ERR_DEPRECATED_FUNCTION";break;} + case -1074395767: + { errorText = "ERR_INVALID_ALIGNMENT";break;} + case -1074395768: + { errorText = "ERR_INVALID_SCALE";break;} + case -1074395769: + { errorText = "ERR_INVALID_EDGE_THICKNESS";break;} + case -1074395770: + { errorText = "ERR_INVALID_INSPECTION_TEMPLATE";break;} + case -1074395771: + { errorText = "ERR_OPENING_NEWER_INSPECTION_TEMPLATE";break;} + case -1074395772: + { errorText = "ERR_INVALID_REGISTRATION_METHOD";break;} + case -1074395773: + { errorText = "ERR_NO_DEST_IMAGE";break;} + case -1074395774: + { errorText = "ERR_NO_LABEL";break;} + case -1074395775: + { errorText = "ERR_ROI_HAS_OPEN_CONTOURS";break;} + case -1074395776: + { errorText = "ERR_INVALID_USE_OF_COMPACT_SESSION_FILE";break;} + case -1074395777: + { errorText = "ERR_INCOMPATIBLE_CLASSIFIER_TYPES";break;} + case -1074395778: + { errorText = "ERR_INVALID_KERNEL_SIZE";break;} + case -1074395779: + { errorText = "ERR_CANNOT_COMPACT_UNTRAINED";break;} + case -1074395780: + { errorText = "ERR_INVALID_PARTICLE_TYPE";break;} + case -1074395781: + { errorText = "ERR_CLASSIFIER_INVALID_ENGINE_TYPE";break;} + case -1074395782: + { errorText = "ERR_DESCRIPTION_TOO_LONG";break;} + case -1074395783: + { errorText = "ERR_BAD_SAMPLE_INDEX";break;} + case -1074395784: + { errorText = "ERR_INVALID_LIMITS";break;} + case -1074395785: + { errorText = "ERR_NO_PARTICLE";break;} + case -1074395786: + { errorText = "ERR_INVALID_PARTICLE_OPTIONS";break;} + case -1074395787: + { errorText = "ERR_INVALID_CLASSIFIER_TYPE";break;} + case -1074395788: + { errorText = "ERR_NO_SAMPLES";break;} + case -1074395789: + { errorText = "ERR_OPENING_NEWER_CLASSIFIER_SESSION";break;} + case -1074395790: + { errorText = "ERR_INVALID_DISTANCE_METRIC";break;} + case -1074395791: + { errorText = "ERR_CLASSIFIER_INVALID_SESSION_TYPE";break;} + case -1074395792: + { errorText = "ERR_CLASSIFIER_SESSION_NOT_TRAINED";break;} + case -1074395793: + { errorText = "ERR_INVALID_OPERATION_ON_COMPACT_SESSION_ATTEMPTED";break;} + case -1074395794: + { errorText = "ERR_K_TOO_HIGH";break;} + case -1074395795: + { errorText = "ERR_K_TOO_LOW";break;} + case -1074395796: + { errorText = "ERR_INVALID_KNN_METHOD";break;} + case -1074395797: + { errorText = "ERR_INVALID_CLASSIFIER_SESSION";break;} + case -1074395798: + { errorText = "ERR_INVALID_CUSTOM_SAMPLE";break;} + case -1074395799: + { errorText = "ERR_INTERNAL";break;} + case -1074395800: + { errorText = "ERR_PROTECTION";break;} + case -1074395801: + { errorText = "ERR_TOO_MANY_CONTOURS";break;} + case -1074395837: + { errorText = "ERR_INVALID_COMPRESSION_RATIO";break;} + case -1074395840: + { errorText = "ERR_BAD_INDEX";break;} + case -1074395875: + { errorText = "ERR_BARCODE_PHARMACODE";break;} + case -1074395876: + { errorText = "ERR_UNSUPPORTED_COLOR_MODE";break;} + case -1074395877: + { errorText = "ERR_COLORMODE_REQUIRES_CHANGECOLORSPACE2";break;} + case -1074395878: + { errorText = "ERR_PROP_NODE_WRITE_NOT_SUPPORTED";break;} + case -1074395879: + { errorText = "ERR_BAD_MEASURE";break;} + case -1074395880: + { errorText = "ERR_PARTICLE";break;} + case -1074395920: + { errorText = "ERR_NUMBER_CLASS";break;} + case -1074395953: + { errorText = "ERR_INVALID_WAVELET_TRANSFORM_MODE";break;} + case -1074395954: + { errorText = "ERR_INVALID_QUANTIZATION_STEP_SIZE";break;} + case -1074395955: + { errorText = "ERR_INVALID_MAX_WAVELET_TRANSFORM_LEVEL";break;} + case -1074395956: + { errorText = "ERR_INVALID_QUALITY";break;} + case -1074395957: + { errorText = "ERR_ARRAY_SIZE_MISMATCH";break;} + case -1074395958: + { errorText = "ERR_WINDOW_ID";break;} + case -1074395959: + { errorText = "ERR_CREATE_WINDOW";break;} + case -1074395960: + { errorText = "ERR_INIT";break;} + case -1074395971: + { errorText = "ERR_INVALID_OFFSET";break;} + case -1074395972: + { errorText = "ERR_DIRECTX_ENUMERATE_FILTERS";break;} + case -1074395973: + { errorText = "ERR_JPEG2000_UNSUPPORTED_MULTIPLE_LAYERS";break;} + case -1074395974: + { errorText = "ERR_UNSUPPORTED_JPEG2000_COLORSPACE_METHOD";break;} + case -1074395975: + { errorText = "ERR_AVI_TIMEOUT";break;} + case -1074395976: + { errorText = "ERR_NUMBER_OF_PALETTE_COLORS";break;} + case -1074395977: + { errorText = "ERR_AVI_VERSION";break;} + case -1074395978: + { errorText = "ERR_INVALID_PARTICLE_NUMBER";break;} + case -1074395979: + { errorText = "ERR_INVALID_PARTICLE_INFO";break;} + case -1074395980: + { errorText = "ERR_COM_INITIALIZE";break;} + case -1074395981: + { errorText = "ERR_INSUFFICIENT_BUFFER_SIZE";break;} + case -1074395982: + { errorText = "ERR_INVALID_FRAMES_PER_SECOND";break;} + case -1074395983: + { errorText = "ERR_FILE_NO_SPACE";break;} + case -1074395984: + { errorText = "ERR_FILE_INVALID_DATA_TYPE";break;} + case -1074395985: + { errorText = "ERR_FILE_OPERATION";break;} + case -1074395986: + { errorText = "ERR_FILE_FORMAT";break;} + case -1074395987: + { errorText = "ERR_FILE_EOF";break;} + case -1074395988: + { errorText = "ERR_FILE_WRITE";break;} + case -1074395989: + { errorText = "ERR_FILE_READ";break;} + case -1074395990: + { errorText = "ERR_FILE_GET_INFO";break;} + case -1074395991: + { errorText = "ERR_FILE_INVALID_TYPE";break;} + case -1074395992: + { errorText = "ERR_FILE_PERMISSION";break;} + case -1074395993: + { errorText = "ERR_FILE_IO_ERR";break;} + case -1074395994: + { errorText = "ERR_FILE_TOO_MANY_OPEN";break;} + case -1074395995: + { errorText = "ERR_FILE_NOT_FOUND";break;} + case -1074395996: + { errorText = "ERR_FILE_OPEN";break;} + case -1074395997: + { errorText = "ERR_FILE_ARGERR";break;} + case -1074395998: + { errorText = "ERR_FILE_COLOR_TABLE";break;} + case -1074395999: + { errorText = "ERR_FILE_FILE_TYPE";break;} + case -1074396000: + { errorText = "ERR_FILE_FILE_HEADER";break;} + case -1074396001: + { errorText = "ERR_TOO_MANY_AVI_SESSIONS";break;} + case -1074396002: + { errorText = "ERR_INVALID_LINEGAUGEMETHOD";break;} + case -1074396003: + { errorText = "ERR_AVI_DATA_EXCEEDS_BUFFER_SIZE";break;} + case -1074396004: + { errorText = "ERR_DIRECTX_CERTIFICATION_FAILURE";break;} + case -1074396005: + { errorText = "ERR_INVALID_AVI_SESSION";break;} + case -1074396006: + { errorText = "ERR_DIRECTX_UNKNOWN_COMPRESSION_FILTER";break;} + case -1074396007: + { errorText = "ERR_DIRECTX_INCOMPATIBLE_COMPRESSION_FILTER";break;} + case -1074396008: + { errorText = "ERR_DIRECTX_NO_FILTER";break;} + case -1074396009: + { errorText = "ERR_DIRECTX";break;} + case -1074396010: + { errorText = "ERR_INVALID_FRAME_NUMBER";break;} + case -1074396011: + { errorText = "ERR_RPC_BIND";break;} + case -1074396012: + { errorText = "ERR_RPC_EXECUTE";break;} + case -1074396013: + { errorText = "ERR_INVALID_VIDEO_MODE";break;} + case -1074396014: + { errorText = "ERR_INVALID_VIDEO_BLIT";break;} + case -1074396015: + { errorText = "ERR_RPC_EXECUTE_IVB";break;} + case -1074396016: + { errorText = "ERR_NO_VIDEO_DRIVER";break;} + case -1074396017: + { errorText = "ERR_OPENING_NEWER_AIM_GRADING_DATA";break;} + case -1074396018: + { errorText = "ERR_INVALID_EDGE_POLARITY_SEARCH_MODE";break;} + case -1074396019: + { errorText = "ERR_INVALID_THRESHOLD_PERCENTAGE";break;} + case -1074396020: + { errorText = "ERR_INVALID_GRADING_MODE";break;} + case -1074396021: + { errorText = "ERR_INVALID_KERNEL_SIZE_FOR_EDGE_DETECTION";break;} + case -1074396022: + { errorText = "ERR_INVALID_SEARCH_MODE_FOR_STRAIGHT_EDGE";break;} + case -1074396023: + { errorText = "ERR_INVALID_ANGLE_TOL_FOR_STRAIGHT_EDGE";break;} + case -1074396024: + { errorText = "ERR_INVALID_MIN_COVERAGE_FOR_STRAIGHT_EDGE";break;} + case -1074396025: + { errorText = "ERR_INVALID_ANGLE_RANGE_FOR_STRAIGHT_EDGE";break;} + case -1074396026: + { errorText = "ERR_INVALID_PROCESS_TYPE_FOR_EDGE_DETECTION";break;} + case -1074396032: + { errorText = "ERR_TEMPLATEDESCRIPTOR_ROTATION_SEARCHSTRATEGY";break;} + case -1074396033: + { errorText = "ERR_TEMPLATEDESCRIPTOR_LEARNSETUPDATA";break;} + case -1074396034: + { errorText = "ERR_TEMPLATEIMAGE_EDGEINFO";break;} + case -1074396035: + { errorText = "ERR_TEMPLATEIMAGE_NOCIRCLE";break;} + case -1074396036: + { errorText = "ERR_INVALID_SKELETONMODE";break;} + case -1074396037: + { errorText = "ERR_TIMEOUT";break;} + case -1074396038: + { errorText = "ERR_FIND_COORDSYS_MORE_THAN_ONE_EDGE";break;} + case -1074396039: + { errorText = "ERR_IO_ERROR";break;} + case -1074396040: + { errorText = "ERR_DRIVER";break;} + case -1074396041: + { errorText = "ERR_INVALID_2D_BARCODE_TYPE";break;} + case -1074396042: + { errorText = "ERR_INVALID_2D_BARCODE_CONTRAST";break;} + case -1074396043: + { errorText = "ERR_INVALID_2D_BARCODE_CELL_SHAPE";break;} + case -1074396044: + { errorText = "ERR_INVALID_2D_BARCODE_SHAPE";break;} + case -1074396045: + { errorText = "ERR_INVALID_2D_BARCODE_SUBTYPE";break;} + case -1074396046: + { errorText = "ERR_INVALID_2D_BARCODE_CONTRAST_FOR_ROI";break;} + case -1074396047: + { errorText = "ERR_INVALID_LINEAR_AVERAGE_MODE";break;} + case -1074396048: + { errorText = "ERR_INVALID_CELL_SAMPLE_SIZE";break;} + case -1074396049: + { errorText = "ERR_INVALID_MATRIX_POLARITY";break;} + case -1074396050: + { errorText = "ERR_INVALID_ECC_TYPE";break;} + case -1074396051: + { errorText = "ERR_INVALID_CELL_FILTER_MODE";break;} + case -1074396052: + { errorText = "ERR_INVALID_DEMODULATION_MODE";break;} + case -1074396053: + { errorText = "ERR_INVALID_BORDER_INTEGRITY";break;} + case -1074396054: + { errorText = "ERR_INVALID_CELL_FILL_TYPE";break;} + case -1074396055: + { errorText = "ERR_INVALID_ASPECT_RATIO";break;} + case -1074396056: + { errorText = "ERR_INVALID_MATRIX_MIRROR_MODE";break;} + case -1074396057: + { errorText = "ERR_INVALID_SEARCH_VECTOR_WIDTH";break;} + case -1074396058: + { errorText = "ERR_INVALID_ROTATION_MODE";break;} + case -1074396059: + { errorText = "ERR_INVALID_MAX_ITERATIONS";break;} + case -1074396060: + { errorText = "ERR_JPEG2000_LOSSLESS_WITH_FLOATING_POINT";break;} + case -1074396061: + { errorText = "ERR_INVALID_WINDOW_SIZE";break;} + case -1074396062: + { errorText = "ERR_INVALID_TOLERANCE";break;} + case -1074396063: + { errorText = "ERR_EXTERNAL_ALIGNMENT";break;} + case -1074396064: + { errorText = "ERR_EXTERNAL_NOT_SUPPORTED";break;} + case -1074396065: + { errorText = "ERR_CANT_RESIZE_EXTERNAL";break;} + case -1074396066: + { errorText = "ERR_INVALID_POINTSYMBOL";break;} + case -1074396067: + { errorText = "ERR_IMAGES_NOT_DIFF";break;} + case -1074396068: + { errorText = "ERR_INVALID_ACTION";break;} + case -1074396069: + { errorText = "ERR_INVALID_COLOR_MODE";break;} + case -1074396070: + { errorText = "ERR_INVALID_FUNCTION";break;} + case -1074396071: + { errorText = "ERR_INVALID_SCAN_DIRECTION";break;} + case -1074396072: + { errorText = "ERR_INVALID_BORDER";break;} + case -1074396073: + { errorText = "ERR_MASK_OUTSIDE_IMAGE";break;} + case -1074396074: + { errorText = "ERR_INCOMP_SIZE";break;} + case -1074396075: + { errorText = "ERR_COORD_SYS_SECOND_AXIS";break;} + case -1074396076: + { errorText = "ERR_COORD_SYS_FIRST_AXIS";break;} + case -1074396077: + { errorText = "ERR_INCOMP_TYPE";break;} + case -1074396079: + { errorText = "ERR_INVALID_METAFILE_HANDLE";break;} + case -1074396080: + { errorText = "ERR_INVALID_IMAGE_TYPE";break;} + case -1074396081: + { errorText = "ERR_BAD_PASSWORD";break;} + case -1074396082: + { errorText = "ERR_PALETTE_NOT_SUPPORTED";break;} + case -1074396083: + { errorText = "ERR_ROLLBACK_TIMEOUT";break;} + case -1074396084: + { errorText = "ERR_ROLLBACK_DELETE_TIMER";break;} + case -1074396085: + { errorText = "ERR_ROLLBACK_INIT_TIMER";break;} + case -1074396086: + { errorText = "ERR_ROLLBACK_START_TIMER";break;} + case -1074396087: + { errorText = "ERR_ROLLBACK_STOP_TIMER";break;} + case -1074396088: + { errorText = "ERR_ROLLBACK_RESIZE";break;} + case -1074396089: + { errorText = "ERR_ROLLBACK_RESOURCE_REINITIALIZE";break;} + case -1074396090: + { errorText = "ERR_ROLLBACK_RESOURCE_ENABLED";break;} + case -1074396091: + { errorText = "ERR_ROLLBACK_RESOURCE_UNINITIALIZED_ENABLE";break;} + case -1074396092: + { errorText = "ERR_ROLLBACK_RESOURCE_NON_EMPTY_INITIALIZE";break;} + case -1074396093: + { errorText = "ERR_ROLLBACK_RESOURCE_LOCKED";break;} + case -1074396094: + { errorText = "ERR_ROLLBACK_RESOURCE_CANNOT_UNLOCK";break;} + case -1074396095: + { errorText = "ERR_CALIBRATION_DUPLICATE_REFERENCE_POINT";break;} + case -1074396096: + { errorText = "ERR_NOT_AN_OBJECT";break;} + case -1074396097: + { errorText = "ERR_INVALID_PARTICLE_PARAMETER_VALUE";break;} + case -1074396098: + { errorText = "ERR_RESERVED_MUST_BE_NULL";break;} + case -1074396099: + { errorText = "ERR_CALIBRATION_INFO_SIMPLE_TRANSFORM";break;} + case -1074396100: + { errorText = "ERR_CALIBRATION_INFO_PERSPECTIVE_PROJECTION";break;} + case -1074396101: + { errorText = "ERR_CALIBRATION_INFO_MICRO_PLANE";break;} + case -1074396102: + { errorText = "ERR_CALIBRATION_INFO_6";break;} + case -1074396103: + { errorText = "ERR_CALIBRATION_INFO_5";break;} + case -1074396104: + { errorText = "ERR_CALIBRATION_INFO_4";break;} + case -1074396105: + { errorText = "ERR_CALIBRATION_INFO_3";break;} + case -1074396106: + { errorText = "ERR_CALIBRATION_INFO_2";break;} + case -1074396107: + { errorText = "ERR_CALIBRATION_INFO_1";break;} + case -1074396108: + { errorText = "ERR_CALIBRATION_ERRORMAP";break;} + case -1074396109: + { errorText = "ERR_CALIBRATION_INVALID_SCALING_FACTOR";break;} + case -1074396110: + { errorText = "ERR_CALIBRATION_INFO_VERSION";break;} + case -1074396111: + { errorText = "ERR_CALIBRATION_FAILED_TO_FIND_GRID";break;} + case -1074396112: + { errorText = "ERR_INCOMP_MATRIX_SIZE";break;} + case -1074396113: + { errorText = "ERR_CALIBRATION_IMAGE_UNCALIBRATED";break;} + case -1074396114: + { errorText = "ERR_CALIBRATION_INVALID_ROI";break;} + case -1074396115: + { errorText = "ERR_CALIBRATION_IMAGE_CORRECTED";break;} + case -1074396116: + { errorText = "ERR_CALIBRATION_INSF_POINTS";break;} + case -1074396117: + { errorText = "ERR_MATRIX_SIZE";break;} + case -1074396118: + { errorText = "ERR_INVALID_STEP_SIZE";break;} + case -1074396119: + { errorText = "ERR_CUSTOMDATA_INVALID_KEY";break;} + case -1074396120: + { errorText = "ERR_NOT_IMAGE";break;} + case -1074396121: + { errorText = "ERR_SATURATION_THRESHOLD_OUT_OF_RANGE";break;} + case -1074396122: + { errorText = "ERR_DRAWTEXT_COLOR_MUST_BE_GRAYSCALE";break;} + case -1074396123: + { errorText = "ERR_INVALID_CALIBRATION_MODE";break;} + case -1074396124: + { errorText = "ERR_INVALID_CALIBRATION_ROI_MODE";break;} + case -1074396125: + { errorText = "ERR_INVALID_CONTRAST_THRESHOLD";break;} + case -1074396126: + { errorText = "ERR_ROLLBACK_RESOURCE_CONFLICT_1";break;} + case -1074396127: + { errorText = "ERR_ROLLBACK_RESOURCE_CONFLICT_2";break;} + case -1074396128: + { errorText = "ERR_ROLLBACK_RESOURCE_CONFLICT_3";break;} + case -1074396129: + { errorText = "ERR_ROLLBACK_UNBOUNDED_INTERFACE";break;} + case -1074396130: + { errorText = "ERR_NOT_RECT_OR_ROTATED_RECT";break;} + case -1074396132: + { errorText = "ERR_MASK_NOT_TEMPLATE_SIZE";break;} + case -1074396133: + { errorText = "ERR_THREAD_COULD_NOT_INITIALIZE";break;} + case -1074396134: + { errorText = "ERR_THREAD_INITIALIZING";break;} + case -1074396135: + { errorText = "ERR_INVALID_BUTTON_LABEL";break;} + case -1074396136: + { errorText = "ERR_DIRECTX_INVALID_FILTER_QUALITY";break;} + case -1074396137: + { errorText = "ERR_DIRECTX_DLL_NOT_FOUND";break;} + case -1074396138: + { errorText = "ERR_ROLLBACK_NOT_SUPPORTED";break;} + case -1074396139: + { errorText = "ERR_ROLLBACK_RESOURCE_OUT_OF_MEMORY";break;} + case -1074396140: + { errorText = "ERR_BARCODE_CODE128_SET";break;} + case -1074396141: + { errorText = "ERR_BARCODE_CODE128_FNC";break;} + case -1074396142: + { errorText = "ERR_BARCODE_INVALID";break;} + case -1074396143: + { errorText = "ERR_BARCODE_TYPE";break;} + case -1074396144: + { errorText = "ERR_BARCODE_CODE93_SHIFT";break;} + case -1074396145: + { errorText = "ERR_BARCODE_UPCA";break;} + case -1074396146: + { errorText = "ERR_BARCODE_MSI";break;} + case -1074396147: + { errorText = "ERR_BARCODE_I25";break;} + case -1074396148: + { errorText = "ERR_BARCODE_EAN13";break;} + case -1074396149: + { errorText = "ERR_BARCODE_EAN8";break;} + case -1074396150: + { errorText = "ERR_BARCODE_CODE128";break;} + case -1074396151: + { errorText = "ERR_BARCODE_CODE93";break;} + case -1074396152: + { errorText = "ERR_BARCODE_CODE39";break;} + case -1074396153: + { errorText = "ERR_BARCODE_CODABAR";break;} + case -1074396154: + { errorText = "ERR_IMAGE_TOO_SMALL";break;} + case -1074396155: + { errorText = "ERR_UNINIT";break;} + case -1074396156: + { errorText = "ERR_NEED_FULL_VERSION";break;} + case -1074396157: + { errorText = "ERR_UNREGISTERED";break;} + case -1074396158: + { errorText = "ERR_MEMORY_ERROR";break;} + case -1074396159: + { errorText = "ERR_OUT_OF_MEMORY";break;} + case -1074396160: + { errorText = "ERR_SYSTEM_ERROR";break;} + case 0: + { errorText = "ERR_SUCCESS";break;} + // end National Instruments defined errors + + // begin BAE defined errors + case ERR_VISION_GENERAL_ERROR: + { errorText = "ERR_VISION_GENERAL_ERROR";break;} + case ERR_COLOR_NOT_FOUND: + { errorText = "ERR_COLOR_NOT_FOUND";break;} + case ERR_PARTICLE_TOO_SMALL: + { errorText = "ERR_PARTICLE_TOO_SMALL";break;} + case ERR_CAMERA_FAILURE: + { errorText = "ERR_CAMERA_FAILURE";break;} + case ERR_CAMERA_SOCKET_CREATE_FAILED: + { errorText = "ERR_CAMERA_SOCKET_CREATE_FAILED";break;} + case ERR_CAMERA_CONNECT_FAILED: + { errorText = "ERR_CAMERA_CONNECT_FAILED";break;} + case ERR_CAMERA_STALE_IMAGE: + { errorText = "ERR_CAMERA_STALE_IMAGE";break;} + case ERR_CAMERA_NOT_INITIALIZED: + { errorText = "ERR_CAMERA_NOT_INITIALIZED";break;} + case ERR_CAMERA_NO_BUFFER_AVAILABLE: + { errorText = "ERR_CAMERA_NO_BUFFER_AVAILABLE";break;} + case ERR_CAMERA_HEADER_ERROR: + { errorText = "ERR_CAMERA_HEADER_ERROR";break;} + case ERR_CAMERA_BLOCKING_TIMEOUT: + { errorText = "ERR_CAMERA_BLOCKING_TIMEOUT";break;} + case ERR_CAMERA_AUTHORIZATION_FAILED: + { errorText = "ERR_CAMERA_AUTHORIZATION_FAILED";break;} + case ERR_CAMERA_TASK_SPAWN_FAILED: + { errorText = "ERR_CAMERA_TASK_SPAWN_FAILED";break;} + case ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE: + { errorText = "ERR_CAMERA_TASK_INPUT_OUT_OF_RANGE";break;} + case ERR_CAMERA_COMMAND_FAILURE: + { errorText = "ERR_CAMERA_COMMAND_FAILURE";break;} + } + + return errorText; +} + + + diff --git a/wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp b/wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp new file mode 100644 index 0000000000..1a6694901b --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/HSLImage.cpp @@ -0,0 +1,28 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "Vision/HSLImage.h" + +/** + * Create a new image that uses the Hue, Saturation, and Luminance planes. + */ +HSLImage::HSLImage() : ColorImage(IMAQ_IMAGE_HSL) +{ +} + +/** + * Create a new image by loading a file. + * @param fileName The path of the file to load. + */ +HSLImage::HSLImage(const char *fileName) : ColorImage(IMAQ_IMAGE_HSL) +{ + int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL); + wpi_setImaqErrorWithContext(success, "Imaq ReadFile error"); +} + +HSLImage::~HSLImage() +{ +} diff --git a/wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp b/wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp new file mode 100644 index 0000000000..ba549b6e0a --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/ImageBase.cpp @@ -0,0 +1,73 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "Vision/ImageBase.h" +#include "nivision.h" + +/** + * Create a new instance of an ImageBase. + * Imagebase is the base of all the other image classes. The constructor + * creates any type of image and stores the pointer to it in the class. + * @param type The type of image to create + */ +ImageBase::ImageBase(ImageType type) +{ + m_imaqImage = imaqCreateImage(type, DEFAULT_BORDER_SIZE); +} + +/** + * Frees memory associated with an ImageBase. + * Destructor frees the imaq image allocated with the class. + */ +ImageBase::~ImageBase() +{ + if(m_imaqImage) + imaqDispose(m_imaqImage); +} + +/** + * Writes an image to a file with the given filename. + * Write the image to a file in the flash on the cRIO. + * @param fileName The name of the file to write + */ +void ImageBase::Write(const char *fileName) +{ + int success = imaqWriteFile(m_imaqImage, fileName, NULL); + wpi_setImaqErrorWithContext(success, "Imaq Image writeFile error"); +} + +/** + * Gets the height of an image. + * @return The height of the image in pixels. + */ +int ImageBase::GetHeight() +{ + int height; + imaqGetImageSize(m_imaqImage, NULL, &height); + return height; +} + +/** + * Gets the width of an image. + * @return The width of the image in pixels. + */ +int ImageBase::GetWidth() +{ + int width; + imaqGetImageSize(m_imaqImage, &width, NULL); + return width; +} + +/** + * Access the internal IMAQ Image data structure. + * + * @return A pointer to the internal IMAQ Image data structure. + */ +Image *ImageBase::GetImaqImage() +{ + return m_imaqImage; +} + diff --git a/wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp b/wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp new file mode 100644 index 0000000000..17efe2012e --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/MonoImage.cpp @@ -0,0 +1,55 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "Vision/MonoImage.h" +#include "nivision.h" + +using namespace std; + +MonoImage::MonoImage() : ImageBase(IMAQ_IMAGE_U8) +{ +} + +MonoImage::~MonoImage() +{ +} + +/** + * Look for ellipses in an image. + * Given some input parameters, look for any number of ellipses in an image. + * @param ellipseDescriptor Ellipse descriptor + * @param curveOptions Curve options + * @param shapeDetectionOptions Shape detection options + * @param roi Region of Interest + * @returns a vector of EllipseMatch structures (0 length vector on no match) + */ +vector * MonoImage::DetectEllipses( + EllipseDescriptor *ellipseDescriptor, CurveOptions *curveOptions, + ShapeDetectionOptions *shapeDetectionOptions, ROI *roi) +{ + int numberOfMatches; + EllipseMatch *e = imaqDetectEllipses(m_imaqImage, ellipseDescriptor, + curveOptions, shapeDetectionOptions, roi, &numberOfMatches); + vector *ellipses = new vector; + if (e == NULL) + { + return ellipses; + } + for (int i = 0; i < numberOfMatches; i++) + { + ellipses->push_back(e[i]); + } + imaqDispose(e); + return ellipses; +} + +vector * MonoImage::DetectEllipses( + EllipseDescriptor *ellipseDescriptor) +{ + vector *ellipses = DetectEllipses(ellipseDescriptor, NULL, + NULL, NULL); + return ellipses; +} diff --git a/wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp b/wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp new file mode 100644 index 0000000000..a34212e686 --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/RGBImage.cpp @@ -0,0 +1,28 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "Vision/RGBImage.h" + +/** + * Create a new image that uses Red, Green, and Blue planes. + */ +RGBImage::RGBImage() : ColorImage(IMAQ_IMAGE_RGB) +{ +} + +/** + * Create a new image by loading a file. + * @param fileName The path of the file to load. + */ +RGBImage::RGBImage(const char *fileName) : ColorImage(IMAQ_IMAGE_RGB) +{ + int success = imaqReadFile(m_imaqImage, fileName, NULL, NULL); + wpi_setImaqErrorWithContext(success, "Imaq ReadFile error"); +} + +RGBImage::~RGBImage() +{ +} diff --git a/wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp b/wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp new file mode 100644 index 0000000000..1d81b388ea --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/Threshold.cpp @@ -0,0 +1,18 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include "Vision/Threshold.h" + +Threshold::Threshold(int new_plane1Low, int new_plane1High, int new_plane2Low, + int new_plane2High, int new_plane3Low, int new_plane3High) +{ + plane1Low = new_plane1Low; + plane1High = new_plane1High; + plane2Low = new_plane2Low; + plane2High = new_plane2High; + plane3Low = new_plane3Low; + plane3High = new_plane3High; +} diff --git a/wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp b/wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp new file mode 100644 index 0000000000..7ac3ac91ab --- /dev/null +++ b/wpilibc/wpilibC++Devices/src/Vision/VisionAPI.cpp @@ -0,0 +1,665 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2014. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ +/*----------------------------------------------------------------------------*/ + +#include +#include + +#include "Vision/BaeUtilities.h" +#include "Vision/FrcError.h" +#include "Vision/VisionAPI.h" + +int VisionAPI_debugFlag = 1; +#define DPRINTF if(VisionAPI_debugFlag)dprintf + +/* Image Management functions */ + +/** +* @brief Create an image object +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64 +* The border size is defaulted to 3 so that convolutional algorithms work at the edges. +* When you are finished with the created image, dispose of it by calling frcDispose(). +* To get extended error information, call GetLastError(). +* +* @param type Type of image to create +* @return Image* On success, this function returns the created image. On failure, it returns NULL. +*/ +Image* frcCreateImage(ImageType type) { return imaqCreateImage(type, DEFAULT_BORDER_SIZE); } + +/** +* @brief Dispose of one object. Supports any object created on the heap. +* +* @param object object to dispose of +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcDispose(void* object) { return imaqDispose(object); } +/** +* @brief Dispose of a list of objects. Supports any object created on the heap. +* +* @param functionName The name of the function +* @param ... A list of pointers to structures that need to be disposed of. +* The last pointer in the list should always be set to NULL. +* +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcDispose( const char* functionName, ... ) /* Variable argument list */ +{ + va_list disposalPtrList; /* Input argument list */ + void* disposalPtr; /* For iteration */ + int success, returnValue = 1; + + va_start( disposalPtrList, functionName ); /* start of variable list */ + disposalPtr = va_arg( disposalPtrList, void* ); + while( disposalPtr != NULL ) { + success = imaqDispose(disposalPtr); + if (!success) {returnValue = 0;} + disposalPtr = va_arg( disposalPtrList, void* ); + } + return returnValue; +} + +/** +* @brief Copy an image object. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL. +* +* @param dest Copy of image. On failure, dest is NULL. Must have already been created using frcCreateImage(). +* When you are finished with the created image, dispose of it by calling frcDispose(). +* @param source Image to copy +* +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcCopyImage(Image* dest, const Image* source) { return imaqDuplicate(dest, source); } + +/** +* @brief Crop image without changing the scale. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL. +* +* @param dest Modified image +* @param source Image to crop +* @param rect region to process, or IMAQ_NO_RECT +* +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcCrop(Image* dest, const Image* source, Rect rect) +{ + return imaqScale(dest, source, 1, 1, IMAQ_SCALE_LARGER, rect); +} + + +/** +* @brief Scales the entire image larger or smaller. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL. +* +* @param dest Modified image +* @param source Image to scale +* @param xScale the horizontal reduction ratio +* @param yScale the vertical reduction ratio +* @param scaleMode IMAQ_SCALE_LARGER or IMAQ_SCALE_SMALLER +* +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcScale(Image* dest, const Image* source, int xScale, int yScale, ScalingMode scaleMode) +{ + Rect rect = IMAQ_NO_RECT; + return imaqScale(dest, source, xScale, yScale, scaleMode, rect); +} + +/** + * @brief Creates image object from the information in a file. The file can be in one of the following formats: + * PNG, JPEG, JPEG2000, TIFF, AIPD, or BMP. + * Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64. + * + * @param image Image read in + * @param fileName File to read. Cannot be NULL + * + * @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). + */ + int frcReadImage(Image* image, const char* fileName) + { + return imaqReadFile(image, fileName, NULL, NULL); + } + + + /** + * @brief Write image to a file. + * Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL, IMAQ_IMAGE_COMPLEX, IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL, IMAQ_IMAGE_RGB_U64. + * + * The file type is determined by the extension, as follows: + * + * Extension File Type + * aipd or .apd AIPD + * .bmp BMP + * .jpg or .jpeg JPEG + * .jp2 JPEG2000 + * .png PNG + * .tif or .tiff TIFF + * + * + *The following are the supported image types for each file type: + * + * File Types Image Types + * AIPD all image types + * BMP, JPEG 8-bit, RGB + * PNG, TIFF, JPEG2000 8-bit, 16-bit, RGB, RGBU64 + * + * @param image Image to write + * @param fileName File to read. Cannot be NULL. The extension determines the file format that is written. + * + * @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). + */ +int frcWriteImage(const Image* image, const char* fileName) +{ + RGBValue* colorTable = NULL; + return imaqWriteFile(image, fileName, colorTable); +} + + +/* Measure Intensity functions */ + +/** +* @brief Measures the pixel intensities in a rectangle of an image. +* Outputs intensity based statistics about an image such as Max, Min, Mean and Std Dev of pixel value. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL. +* +* Parameter Discussion : +* Relevant parameters of the HistogramReport include: +* min, max, mean and stdDev +* min/max —Setting both min and max to 0 causes the function to set min to 0 +* and the max to 255 for 8-bit images and to the actual minimum value and +* maximum value of the image for all other image types. +* max—Setting both min and max to 0 causes the function to set max to 255 +* for 8-bit images and to the actual maximum value of the image for +* all other image types. +* +* @param image Image whose histogram the function calculates. +* @param numClasses The number of classes into which the function separates the pixels. +* Determines the number of elements in the histogram array returned +* @param min The minimum pixel value to consider for the histogram. +* The function does not count pixels with values less than min. +* @param max The maximum pixel value to consider for the histogram. +* The function does not count pixels with values greater than max. +* @param rect Region of interest in the image. If not included, the entire image is used. +* @return On success, this function returns a report describing the pixel value classification. +* When you are finished with the report, dispose of it by calling frcDispose(). +* On failure, this function returns NULL. To get extended error information, call GetLastError(). +* +*/ +HistogramReport* frcHistogram(const Image* image, int numClasses, float min, float max) +{ + Rect rect = IMAQ_NO_RECT; + return frcHistogram(image, numClasses, min, max, rect); +} +HistogramReport* frcHistogram(const Image* image, int numClasses, float min, float max, Rect rect) +{ + int success; + int fillValue = 1; + + /* create the region of interest */ + ROI* pRoi = imaqCreateROI(); + success = imaqAddRectContour(pRoi, rect); + if ( !success ) { GetLastVisionError(); return NULL; } + + /* make a mask from the ROI */ + Image* pMask = frcCreateImage(IMAQ_IMAGE_U8); + success = imaqROIToMask(pMask, pRoi, fillValue, NULL, NULL); + if ( !success ) { + GetLastVisionError(); + frcDispose(__FUNCTION__, pRoi, NULL); + return NULL; + } + + /* get a histogram report */ + HistogramReport* pHr = NULL; + pHr = imaqHistogram(image, numClasses, min, max, pMask); + + /* clean up */ + frcDispose(__FUNCTION__, pRoi, pMask, NULL); + + return pHr; +} + +/** +* @brief Calculates the histogram, or pixel distribution, of a color image. +* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL. +* +* @param image Image whose histogram the function calculates. +* @param numClasses The number of classes into which the function separates the pixels. +* Determines the number of elements in the histogram array returned +* @param mode The color space in which to perform the histogram. Possible values include IMAQ_RGB and IMAQ_HSL. +* @param mask An optional mask image. This image must be an IMAQ_IMAGE_U8 image. +* The function calculates the histogram using only those pixels in the image whose +* corresponding pixels in the mask are non-zero. Set this parameter to NULL to calculate +* the histogram of the entire image, or use the simplified call. +* +* @return On success, this function returns a report describing the classification +* of each plane in a HistogramReport. +* When you are finished with the report, dispose of it by calling frcDispose(). +* On failure, this function returns NULL. +* To get extended error information, call imaqGetLastError(). +*/ +ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode) +{ + return frcColorHistogram(image, numClasses, mode, NULL); +} + +ColorHistogramReport* frcColorHistogram(const Image* image, int numClasses, ColorMode mode, Image* mask) +{ + return imaqColorHistogram2((Image*)image, numClasses, mode, NULL, mask); +} + + +/** +* @brief Measures the pixel intensities in a rectangle of an image. +* Outputs intensity based statistics about an image such as Max, Min, Mean and Std Dev of pixel value. +* Supports IMAQ_IMAGE_U8 (grayscale) IMAQ_IMAGE_RGB (color) IMAQ_IMAGE_HSL (color-HSL). +* +* @param image The image whose pixel value the function queries +* @param pixel The coordinates of the pixel that the function queries +* @param value On return, the value of the specified image pixel. This parameter cannot be NULL. +* This data structure contains either grayscale, RGB, HSL, Complex or RGBU64Value depending on the type of image. +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcGetPixelValue(const Image* image, Point pixel, PixelValue* value) +{ + return imaqGetPixel(image, pixel, value); +} + + +/* Particle Analysis functions */ + +/** +* @brief Filters particles out of an image based on their measurements. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL. +* +* @param dest The destination image. If dest is used, it must be the same size as the Source image. It will contain only the filtered particles. +* @param source The image containing the particles to filter. +* @param criteria An array of criteria to apply to the particles in the source image. This array cannot be NULL. +* See the NIVisionCVI.chm help file for definitions of criteria. +* @param criteriaCount The number of elements in the criteria array. +* @param options Binary filter options, including rejectMatches, rejectBorder, and connectivity8. +* @param rect Area of image to filter. If omitted, the default is entire image. +* @param numParticles On return, the number of particles left in the image +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, + int criteriaCount, const ParticleFilterOptions* options, int* numParticles) +{ + Rect rect = IMAQ_NO_RECT; + return frcParticleFilter(dest, source, criteria, criteriaCount, options, rect, numParticles); +} + +int frcParticleFilter(Image* dest, Image* source, const ParticleFilterCriteria2* criteria, + int criteriaCount, const ParticleFilterOptions* options, Rect rect, int* numParticles) +{ + ROI* roi = imaqCreateROI(); + imaqAddRectContour(roi, rect); + return imaqParticleFilter3(dest, source, criteria, criteriaCount, options, roi, numParticles); +} + + +/** +* @brief Performs morphological transformations on binary images. +* Supports IMAQ_IMAGE_U8. +* +* @param dest The destination image. The border size of the destination image is not important. +* @param source The image on which the function performs the morphological operations. The calculation +* modifies the border of the source image. The border must be at least half as large as the larger +* dimension of the structuring element. The connected source image for a morphological transformation +* must have been created with a border capable of supporting the size of the structuring element. +* A 3 by 3 structuring element requires a minimal border of 1, a 5 by 5 structuring element requires a minimal border of 2, and so on. +* @param method The morphological transform to apply. +* @param structuringElement The structuring element used in the operation. Omit this parameter if you do not want a custom structuring element. +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcMorphology(Image* dest, Image* source, MorphologyMethod method) +{ + return imaqMorphology(dest, source, method, NULL); +} + +int frcMorphology(Image* dest, Image* source, MorphologyMethod method, const StructuringElement* structuringElement) +{ + return imaqMorphology(dest, source, method, structuringElement); +} + +/** +* @brief Eliminates particles that touch the border of the image. +* Supports IMAQ_IMAGE_U8. +* +* @param dest The destination image. +* @param source The source image. If the image has a border, the function sets all border pixel values to 0. +* @param connectivity8 specifies the type of connectivity used by the algorithm for particle detection. +* The connectivity mode directly determines whether an adjacent pixel belongs to the same particle or a +* different particle. Set to TRUE to use connectivity-8 to determine whether particles are touching +* Set to FALSE to use connectivity-4 to determine whether particles are touching. +* The default setting for the simplified call is TRUE +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcRejectBorder(Image* dest, Image* source) +{ return imaqRejectBorder(dest, source, TRUE); } + +int frcRejectBorder(Image* dest, Image* source, int connectivity8) +{ + return imaqRejectBorder(dest, source, connectivity8); +} + + +/** +* @brief Counts the number of particles in a binary image. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL. +* @param image binary (thresholded) image +* @param numParticles On return, the number of particles. +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcCountParticles(Image* image, int* numParticles) +{ + return imaqCountParticles(image, 1, numParticles); +} + + +/** +* @brief Conduct measurements for a single particle in an images. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16, IMAQ_IMAGE_SGL. +* +* @param image image with the particle to analyze. This function modifies the source image. +* If you need the original image, create a copy of the image using frcCopy() before using this function. +* @param particleNumber The number of the particle to get information on +* @param par on return, a particle analysis report containing information about the particle. This structure must be created by the caller. +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcParticleAnalysis(Image* image, int particleNumber, ParticleAnalysisReport* par) +{ + int success = 0; + + /* image information */ + int height, width; + if ( ! imaqGetImageSize(image, &width, &height) ) { return success; } + par->imageWidth = width; + par->imageHeight = height; + par->particleIndex = particleNumber; + + /* center of mass point of the largest particle */ + double returnDouble; + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_CENTER_OF_MASS_X, &returnDouble); + if ( !success ) { return success; } + par->center_mass_x = (int)returnDouble; // pixel + + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_CENTER_OF_MASS_Y, &returnDouble); + if ( !success ) { return success; } + par->center_mass_y = (int)returnDouble; // pixel + + /* particle size statistics */ + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA, &returnDouble); + if ( !success ) { return success; } + par->particleArea = returnDouble; + + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_TOP, &returnDouble); + if ( !success ) { return success; } + par->boundingRect.top = (int)returnDouble; + + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_LEFT, &returnDouble); + if ( !success ) { return success; } + par->boundingRect.left = (int)returnDouble; + + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_HEIGHT, &returnDouble); + if ( !success ) { return success; } + par->boundingRect.height = (int)returnDouble; + + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_BOUNDING_RECT_WIDTH, &returnDouble); + if ( !success ) { return success; } + par->boundingRect.width = (int)returnDouble; + + /* particle quality statistics */ + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA_BY_IMAGE_AREA, &returnDouble); + if ( !success ) { return success; } + par->particleToImagePercent = returnDouble; + + success = imaqMeasureParticle(image, particleNumber, 0, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &returnDouble); + if ( !success ) { return success; } + par->particleQuality = returnDouble; + + /* normalized position (-1 to 1) */ + par->center_mass_x_normalized = RangeToNormalized(par->center_mass_x, width); + par->center_mass_y_normalized = RangeToNormalized(par->center_mass_y, height); + + return success; +} + + +/* Image Enhancement functions */ + +/** +* @brief Improves contrast on a grayscale image. +* Supports IMAQ_IMAGE_U8, IMAQ_IMAGE_I16. +* @param dest The destination image. +* @param source The image to equalize +* @param min the smallest value used for processing. After processing, all pixel values that are less than or equal to the Minimum in the original image are set to 0 for an 8-bit image. In 16-bit and floating-point images, these pixel values are set to the smallest pixel value found in the original image. +* @param max the largest value used for processing. After processing, all pixel values that are greater than or equal to the Maximum in the original image are set to 255 for an 8-bit image. In 16-bit and floating-point images, these pixel values are set to the largest pixel value found in the original image. +* @param mask an 8-bit image that specifies the region of the small image that will be copied. Only those pixels in the Image Src (Small) image that correspond to an equivalent non-zero pixel in the mask image are copied. All other pixels keep their original values. The entire image is processed if Image Mask is NULL or this parameter is omitted. +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +* +* option defaults: +* searchRect = IMAQ_NO_RECT +* minMatchScore = DEFAULT_MINMAX_SCORE (800) +*/ +int frcEqualize(Image* dest, const Image* source, float min, float max) +{ return frcEqualize(dest, source, min, max, NULL); } + +int frcEqualize(Image* dest, const Image* source, float min, float max, const Image* mask) +{ + return imaqEqualize(dest, source, min, max, mask); +} + +/** +* @brief Improves contrast on a color image. +* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL +* +* option defaults: colorEqualization = TRUE to equalize all three planes of the image +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +* @param dest The destination image. +* @param source The image to equalize +* @param colorEqualization Set this parameter to TRUE to equalize all three planes of the image (the default). Set this parameter to FALSE to equalize only the luminance plane. +*/ +int frcColorEqualize(Image* dest, const Image* source) +{ + return imaqColorEqualize(dest, source, TRUE); +} + +int frcColorEqualize(Image* dest, const Image* source, int colorEqualization) +{ + return imaqColorEqualize(dest, source, TRUE); +} + +/* Image Conversion functions */ + +/** +* @brief Automatically thresholds a grayscale image into a binary image for Particle Analysis based on a smart threshold. +* Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_I16 +* @param dest The destination image. +* @param source The image to threshold +* @param windowWidth The width of the rectangular window around the pixel on which the function +* performs the local threshold. This number must be at least 3 and cannot be larger than the width of source +* @param windowHeight The height of the rectangular window around the pixel on which the function +* performs the local threshold. This number must be at least 3 and cannot be larger than the height of source +* @param method Specifies the local thresholding method the function uses. Value can be IMAQ_NIBLACK +* (which computes thresholds for each pixel based on its local statistics using the Niblack local thresholding +* algorithm.), or IMAQ_BACKGROUND_CORRECTION (which does background correction first to eliminate non-uniform +* lighting effects, then performs thresholding using the Otsu thresholding algorithm) +* @param deviationWeight Specifies the k constant used in the Niblack local thresholding algorithm, which +* determines the weight applied to the variance calculation. Valid k constants range from 0 to 1. Setting +* this value to 0 will increase the performance of the function because the function will not calculate the +* variance for any of the pixels. The function ignores this value if method is not set to IMAQ_NIBLACK +* @param type Specifies the type of objects for which you want to look. Values can be IMAQ_BRIGHT_OBJECTS +* or IMAQ_DARK_OBJECTS. +* @param replaceValue Specifies the replacement value the function uses for the pixels of the kept objects +* in the destination image. +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcSmartThreshold(Image* dest, const Image* source, + unsigned int windowWidth, unsigned int windowHeight, LocalThresholdMethod method, + double deviationWeight, ObjectType type) +{ + float replaceValue = 1.0; + return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method, + deviationWeight, type, replaceValue); +} + +int frcSmartThreshold(Image* dest, const Image* source, + unsigned int windowWidth, unsigned int windowHeight, LocalThresholdMethod method, + double deviationWeight, ObjectType type, float replaceValue) +{ + return imaqLocalThreshold(dest, source, windowWidth, windowHeight, method, + deviationWeight, type, replaceValue); +} + +/** +* @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 a given value or leaves the values unchanged. +* Use the simplified call to leave pixel values unchanged. +* 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. +* +* @return int - error code: 0 = error. To get extended error information, call GetLastError(). +*/ +int frcSimpleThreshold(Image* dest, const Image* source, float rangeMin, float rangeMax) +{ + int newValue = 255; + return frcSimpleThreshold(dest, source, rangeMin, rangeMax, newValue); +} + +/** +* @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); +} + +/** +* @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 NULL 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 NULL 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 NULL 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); +} + +/** +* @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. +* The 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 replaceValue Value to assign to selected pixels. Defaults to 1 if simplified call is used. +* @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 NULL 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 NULL 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 NULL 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, int replaceValue, ColorMode mode, + const Range* plane1Range, const Range* plane2Range, const Range* plane3Range) +{ return imaqColorThreshold(dest, source, replaceValue, mode, plane1Range, plane2Range, plane3Range);} + + +/** +* @brief A simpler version of ColorThreshold that thresholds hue range in the HSL mode. Supports IMAQ_IMAGE_RGB, IMAQ_IMAGE_HSL. +* @param dest The destination image. +* @param source The image to threshold +* @param hueRange The selection range for the hue (color). +* @param minSaturation The minimum saturation value (1-255). If not used, DEFAULT_SATURATION_THRESHOLD is the default. +* +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcHueThreshold(Image* dest, const Image* source, const Range* hueRange) +{ return frcHueThreshold(dest, source, hueRange, DEFAULT_SATURATION_THRESHOLD); } + +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); +} + +/** +* @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); } + +/** +* @brief Extracts the Hue 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 plane from. +* @param huePlane On return, the extracted hue plane. +* @param minSaturation the minimum saturation level required 0-255 (try 50) +* +* @return On success: 1. On failure: 0. To get extended error information, call GetLastError(). +*/ +int frcExtractHuePlane(const Image* image, Image* huePlane) +{ + return frcExtractHuePlane(image, huePlane, DEFAULT_SATURATION_THRESHOLD); +} + +int frcExtractHuePlane(const Image* image, Image* huePlane, int minSaturation) +{ + return frcExtractColorPlanes(image, IMAQ_HSL, huePlane, NULL, NULL); +} + + + + + + + +