Now you can download a copy of these docs so you can use them offline! Download now
BinaryImage.cpp
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) FIRST 2008. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5 /*----------------------------------------------------------------------------*/
6 
7 #include "BinaryImage.h"
8 #include "WPIErrors.h"
9 #include <cstring>
10 
12 IMAQ_FUNC int Priv_SetWriteFileAllowed(uint32_t enable);
13 
14 BinaryImage::BinaryImage() : MonoImage()
15 {
16 }
17 
18 BinaryImage::~BinaryImage()
19 {
20 }
21 
27 {
28  int numParticles = 0;
29  int success = imaqCountParticles(m_imaqImage, 1, &numParticles);
30  wpi_setImaqErrorWithContext(success, "Error counting particles");
31  return numParticles;
32 }
33 
41 {
43  GetParticleAnalysisReport(particleNumber, &par);
44  return par;
45 }
46 
55 {
56  int success;
57  int numParticles = 0;
58 
59  success = imaqGetImageSize(m_imaqImage, &par->imageWidth, &par->imageHeight);
60  wpi_setImaqErrorWithContext(success, "Error getting image size");
61  if (StatusIsFatal())
62  return;
63 
64  success = imaqCountParticles(m_imaqImage, 1, &numParticles);
65  wpi_setImaqErrorWithContext(success, "Error counting particles");
66  if (StatusIsFatal())
67  return;
68 
69  if (particleNumber >= numParticles)
70  {
71  wpi_setWPIErrorWithContext(ParameterOutOfRange, "particleNumber");
72  return;
73  }
74 
75  par->particleIndex = particleNumber;
76  // Don't bother measuring the rest of the particle if one fails
77  bool good = ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_X, &par->center_mass_x);
78  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_CENTER_OF_MASS_Y, &par->center_mass_y);
79  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA, &par->particleArea);
80  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_TOP, &par->boundingRect.top);
81  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_LEFT, &par->boundingRect.left);
82  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_HEIGHT, &par->boundingRect.height);
83  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_BOUNDING_RECT_WIDTH, &par->boundingRect.width);
84  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_IMAGE_AREA, &par->particleToImagePercent);
85  good = good && ParticleMeasurement(particleNumber, IMAQ_MT_AREA_BY_PARTICLE_AND_HOLES_AREA, &par->particleQuality);
86 
87  if (good)
88  {
89  /* normalized position (-1 to 1) */
90  par->center_mass_x_normalized = NormalizeFromRange(par->center_mass_x, par->imageWidth);
91  par->center_mass_y_normalized = NormalizeFromRange(par->center_mass_y, par->imageHeight);
92  }
93 }
94 
95 
103 vector<ParticleAnalysisReport>* BinaryImage::GetOrderedParticleAnalysisReports()
104 {
105  vector<ParticleAnalysisReport>* particles = new vector<ParticleAnalysisReport>;
106  int particleCount = GetNumberParticles();
107  for(int particleIndex = 0; particleIndex < particleCount; particleIndex++)
108  {
109  particles->push_back(GetParticleAnalysisReport(particleIndex));
110  }
111  // TODO: This is pretty inefficient since each compare in the sort copies
112  // both reports being compared... do it manually instead... while we're
113  // at it, we should provide a version that allows a preallocated buffer of
114  // ParticleAnalysisReport structures
115  sort(particles->begin(), particles->end(), CompareParticleSizes);
116  return particles;
117 }
118 
124 void BinaryImage::Write(const char *fileName)
125 {
126  RGBValue colorTable[256];
127  Priv_SetWriteFileAllowed(1);
128  memset(colorTable, 0, sizeof(colorTable));
129  colorTable[0].R = 0;
130  colorTable[1].R = 255;
131  colorTable[0].G = colorTable[1].G = 0;
132  colorTable[0].B = colorTable[1].B = 0;
133  colorTable[0].alpha = colorTable[1].alpha = 0;
134  imaqWriteFile(m_imaqImage, fileName, colorTable);
135 }
136 
146 bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, int *result)
147 {
148  double resultDouble;
149  bool success = ParticleMeasurement(particleNumber, whatToMeasure, &resultDouble);
150  *result = (int)resultDouble;
151  return success;
152 }
153 
163 bool BinaryImage::ParticleMeasurement(int particleNumber, MeasurementType whatToMeasure, double *result)
164 {
165  int success;
166  success = imaqMeasureParticle(m_imaqImage, particleNumber, 0, whatToMeasure, result);
167  wpi_setImaqErrorWithContext(success, "Error measuring particle");
168  return !StatusIsFatal();
169 }
170 
171 //Normalizes to [-1,1]
172 double BinaryImage::NormalizeFromRange(double position, int range)
173 {
174  return (position * 2.0 / (double)range) - 1.0;
175 }
176 
184 bool BinaryImage::CompareParticleSizes(ParticleAnalysisReport particle1, ParticleAnalysisReport particle2)
185 {
186  //we want descending sort order
187  return particle1.particleToImagePercent > particle2.particleToImagePercent;
188 }
189 
190 BinaryImage *BinaryImage::RemoveSmallObjects(bool connectivity8, int erosions)
191 {
192  BinaryImage *result = new BinaryImage();
193  int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_LARGE, NULL);
194  wpi_setImaqErrorWithContext(success, "Error in RemoveSmallObjects");
195  return result;
196 }
197 
198 BinaryImage *BinaryImage::RemoveLargeObjects(bool connectivity8, int erosions)
199 {
200  BinaryImage *result = new BinaryImage();
201  int success = imaqSizeFilter(result->GetImaqImage(), m_imaqImage, connectivity8, erosions, IMAQ_KEEP_SMALL, NULL);
202  wpi_setImaqErrorWithContext(success, "Error in RemoveLargeObjects");
203  return result;
204 }
205 
206 BinaryImage *BinaryImage::ConvexHull(bool connectivity8)
207 {
208  BinaryImage *result = new BinaryImage();
209  int success = imaqConvexHull(result->GetImaqImage(), m_imaqImage, connectivity8);
210  wpi_setImaqErrorWithContext(success, "Error in convex hull operation");
211  return result;
212 }
213 
214 BinaryImage *BinaryImage::ParticleFilter(ParticleFilterCriteria2 *criteria, int criteriaCount)
215 {
216  BinaryImage *result = new BinaryImage();
217  int numParticles;
218  ParticleFilterOptions2 filterOptions = {0, 0, 0, 1};
219  int success = imaqParticleFilter4(result->GetImaqImage(), m_imaqImage, criteria, criteriaCount, &filterOptions, NULL, &numParticles);
220  wpi_setImaqErrorWithContext(success, "Error in particle filter operation");
221  return result;
222 }
223 
ParticleAnalysisReport GetParticleAnalysisReport(int particleNumber)
Definition: BinaryImage.cpp:40
vector< ParticleAnalysisReport > * GetOrderedParticleAnalysisReports()
virtual bool StatusIsFatal() const
Check if the current error code represents a fatal error.
Definition: ErrorBase.cpp:178
virtual void Write(const char *fileName)
Image * GetImaqImage()
Definition: ImageBase.cpp:73
int GetNumberParticles()
Definition: BinaryImage.cpp:26

Generated on Sat Apr 26 2014 12:26:45 for WPILibC++ by doxygen 1.8.6