Rose-Hulman Robotics Team

Changeset 455

Show
Ignore:
Timestamp:
03/11/09 21:51:23 (3 years ago)
Author:
spenceal
Message:

thresholding in OpenCV

Location:
trunk/software/rb/vision
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/software/rb/vision/main.c

    r345 r455  
    7777 
    7878        /* Mark grass */ 
     79        print_time("Marking grass"); 
    7980        IplImage *out = cvCreateImage(size, in->depth, in->nChannels); 
    80         print_time("Marking grass"); 
    81         mark_grass(hsv, out); 
     81        CvMat *grass_mask = cvCreateMat(size.height, size.width, CV_8UC1); 
     82        cvInRangeS(hsv, cvScalar(30,0,80,0), cvScalar(120,90,180,0), grass_mask); 
     83        cvSet(out, SC_GRASS, grass_mask); 
    8284 
    8385        /* Mark lines */ 
    84         print_time("Marking lines"); 
    85         mark_lines(hsv, out); 
     86        print_time("Marking/Expanding lines"); 
    8687 
    87         /* Expand lines */ 
    88         print_time("Expanding lines"); 
    89         IplImage *out2 = cvCreateImage(size, in->depth, in->nChannels); 
    90         cvCopyImage(out, out2); 
    91         expand_lines(out, out2); 
    92         cvReleaseImage(&out); 
    93         out = out2; 
    94          
     88        CvMat *line_mask = cvCreateMat(size.height, size.width, CV_8UC1); 
     89        cvInRangeS(hsv, cvScalar(100,60,140,0), cvScalar(120,90,254,0), line_mask); 
     90 
     91        double rad = out->width*0.003; 
     92        IplConvKernel *se = cvCreateStructuringElementEx(rad, rad, rad/2, rad/2, CV_SHAPE_RECT, NULL); 
     93        cvDilate(line_mask, line_mask, se, 2); 
     94 
     95        cvSet(out, SC_LINE, line_mask); 
     96        cvReleaseStructuringElement(&se); 
     97 
    9598 
    9699        /* 
  • trunk/software/rb/vision/vision.c

    r301 r455  
    131131} 
    132132 
    133 /* in in HSV, out in BGR :) */ 
    134 px_t mark_type(const IplImage *in, IplImage *out, px_params_t px_params, 
    135                get_type_cb_t get_type_cb) 
    136 { 
    137         int x, y; 
    138         //uint32_t type_avg_h = 0, type_avg_s = 0, type_avg_v = 0, type_count = 1; 
    139         for (x = 0; x < in->width; x++) { 
    140                 for (y = 0; y < in->height; y++) { 
    141                         px_t px = get_type_cb(in, out, x, y, px_params); 
    142                         if (IS_PX(px, PX_IGNORE)) continue; 
    143                         SET_PX(out, x, y, px); 
    144                          
    145                         //const px_t rpx = GET_PX(in, x, y); 
    146                         //fprintf(stderr, "%d %d %d\n", rpx.hsv.h, rpx.hsv.s, 
    147                         //                rpx.hsv.v); 
    148                         //if (IS_PX(px, px_params.target)) { 
    149                         //      type_avg_h += rpx.hsv.h; 
    150                         //      type_avg_s += rpx.hsv.s; 
    151                         //      type_avg_v += rpx.hsv.v; 
    152                         //      type_count++; 
    153                         //} 
    154                 } 
    155         } 
    156         //printf("h = %lld, s = %lld, v = %lld, count = %lld\n", type_avg_h, 
    157         //       type_avg_s, type_avg_v, type_count); 
    158         //type_avg_h /= type_count; 
    159         //type_avg_s /= type_count; 
    160         //type_avg_v /= type_count; 
    161         //px_t type_avg = {.hsv = { 
    162         //      .h = type_avg_h,  
    163         //      .s = type_avg_s,  
    164         //      .v = type_avg_v 
    165         //}}; 
    166         px_t type_avg = {{0,0,0}}; 
    167         return type_avg; 
    168 } 
    169  
    170 /** 
    171  * Generalize this, e.g. 
    172  *  if (pass > 2) { grass_stuff; ..; } 
    173  *  Specify a number of iterations certain things need 
    174  *  Save values inbetween in static/global variables 
    175  */ 
    176 inline px_t get_grass(const IplImage *in, IplImage *out, int x, int y, px_params_t px_params) 
    177 { 
    178         const px_t px = GET_PX(in, x, y); 
    179         if (y < in->height*0.10) 
    180                 return PX_SKY; 
    181         else if (px.hsv.h > px_params.hue_min && px.hsv.h < px_params.hue_max && 
    182                  px.hsv.s > px_params.sat_min && px.hsv.s < px_params.sat_max && 
    183                  px.hsv.v > px_params.val_min && px.hsv.v < px_params.val_max ) 
    184                 return px_params.target; 
    185         else 
    186                 return PX_OBSTICLE; 
    187 } 
    188 void mark_grass(const IplImage *in, IplImage *out) 
    189 { 
    190         /* Default grass colors */ 
    191         px_params_t px_params = { 
    192                 /* Rose images */ 
    193                 //.hue_min = 10, .hue_max = 50,  // basic green 
    194                 //.sat_min = 40, .sat_max = 255, // no upper bound 
    195                 //.val_min = 20, .val_max = 255, // no default upper bound 
    196                 .hue_min =  30, .hue_max = 120, // Any Hue 
    197                 .sat_min =   0, .sat_max =  90, // no upper bound 
    198                 .val_min =  80, .val_max = 180, // no default upper bound 
    199                 .target = PX_GRASS 
    200         }; 
    201         px_t grass_avg = mark_type(in, out, px_params, get_grass); 
    202         printf("hsv.h = %02x, hsv.s = %02x, hsv.v = %02x\n", grass_avg.hsv.h, grass_avg.hsv.s, grass_avg.hsv.v); 
    203         //px_params.hue_min = MAX(grass_avg.hsv.h - 15, 0); 
    204         //px_params.hue_max = MIN(grass_avg.hsv.h + 13, 256); 
    205         //px_params.sat_min = MAX(grass_avg.hsv.s - 25, 0); 
    206         //px_params.sat_max = MIN(grass_avg.hsv.s + 30, 256); 
    207         //px_params.val_min = MAX(grass_avg.hsv.v - 20, 0); 
    208         //px_params.val_max = MIN(grass_avg.hsv.v + 20, 256); 
    209         //mark_type(in, out, width, height, px_params, get_grass); 
    210 } 
    211  
    212 /* can only one at a time (white or yellow) :( */ 
    213 inline px_t get_lines(const IplImage *in, IplImage *out, int x, int y, px_params_t px_params) 
    214 { 
    215         if (y < 30) 
    216                 return PX_IGNORE; 
    217         const px_t px = GET_PX(in, x, y); 
    218         if (px.hsv.h > px_params.hue_min && px.hsv.h < px_params.hue_max && 
    219             px.hsv.s > px_params.sat_min && px.hsv.s < px_params.sat_max && 
    220             px.hsv.v > px_params.val_min && px.hsv.v < px_params.val_max ) { 
    221                 //return px_params.target; 
    222                 int rad = in->width*0.10; 
    223                 /* Check if there's grass (or nothing) on both sides */ 
    224                 if (((x-rad <  0          || IS_PX(GET_PX(out, x-rad, y), PX_GRASS)) && 
    225                      (x+rad >= in->width  || IS_PX(GET_PX(out, x+rad, y), PX_GRASS))) || 
    226                     ((y-rad <  0          || IS_PX(GET_PX(out, x, y-rad), PX_GRASS)) && 
    227                      (y+rad >= in->height || IS_PX(GET_PX(out, x, y+rad), PX_GRASS)))) { 
    228                         return px_params.target; 
    229                 } 
    230         } 
    231         return PX_IGNORE; 
    232 } 
    233 void mark_lines(const IplImage *in, IplImage *out) 
    234 { 
    235         /* Default grass colors */ 
    236         px_params_t px_params = { 
    237                 //.hue_min = 0,  .hue_max = 180, // Any Hue 
    238                 //.sat_min = 30, .sat_max = 70,  // no upper bound 
    239                 //.val_min = 60, .val_max = 120, // no default upper bound 
    240                 .hue_min = 100, .hue_max = 120,  // basic green (good) 
    241                 .sat_min = 60,  .sat_max =  90, // no upper bound  
    242                 .val_min = 140, .val_max = 254, // no default upper bound 
    243                 .target = PX_LINE 
    244         }; 
    245         px_t white_avg = mark_type(in, out, px_params, get_lines); 
    246         printf("hsv.h = %d, hsv.s = %d, hsv.v = %d\n", 
    247                 white_avg.hsv.h, white_avg.hsv.s, white_avg.hsv.v); 
    248 } 
    249 void expand_lines(const IplImage *out1, IplImage *out2) 
    250 { 
    251         CvPoint pt; 
    252         int rad = out1->width*0.003; 
    253         int size = sizeof(px_t)*(rad*2+1); 
    254         for (pt.x = 0; pt.x < out1->width; pt.x++) { 
    255                 for (pt.y = 0; pt.y < out1->height; pt.y++) { 
    256                         if (pt.x-rad < 0 || pt.x+rad >= out2->width || 
    257                             pt.y-rad < 0 || pt.y+rad >= out2->height) 
    258                                 continue; // Skip out of bounds 
    259                         if (IS_PX(GET_PX(out1, pt.x, pt.y), PX_LINE)) { 
    260                                 //int x,y; 
    261                                 //for (x=-rad, y= rad; x <= rad; x++) SET_PX(out2, pt.x+x, pt.y+y, PX_LINE); 
    262                                 //for (x=-rad, y=-rad; x <= rad; x++) SET_PX(out2, pt.x+x, pt.y+y, PX_LINE); 
    263                                 //for (y=-rad, x= rad; y <= rad; y++) SET_PX(out2, pt.x+x, pt.y+y, PX_LINE); 
    264                                 //for (y=-rad, x=-rad; y <= rad; y++) SET_PX(out2, pt.x+x, pt.y+y, PX_LINE); 
    265                                 px_t *top = (px_t*)(out2->imageData + out2->widthStep*(pt.y+rad) + out2->nChannels*pt.x); 
    266                                 px_t *mid = (px_t*)(out2->imageData + out2->widthStep*(pt.y    ) + out2->nChannels*pt.x); 
    267                                 px_t *bot = (px_t*)(out2->imageData + out2->widthStep*(pt.y-rad) + out2->nChannels*pt.x); 
    268                                 memset(top, -1, size); 
    269                                 memset(mid, -1, size); 
    270                                 memset(bot, -1, size); 
    271                                 //for (int y = pt.y-rad; y < pt.y+rad; y++) { 
    272                                 //      px_t *yln = (px_t*)(out2->imageData + out2->widthStep*(pt.y+rad) + out2->nChannels*pt.x); 
    273                                 //      memset(yln, -1, size); 
    274                                 //} 
    275                                 //cvCircle(out2, pt, 10, color, 1, 0, 0); 
    276                                 //cvCircle(out2, pt, 10, color, 1, 0, 0); 
    277                         } 
    278                         //if (x-rad < 0 || x+rad >= out1->width || 
    279                         //    y-rad < 0 || y+rad >= out1->height) 
    280                         //      continue; // Skip out of bounds 
    281                         //if (IS_PX(GET_PX(out1, x-rad, y), PX_LINE) || 
    282                         //    IS_PX(GET_PX(out1, x+rad, y), PX_LINE) || 
    283                         //    IS_PX(GET_PX(out1, x, y-rad), PX_LINE) || 
    284                         //    IS_PX(GET_PX(out1, x, y+rad), PX_LINE) || 
    285                         //    IS_PX(GET_PX(out1, x, y    ), PX_LINE)) { 
    286                         //      SET_PX(out2, x, y, PX_LINE); 
    287                         //} 
    288                 } 
    289         } 
    290 } 
    291133void mark_slopes(IplImage *out) 
    292134{ 
  • trunk/software/rb/vision/vision.h

    r230 r455  
    9292const static px_t PX_IGNORE   = {.bgr = {.r =  0, .g =  0, .b =  0}}; // Black 
    9393 
     94const static CvScalar SC_SKY      = {{0*255, 0*255, 1*255, 0}}; // Blue 
     95const static CvScalar SC_GRASS    = {{0*255, 1*255, 0*255, 0}}; // Green 
     96const static CvScalar SC_LINE     = {{1*255, 1*255, 1*255, 0}}; // White 
     97const static CvScalar SC_OBSTICLE = {{1*255, 0*255, 0*255, 0}}; // Red 
     98const static CvScalar SC_PATH     = {{1*255, 0*255, 1*255, 0}}; // Purple 
     99const static CvScalar SC_IGNORE   = {{0*255, 0*255, 0*255, 0}}; // Black 
    94100 
    95101 
     
    133139                            double *yint, double *slope); 
    134140 
    135 /* 
    136  * Runs callback functions for mark_* 
    137  * 
    138  * Each callback funcion only specifies the type for a particular pixle. This 
    139  * function loops though all pixels in the input image in order to generate a 
    140  * complete output image. It calls `get_type_cb' once for each pixle in the 
    141  * image. 
    142  * 
    143  * \param in          Input  image in HSV colorspace 
    144  * \param out         Output image in BGR colorspace 
    145  * \param px_params   Pixel parameters to pass to the get_type_cb function. 
    146  *                    This allows the same get_type_cb to be tweeked for the 
    147  *                    particular color of the grass/lines, etc. 
    148  * \param get_type_cb The callback function to call for each pixel. 
    149  */ 
    150 px_t     mark_type         (const IplImage *in, IplImage *out, 
    151                             px_params_t px_params, get_type_cb_t get_type_cb); 
    152  
    153  
    154  
    155 /** 
    156  * Grass, Sky, Obsticle finding 
    157  **/ 
    158  
    159 /* 
    160  * Callback function for detecting grass, sky, and obsticles. 
    161  * 
    162  * This is the first callback issued. It works by determining if the pixel in 
    163  * question matches the given pixel parameters, if so it is designated as 
    164  * grass, otherwise it is designated as an obsticle. 
    165  * 
    166  * The exception to this is if the pixel is above the horizon, in that case it 
    167  * is designated as sky. 
    168  * 
    169  * See get_type_cb_t for parameter details 
    170  */ 
    171 px_t     get_grass         (const IplImage *in, IplImage *out, int x, int y, 
    172                             px_params_t px_params); 
    173  
    174 // TODO: Discuss the flow (mark_grass -> mark_type -> get_grass) 
    175 /* 
    176  * Mark all grass in the input image as grass in the output image. 
    177  * 
    178  * For any pixel in the input image that is grass write a green pixel to the 
    179  * output image. 
    180  */ 
    181 void     mark_grass        (const IplImage *in, IplImage *out); 
    182  
    183  
    184141 
    185142/** 
    186143 * Line finding 
    187144 **/ 
    188  
    189 /* 
    190  * Determine whether a pixel is a line. This based mostly on the HSV value of 
    191  * the pixels but also does some more advanced logic to prevent barrels and 
    192  * such from being incorrectly shown as lines. 
    193  * 
    194  * See get_type_cb_t for parameter details 
    195  */ 
    196 px_t     get_lines         (const IplImage *in, IplImage *out, int x, int y, 
    197                             px_params_t px_params); 
    198  
    199 /* 
    200  * Mark all lines as in the image, this may call call get_type/get_lines for 
    201  * both white and yellow lines. 
    202  */ 
    203 void     mark_lines        (const IplImage *in, IplImage *out); 
    204  
    205 /* 
    206  * Expand lines to fill gaps 
    207  * 
    208  * This expands lines so that small areas in the lines that were missed get 
    209  * filled in. This also helps to keep the robot a little bit away from the 
    210  * actual line. 
    211  */ 
    212 void     expand_lines      (const IplImage *o1, IplImage *o2); 
    213  
    214145/* 
    215146 * This partitions the image into a grid of boxes and attempts to draw the 
     
    218149 */ 
    219150void     mark_slopes       (IplImage *out); 
    220  
    221151 
    222152