00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <classifiers/simple.h>
00025
00026 #include <fvutils/color/colorspaces.h>
00027 #include <fvutils/color/yuv.h>
00028 #include <fvutils/color/color_object_map.h>
00029
00030 #include <models/scanlines/scanlinemodel.h>
00031 #include <models/color/colormodel.h>
00032
00033 #include <core/exceptions/software.h>
00034
00035 #include <cstdlib>
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 SimpleColorClassifier::SimpleColorClassifier(ScanlineModel *scanline_model,
00053 ColorModel *color_model,
00054 unsigned int min_num_points,
00055 unsigned int box_extent,
00056 bool upward,
00057 unsigned int neighbourhood_min_match,
00058 unsigned int grow_by)
00059 : Classifier("SimpleColorClassifier")
00060 {
00061 if (!scanline_model)
00062 throw fawkes::NullPointerException("SimpleColorClassifier: scanline_model may not be NULL");
00063 if (!color_model)
00064 throw fawkes::NullPointerException("SimpleColorClassifier: color_model may not be NULL");
00065
00066 modified = false;
00067 this->scanline_model = scanline_model;
00068 this->color_model = color_model;
00069 this->min_num_points = min_num_points;
00070 this->box_extent = box_extent;
00071 this->upward = upward;
00072 this->grow_by = grow_by;
00073 this->neighbourhood_min_match = neighbourhood_min_match;
00074 set_hint(H_BALL);
00075 }
00076
00077
00078
00079
00080
00081
00082 void
00083 SimpleColorClassifier::set_hint (hint_t hint)
00084 {
00085 colors_of_interest.clear();
00086 colors_of_interest.push_back(ColorObjectMap::get_instance().get(hint));
00087 }
00088
00089
00090
00091
00092 void
00093 SimpleColorClassifier::add_hint (hint_t hint)
00094 {
00095 colors_of_interest.push_back(ColorObjectMap::get_instance().get(hint));
00096 colors_of_interest.unique();
00097 }
00098
00099
00100 unsigned int
00101 SimpleColorClassifier::consider_neighbourhood( unsigned int x, unsigned int y , color_t what)
00102 {
00103 color_t c;
00104 unsigned int num_what = 0;
00105
00106 unsigned char yp = 0, up = 0, vp = 0;
00107 int start_x = -2, start_y = -2;
00108 int end_x = 2, end_y = 2;
00109
00110 if (x < (unsigned int)abs(start_x)) {
00111 start_x = 0;
00112 }
00113 if (y < (unsigned int)abs(start_y)) {
00114 start_y = 0;
00115 }
00116
00117 if (x > _width - end_x) {
00118 end_x = 0;
00119 }
00120 if (y == _height - end_y) {
00121 end_y = 0;
00122 }
00123
00124 for (int dx = start_x; dx <= end_x ; dx += 2) {
00125 for (int dy = start_y; dy <= end_y; ++dy) {
00126 if ((dx == 0) && (dy == 0)) {
00127 continue;
00128 }
00129
00130
00131
00132
00133 YUV422_PLANAR_YUV(_src, _width, _height, x+dx, y+dy, yp, up, vp);
00134 c = color_model->determine(yp, up, vp);
00135
00136 if (c == what) {
00137 ++num_what;
00138 }
00139 }
00140 }
00141
00142 return num_what;
00143 }
00144
00145 std::list< ROI > *
00146 SimpleColorClassifier::classify()
00147 {
00148
00149 if (_src == NULL) {
00150
00151 return new std::list< ROI >;
00152 }
00153
00154
00155 std::list< ROI > *rv;
00156 std::list< ROI >::iterator roi_it, roi_it2;
00157 color_t c;
00158 std::map<color_t, std::list< ROI > > to_be_considered;
00159 std::map<color_t, std::list< ROI > >::iterator tbc_it;
00160
00161 for (std::list<color_t>::const_iterator it = colors_of_interest.begin(); it != colors_of_interest.end(); ++it) {
00162 to_be_considered[*it];
00163 }
00164
00165 unsigned int x = 0, y = 0;
00166 unsigned char yp = 0, up = 0, vp = 0;
00167 unsigned int num_what = 0;
00168
00169 ROI r;
00170
00171 scanline_model->reset();
00172 while (! scanline_model->finished()) {
00173
00174 x = (*scanline_model)->x;
00175 y = (*scanline_model)->y;
00176
00177 YUV422_PLANAR_YUV(_src, _width, _height, x, y, yp, up, vp);
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 c = color_model->determine(yp,up, vp);
00192
00193 if ((tbc_it = to_be_considered.find(c)) != to_be_considered.end()) {
00194 rv = &tbc_it->second;
00195
00196
00197
00198
00199
00200 if (neighbourhood_min_match) {
00201 num_what = consider_neighbourhood((*scanline_model)->x, (*scanline_model)->y, c);
00202 }
00203 if (num_what >= neighbourhood_min_match) {
00204
00205 bool ok = false;
00206
00207 for (roi_it = rv->begin(); roi_it != rv->end(); ++roi_it) {
00208 if ( (*roi_it).contains(x, y) ) {
00209
00210 ok = true;
00211 break;
00212 }
00213 }
00214 if (! ok) {
00215 for (roi_it = rv->begin(); roi_it != rv->end(); ++roi_it) {
00216 if ( (*roi_it).neighbours(x, y, scanline_model->get_margin()) ) {
00217
00218 (*roi_it).extend(x, y);
00219 ok = true;
00220 break;
00221 }
00222 }
00223 }
00224
00225 if (! ok) {
00226 if ( upward ) {
00227 if ( x < box_extent ) {
00228 x = 0;
00229 } else {
00230 x -= box_extent;
00231 }
00232 if ( y < box_extent ) {
00233 y = 0;
00234 } else {
00235 y -= box_extent;
00236 }
00237 }
00238 r.start.x = x;
00239 r.start.y = y;
00240
00241 unsigned int to_x = (*scanline_model)->x + box_extent;
00242 unsigned int to_y = (*scanline_model)->y + box_extent;
00243 if (to_x > _width) to_x = _width;
00244 if (to_y > _height) to_y = _height;
00245 r.width = to_x - r.start.x;
00246 r.height = to_y - r.start.y;
00247 r.hint = ColorObjectMap::get_instance().get(c);
00248
00249 r.line_step = _width;
00250 r.pixel_step = 1;
00251
00252 r.image_width = _width;
00253 r.image_height = _height;
00254
00255 if ( (r.start.x + r.width) > _width ) {
00256 r.width -= (r.start.x + r.width) - _width;
00257 }
00258 if ( (r.start.y + r.height) > _height ) {
00259 r.height -= (r.start.y + r.height) - _height;
00260 }
00261
00262 rv->push_back( r );
00263 }
00264 }
00265 }
00266
00267 ++(*scanline_model);
00268 }
00269
00270
00271 if (grow_by > 0) {
00272 for (tbc_it = to_be_considered.begin(); tbc_it != to_be_considered.end(); ++tbc_it) {
00273 rv = &tbc_it->second;
00274
00275 for (roi_it = rv->begin(); roi_it != rv->end(); ++roi_it) {
00276 (*roi_it).grow( grow_by );
00277 }
00278 }
00279 }
00280
00281
00282
00283 for (tbc_it = to_be_considered.begin(); tbc_it != to_be_considered.end(); ++tbc_it) {
00284 rv = &tbc_it->second;
00285
00286 for (roi_it = rv->begin(); roi_it != rv->end(); ++roi_it) {
00287 roi_it2 = roi_it;
00288 ++roi_it2;
00289
00290 while ( roi_it2 != rv->end() ) {
00291 if ((roi_it != roi_it2) && roi_it->neighbours(&(*roi_it2), scanline_model->get_margin())) {
00292 *roi_it += *roi_it2;
00293 rv->erase(roi_it2);
00294 roi_it2 = rv->begin();
00295 } else {
00296 ++roi_it2;
00297 }
00298 }
00299 }
00300 }
00301
00302 std::list< ROI > *result = new std::list< ROI >;
00303 for (tbc_it = to_be_considered.begin(); tbc_it != to_be_considered.end(); ++tbc_it) {
00304 rv = &tbc_it->second;
00305
00306
00307 for (roi_it = rv->begin(); roi_it != rv->end(); ++roi_it) {
00308 while ( (roi_it != rv->end()) &&
00309 ((*roi_it).num_hint_points < min_num_points )) {
00310 roi_it = rv->erase( roi_it );
00311 }
00312 }
00313
00314
00315 rv->sort();
00316 rv->reverse();
00317 result->merge(*rv);
00318 }
00319
00320 return result;
00321 }
00322
00323
00324
00325
00326
00327
00328 void
00329 SimpleColorClassifier::get_mass_point_of_ball( ROI *roi, fawkes::point_t *massPoint )
00330 {
00331 unsigned int nrOfOrangePixels;
00332 nrOfOrangePixels = 0;
00333 massPoint->x = 0;
00334 massPoint->y = 0;
00335
00336
00337 register unsigned int h = 0;
00338 register unsigned int w = 0;
00339
00340 register unsigned char *yp = _src + (roi->start.y * roi->line_step) + (roi->start.x * roi->pixel_step);
00341 register unsigned char *up = YUV422_PLANAR_U_PLANE(_src, roi->image_width, roi->image_height)
00342 + ((roi->start.y * roi->line_step) / 2 + (roi->start.x * roi->pixel_step) / 2) ;
00343 register unsigned char *vp = YUV422_PLANAR_V_PLANE(_src, roi->image_width, roi->image_height)
00344 + ((roi->start.y * roi->line_step) / 2 + (roi->start.x * roi->pixel_step) / 2);
00345
00346 unsigned char *lyp = yp;
00347 unsigned char *lup = up;
00348 unsigned char *lvp = vp;
00349
00350 color_t color;
00351
00352
00353 for (h = 0; h < roi->height; ++h) {
00354 for (w = 0; w < roi->width; w += 2) {
00355
00356 color = color_model->determine(*yp++, *up++, *vp++);
00357 *yp++;
00358
00359 if (color == ColorObjectMap::get_instance().get(roi->hint)) {
00360
00361 massPoint->x += w;
00362 massPoint->y += h;
00363 nrOfOrangePixels++;
00364 }
00365 }
00366
00367 lyp += roi->line_step;
00368 lup += roi->line_step / 2;
00369 lvp += roi->line_step / 2;
00370 yp = lyp;
00371 up = lup;
00372 vp = lvp;
00373 }
00374
00375
00376 massPoint->x = (unsigned int) (float(massPoint->x) / float(nrOfOrangePixels));
00377 massPoint->y = (unsigned int) (float(massPoint->y) / float(nrOfOrangePixels));
00378
00379
00380
00381
00382 massPoint->x += roi->start.x;
00383 massPoint->y += roi->start.y;
00384 }