1
/***************************************************************************
2
ADM_vidParticle.h - detect particles (groups of pixels)
4
Chris MacGregor, 2005, 2007
5
chris-avidemux@bouncingdog.com
6
***************************************************************************/
8
/***************************************************************************
10
* This program is free software; you can redistribute it and/or modify *
11
* it under the terms of the GNU General Public License as published by *
12
* the Free Software Foundation; either version 2 of the License, or *
13
* (at your option) any later version. *
15
***************************************************************************/
22
#include "ADM_video/ADM_cache.h"
32
uint32_t output_format;
33
std::string output_file;
34
uint32_t camera_number;
38
// Alas, because offsetof() is only supposed to work on POD (plain old data)
39
// structs, and our PARTICLE_PARAM includes a std::string (which has a
40
// constructor, and which causes PARTICLE_PARAM to therefore have an implicit
41
// constructor), we need to define our own offsetof() to use for the dialog
43
// http://www.cplusplus.com/reference/clibrary/cstddef/offsetof.html for more
46
#define my_offsetof(_type, _memb) (size_t (&(((_type *)1)->_memb)) - 1)
48
class ADMVideoParticle : public AVDMGenericVideoStream
53
PARTICLE_PARAM * _param;
55
static FILE * outfp; // ugly, but hard to avoid
56
static uint32_t last_frame_written; // ditto
62
OUTPUTFMT_INVALID = 0,
71
ADMVideoParticle (AVDMGenericVideoStream *in, CONFcouple *setup);
75
virtual uint8_t getFrameNumberNoAlloc (uint32_t frame, uint32_t *len,
76
ADMImage *data,uint32_t *flags);
78
virtual uint8_t configure (AVDMGenericVideoStream *instream);
79
virtual char * printConf (void);
80
virtual uint8_t getCoupledConf (CONFcouple **couples);
82
static uint8_t doParticle (ADMImage * image, ADMImage * data,
83
AVDMGenericVideoStream * in,
85
FILE * do_outfp, PARTICLE_PARAM * param,
86
uint32_t width, uint32_t height);
89
//////////////////////////////////////////////////////////////////////////////
108
PixelLoc (uint32_t a_x, uint32_t a_y)
114
// Use this to sort by y's, then (for PixelLoc's with the same y) by x's.
119
int operator () (const PixelLoc & p1, const PixelLoc & p2) const
121
return ((p1.y == p2.y) ? (p1.x < p2.x) : (p1.y < p2.y));
126
// Now that we no longer need to sort the list or insert anything into it, a
127
// vector should be faster.
128
// typedef std::list <PixelLoc> PixelList;
129
typedef std::vector <PixelLoc> PixelList;
131
inline std::ostream &
132
operator << (std::ostream & s, const PixelLoc & pl)
134
return s << "(" << pl.x << "," << pl.y << ")";
137
inline std::ostream &
138
operator << (std::ostream & s, const PixelList & theList)
141
std::copy (theList.begin(), theList.end(),
142
std::ostream_iterator <PixelLoc> (s, " "));
159
uint32_t my_left_margin;
160
uint32_t my_right_margin;
161
uint32_t my_top_margin;
162
uint32_t my_bottom_margin;
163
ADMImage * my_outImage;
166
uint32_t my_particleArea;
167
float my_particleCentroidX;
168
float my_particleCentroidY;
172
enum TracingDirection
174
// The order of the members here is important - several things depend
177
DIRECTION_EAST, // x + 1, y
178
DIRECTION_SOUTH, // x , y + 1
179
DIRECTION_WEST, // x - 1, y
180
DIRECTION_NORTH, // x , y - 1
186
// These values are designed to be added to TracingDirection values.
188
TURN_AROUND = 2, // reverse
192
static char directionLetters [];
193
static PixelOffset leftOffset [DIRECTION_COUNT];
194
static PixelOffset aheadOffset [DIRECTION_COUNT];
197
ImageTool (uint8_t * pixels, uint32_t w, uint32_t h, ADMImage * outImage = 0)
198
: my_pixels (pixels),
204
my_bottom_margin (h),
205
my_outImage (outImage),
207
my_particleCentroidX (0),
208
my_particleCentroidY (0),
213
void setCropping (uint32_t left_crop, uint32_t right_crop,
214
uint32_t top_crop, uint32_t bottom_crop)
216
my_left_margin = left_crop;
217
my_right_margin = my_w - right_crop;
218
my_top_margin = top_crop;
219
my_bottom_margin = my_h - bottom_crop;
222
// Return true if the pixel is part of a particle.
224
bool goodPixel (uint8_t pixel) const
226
// HERE: If we wanted to incorporate thresholding into this step, or look
227
// for black particles on a white background, this function would be the
228
// place to make the change.
233
uint8_t & getPixel (uint32_t x, uint32_t y) const
235
return my_pixels [(y * my_w) + x];
238
uint8_t & getPixel (uint32_t index) const
240
return my_pixels [index];
243
// This one does bounds checking, and forces references "off the edge" to
244
// the nearest valid pixel - it's useful for convolutions. It does not
245
// currently respect the crop settings, only because we know that this
246
// function is used only when those aren't set.
248
uint8_t & getPixelSafely (int32_t x, int32_t y) const
260
return my_pixels [(y * my_w) + x];
263
uint8_t & getPixelSafely (uint32_t x, uint32_t y) const
265
return getPixelSafely (static_cast <int32_t> (x),
266
static_cast <int32_t> (y));
269
uint8_t & outPixel (uint32_t x, uint32_t y) const
271
return YPLANE (my_outImage) [(y * my_w) + x];
274
uint8_t & outUPixel (uint32_t x, uint32_t y) const
276
return UPLANE (my_outImage) [((y >> 2) * my_w) + (x >> 1)];
279
uint8_t & outVPixel (uint32_t x, uint32_t y) const
281
return VPLANE (my_outImage) [((y >> 2) * my_w) + (x >> 1)];
284
bool validPixel (uint32_t x, uint32_t y) const
286
// return (x < my_w && y < my_h);
287
return (x >= my_left_margin && x < my_right_margin
288
&& y >= my_top_margin && y < my_bottom_margin);
291
bool goodPixel (uint32_t x, uint32_t y) const
293
// HERE: this might be a good place to implement ROI (region of
294
// interest) if we want that.
296
return (validPixel (x, y) && goodPixel (getPixel (x, y)));
299
uint32_t width () const
304
uint32_t height () const
309
uint32_t particleArea () const
311
return my_particleArea;
314
float particleCentroidX () const
316
return my_particleCentroidX;
319
float particleCentroidY () const
321
return my_particleCentroidY;
324
uint8_t autoOutline (uint32_t x, uint32_t y);
326
void showStuff () const;
328
// implementation is in ADM_vidSwissArmyKnife.cpp - nothing else uses it
331
template <class Oper, class Histo>
332
void convolve (const std::vector <float> & kernel,
333
uint32_t kw, uint32_t kh, int32_t bias, const Oper & op,
334
const Histo & histogram_in);
336
void setDebug (uint32_t newDebug)
341
void setMinArea (uint32_t newMinArea)
343
my_minArea = newMinArea;
346
void setMaxArea (uint32_t newMaxArea)
348
my_maxArea = newMaxArea;
353
uint8_t DIA_particle (AVDMGenericVideoStream *in,
354
PARTICLE_PARAM * param,
355
const MenuMapping * menu_mapping,
356
uint32_t menu_mapping_count);