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