Rose-Hulman Robotics Team

Changeset 469

Show
Ignore:
Timestamp:
03/22/09 18:15:40 (3 years ago)
Author:
spenceal
Message:

adding c->python interfaces, cleaning up image code even further

Location:
trunk/software
Files:
9 modified

Legend:

Unmodified
Added
Removed
  • trunk/software/Makefile

    r403 r469  
    77        gtk-builder-convert $< $@ 
    88 
    9 test: main 
     9test: all 
    1010        python test.py 
    1111 
    12 docs: main 
     12docs: all 
    1313        epydoc --html --docformat=restructuredtext \ 
    1414                --show-imports --no-frames --graph=all \ 
  • trunk/software/rb/vision

    • Property svn:ignore
      •  

        old new  
        11*.jpeg 
         2*.png 
        23main 
        34gmon.out 
  • trunk/software/rb/vision/_vision.c

    r468 r469  
    2020 
    2121#include <Python.h> 
     22#include <opencv/cv.h> 
     23 
     24#include "vision.h" 
     25 
     26/* TODO: define some constants for the types of points */ 
    2227 
    2328static PyObject* 
    2429_get_points(PyObject *self, PyObject *args) 
    2530{ 
    26         PyObject *points = PyList_New(0); // TODO: start with a larger list 
     31        // TODO: start with a larger list 
     32        PyObject *points = PyList_New(0); 
    2733 
    28         for (int i = 0; i < 10; i++) { 
    29                 /* Each point is (type_of_points, x, y) */ 
    30                 PyObject *point = Py_BuildValue("iii", 0, i, i*2); 
     34        IplImage *input       = get_image(); 
     35        IplImage *transformed = transform_image(input, 0.25); 
     36        CvMat    *classes     = classify_image(transformed); 
     37        CvSeq    *seq         = get_points(classes); 
     38 
     39        CvSeqReader reader; 
     40        cvStartReadSeq(seq, &reader, 0); 
     41        for(int i = 0; i < seq->total; i++) { 
     42                int data[3]; 
     43                CV_READ_SEQ_ELEM(data, reader); 
     44                PyObject *point = Py_BuildValue("iii", data[0], data[1], data[2]); 
    3145                PyList_Append(points, point); 
    3246        } 
     47        cvReleaseMemStorage(&seq->storage); 
    3348 
    3449        return points; 
  • trunk/software/rb/vision/main.c

    r468 r469  
    1818 
    1919#include <stdio.h> 
    20 #include <stdint.h> 
    2120#include <errno.h> 
    22 #include <opencv/cv.h> 
    2321#include <opencv/highgui.h> 
    2422#include <X11/keysym.h> 
     
    4341        /* Process */ 
    4442        print_time("Processing images"); 
    45         IplImage *output = process_image(input, 0.25); 
     43        IplImage *transformed = transform_image(input, 0.25); 
     44        CvMat    *classes     = classify_image(transformed); 
     45        IplImage *colors      = color_mat(classes); 
    4646 
    47         /* Save image */ 
    48         print_time("Saving images"); 
    49         cvSaveImage("out.png", output); 
     47        /* Extracting points */ 
     48        print_time("Extracting and marking points"); 
     49        CvSeq *seq = get_points(classes); 
     50        CvSeqReader reader; 
     51        cvStartReadSeq(seq, &reader, 0); 
     52        for(int i = 0; i < seq->total; i++) { 
     53                int data[3]; 
     54                CV_READ_SEQ_ELEM(data, reader); 
     55                printf("read: (%d, %d, %d)\n", data[0], data[1], data[2]); 
     56                cvCircle(transformed, 
     57                         cvPoint(data[1], data[2]), 
     58                         2, class_colors[data[0]], CV_FILLED, 8, 0); 
     59        } 
     60        cvReleaseMemStorage(&seq->storage); 
    5061 
    5162        /* Display images */ 
     
    5465        cvMoveWindow ("input", 100, 100); 
    5566        cvShowImage  ("input", input); 
    56         cvNamedWindow("out",   0); 
    57         cvMoveWindow ("out",   100, 100); 
    58         cvShowImage  ("out",   output); 
     67        cvNamedWindow("transformed", 0); 
     68        cvMoveWindow ("transformed", 100, 100); 
     69        cvShowImage  ("transformed", transformed); 
     70        cvNamedWindow("colors", 0); 
     71        cvMoveWindow ("colors", 100, 100); 
     72        cvShowImage  ("colors", colors); 
    5973 
    6074        while (cvWaitKey(0) != XK_q); 
     
    6276        /* Release temp data */ 
    6377        cvReleaseImage(&input); 
    64         cvReleaseImage(&output); 
     78        cvReleaseImage(&transformed); 
     79        cvReleaseMat(&classes); 
     80        cvReleaseImage(&colors); 
    6581 
    6682        return 0; 
  • trunk/software/rb/vision/makefile

    r468 r469  
    2525        gcc -o $@ $+ $(LDFLAGS) 
    2626 
    27 %.o: %.c %.h 
     27%.o: %.c 
    2828        gcc $(CFLAGS) -c -o $@ $*.c 
    2929 
  • trunk/software/rb/vision/vision.c

    r468 r469  
    2222#include <sys/timeb.h> 
    2323#include <opencv/cv.h> 
     24#include <opencv/highgui.h> 
    2425#include <X11/keysym.h> 
    2526#include <gsl/gsl_fit.h> 
     
    2728#include "vision.h" 
    2829 
    29 IplImage *process_image(IplImage *input, double scale) 
     30IplImage *get_image() 
     31{ 
     32        char *file = "rb/vision/data/images/cimg4753.jpg"; 
     33        IplImage *image = cvLoadImage(file, 1); 
     34        if (!image) { 
     35                printf("Could not load image file: %s\n", file); 
     36                return NULL; 
     37        } 
     38        return image; 
     39} 
     40 
     41IplImage *transform_image(IplImage *input, double scale) 
    3042{ 
    3143        /* Scale image */ 
     
    5365        cvWarpPerspective(img, transformed, mat, CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); 
    5466        cvReleaseImage(&img); 
    55         img = transformed; 
     67        return transformed; 
     68} 
     69 
     70CvMat *classify_image(IplImage *input) 
     71{ 
     72        CvSize size = {input->width, input->height}; 
     73        IplImage *img = cvCreateImage(size, input->depth, input->nChannels); 
     74        cvCopy(input, img, NULL); 
    5675 
    5776        /* Smooth image */ 
     
    6685        /* Threshold image */ 
    6786        print_time("Marking grass"); 
    68         CvMat *grass_mask = cvCreateMat(size.height, size.width, CV_8UC1); 
    69         CvMat *line_mask  = cvCreateMat(size.height, size.width, CV_8UC1); 
     87        CvMat *grass_mask = cvCreateMat(size.height, size.width, CV_8U); 
     88        CvMat *line_mask  = cvCreateMat(size.height, size.width, CV_8U); 
    7089        cvInRangeS(hsv, cvScalar(30, 0, 80, 0), cvScalar(120,90,180,0), grass_mask); 
    7190        cvInRangeS(hsv, cvScalar(100,60,140,0), cvScalar(120,90,254,0), line_mask); 
     91        // TODO, mark obstacles separately 
    7292 
    7393        /* Morphological operations */ 
    7494        print_time("Expanding lines"); 
    7595        int rad = (int)size.width*0.005; 
    76         printf("se.rad = %d\n", rad); 
    7796        IplConvKernel *se = cvCreateStructuringElementEx(rad, rad, rad/2, rad/2, CV_SHAPE_RECT, NULL); 
    7897        cvDilate(line_mask, line_mask, se, 2); 
     
    8099 
    81100        /* Mark outputs */ 
    82         IplImage *output = cvCreateImage(size, img->depth, img->nChannels); 
    83         cvSet(output, SC_GRASS, grass_mask); 
    84         cvSet(output, SC_LINE,  line_mask); 
     101        CvMat *output = cvCreateMat(input->height, input->width, CV_8U); 
     102        cvSet(output, cvRealScalar(RB_IGNORE), NULL); 
     103        cvSet(output, cvRealScalar(RB_GRASS),  grass_mask); 
     104        cvSet(output, cvRealScalar(RB_LINE ),  line_mask); 
    85105 
    86106        /* Release temporary data */ 
     
    91111 
    92112        return output; 
     113} 
     114 
     115CvSeq *get_points(CvMat *classes) 
     116{ 
     117        int test_data[][3] = { 
     118                {RB_SKY,100,100}, {RB_GRASS,200,100}, {RB_OBSTICLE,300,100}, 
     119                {RB_SKY,100,200}, {RB_GRASS,200,200}, {RB_OBSTICLE,300,200}, 
     120                {RB_SKY,100,300}, {RB_GRASS,200,300}, {RB_OBSTICLE,300,300}, 
     121        }; 
     122 
     123        CvMemStorage *storage = cvCreateMemStorage(0); 
     124        CvSeq *seq = cvCreateSeq(CV_32SC3,      // sequence of 3 tuples? (scalars?) 
     125                                 sizeof(CvSeq), // header size - no extra fields 
     126                                 sizeof(int)*3, // element size 
     127                                 storage);      // the container storage 
     128 
     129        CvSeqWriter writer; 
     130        cvStartAppendToSeq(seq, &writer); 
     131        for(int x = 0; x < classes->cols; x+=10) { 
     132                for(int y = 0; y < classes->rows; y+=10) { 
     133                        CvScalar class = cvGet2D(classes, y, x); 
     134                        int data[3] = {class.val[0], x, y}; 
     135                        CV_WRITE_SEQ_ELEM(data, writer); 
     136                } 
     137        } 
     138        cvEndWriteSeq(&writer); 
     139         
     140        return seq; 
     141} 
     142 
     143IplImage *color_mat(CvMat *classes) 
     144{ 
     145        IplImage *img = cvCreateImage(cvSize(classes->cols, classes->rows), 8, 3); 
     146        CvMat *mask = cvCreateMat(classes->rows, classes->cols, CV_8UC1); 
     147        for (int i = 0; i < RB_NUM_CLASSES; i++) { 
     148                cvCmpS(classes, i, mask, CV_CMP_EQ); 
     149                cvSet(img, class_colors[i], mask); 
     150        } 
     151        return img; 
    93152} 
    94153 
     
    105164                        CvScalar px = cvGet2D(out, x, y); 
    106165                        // TODO: test/check the memcmp line 
    107                         if (!memcmp(&px, &SC_LINE, sizeof(CvScalar))) { 
     166                        if (!memcmp(&px, &class_colors[RB_LINE], sizeof(CvScalar))) { 
    108167                                xs[n] = x; 
    109168                                ys[n] = y; 
     
    160219                                box.width = out->width - box.x; 
    161220 
    162                         // The extreems of the actual line 
     221                        // The extremes of the actual line 
    163222                        CvLine linebox = {{0, 0}, {0, 0}}; 
    164223                        int rval = find_slope_in_box(out, box, &linebox, &yint, &slope); 
  • trunk/software/rb/vision/vision.h

    r468 r469  
    2828} CvLine; 
    2929 
    30 /* 
     30/** 
    3131 * Standard pixel values 
    3232 * 
    3333 * The classified image will be represented by these colors 
    3434 */ 
    35 const static CvScalar SC_SKY      = {{0*255, 0*255, 1*255, 0}}; // Blue 
    36 const static CvScalar SC_GRASS    = {{0*255, 1*255, 0*255, 0}}; // Green 
    37 const static CvScalar SC_LINE     = {{1*255, 1*255, 1*255, 0}}; // White 
    38 const static CvScalar SC_OBSTICLE = {{1*255, 0*255, 0*255, 0}}; // Red 
    39 const static CvScalar SC_PATH     = {{1*255, 0*255, 1*255, 0}}; // Purple 
    40 const static CvScalar SC_IGNORE   = {{0*255, 0*255, 0*255, 0}}; // Black 
     35typedef enum rb_classes_t { 
     36        RB_SKY     , 
     37        RB_GRASS   , 
     38        RB_LINE    , 
     39        RB_OBSTICLE, 
     40        RB_PATH    , 
     41        RB_IGNORE  , 
     42        RB_NUM_CLASSES 
     43} rb_classes_t; 
     44const static CvScalar class_colors[256] = { 
     45        [RB_SKY     ] = {{0*255, 0*255, 1*255, 0}}, // Blue    
     46        [RB_GRASS   ] = {{0*255, 1*255, 0*255, 0}}, // Green   
     47        [RB_LINE    ] = {{1*255, 1*255, 1*255, 0}}, // White   
     48        [RB_OBSTICLE] = {{1*255, 0*255, 0*255, 0}}, // Red     
     49        [RB_PATH    ] = {{1*255, 0*255, 1*255, 0}}, // Purple  
     50        [RB_IGNORE  ] = {{0*255, 0*255, 0*255, 0}}  // Black   
     51}; 
    4152 
    4253/** 
    43  * Preforms the following operations on the image, returning a new image as 
    44  * output. The original image is left untouched. 
    45  *   - scaling 
    46  *   - perspective transform 
     54 * Attempt to obtain an image from the camera 
     55 */ 
     56IplImage *get_image(); 
     57 
     58/** 
     59 * Scales and transforms the image. 
     60 * 
     61 * The goal is to make distacnes in the image (pixel distances) be a constant 
     62 * scale of distances in the actual world. 
     63 */ 
     64IplImage *transform_image(IplImage *input, double scale); 
     65 
     66/** 
     67 * Classifies the input image. 
     68 * 
     69 * This preforms the following operations on the image.  as output. The 
     70 * original image is left untouched. 
    4771 *   - smoothing 
    4872 *   - converting to HSV 
     
    5074 *   - morphologies 
    5175 */ 
    52 IplImage *process_image(IplImage *input, double scale); 
     76CvMat *classify_image(IplImage *input); 
    5377 
    54 /* 
     78/** 
     79 * Retrieves a set of important points from a processed image. This converts an 
     80 * entire image into something small enough to be used by Python 
     81 *  
     82 * @param classes Output of the clasify_image function 
     83 * @return        A sequence of points on the image of type (type,x,y) where 
     84 *                type is a integer that identifies the classification at that 
     85 *                point in the image. 
     86 */ 
     87CvSeq *get_points(CvMat *classes); 
     88 
     89/** 
     90 * Color a matrix of classifications, useful for debugging. 
     91 *  
     92 * @param classes Output of the clasify_image function 
     93 * @return        An image colored according to the class_colors map 
     94 */ 
     95IplImage *color_mat(CvMat *classes); 
     96 
     97/************************* 
     98 * Dashed line detection * 
     99 *************************/ 
     100/** 
    55101 * Attempt to find fit a slope to a line in a given box. 
    56102 * 
     
    62108                            double *yint, double *slope); 
    63109 
    64 /* 
     110/** 
    65111 * This partitions the image into a grid of boxes and attempts to draw the 
    66112 * slope of the white line in each box. This is mostly used for debugging 
     
    69115void     mark_slopes       (IplImage *out); 
    70116 
    71 /* 
     117/** 
    72118 * Prints out the given label as well as a timestamps for the current time. 
    73119 * This is used for profiling the software 
  • trunk/software/setup.py

    r398 r469  
    2222 
    2323example_module = Extension('rb.example.c_module', ['rb/example/c_module.c']) 
    24 laser_module = Extension('rb.camera._laser', ['rb/camera/_laser.c'],  
     24laser_module   = Extension('rb.camera._laser',    ['rb/camera/_laser.c'],  
    2525                                                        libraries=['cv', 'highgui'], 
    2626                                                        extra_compile_args=['-DOPENCV']) 
     27vision_module  = Extension( 
     28        'rb.vision._vision', 
     29        ['rb/vision/_vision.c', 'rb/vision/vision.c', 'rb/vision/main.c'], 
     30        libraries=['cv', 'highgui', 'gsl'], 
     31        extra_compile_args=['--std=c99'] 
     32); 
    2733 
    2834 
     
    3036        version='0.1', 
    3137        #py_modules=['rb'], 
    32         ext_modules=[example_module, laser_module], 
     38        ext_modules=[example_module, laser_module, vision_module], 
    3339) 
  • trunk/software/test.py

    • Property svn:executable deleted