UserPreferences

CBlobPackage


1. CBlob Low-Level Blobification Package

  1. CBlob Low-Level Blobification Package
    1. CBlob contents
      1. Structs
        1. struct point
        2. struct bitmap
        3. struct blob
        4. struct blobdata
        5. playerblob_t
      2. Functions
        1. Blob_*
        2. Bitmap_*
        3. Blobdata_*
        4. Transducer functions
        5. filter functions
        6. Player/Stage export functions

1.1. CBlob contents

1.1.1. Structs

1.1.1.1. struct point
struct point{
  int x;
  int y;
};

Pretty much only used with the blob struct

1.1.1.2. struct bitmap
struct bitmap{
  int width;
  int height;
  uint16_t* data;
};

Pretty self-explanitory. The data is a 16-bit int because the blobdata struct uses the bitmap to represent which pixel belongs to which blob (so there can be more than 256 blobs).

1.1.1.3. struct blob
struct blob{
  int mass;
  struct point ul;
  struct point lr;
  double cm_x;
  double cm_y;
};

blob.ul and blob.lr are the upper-right and lower-left corners of the blob, respectively. cm_x and cm_y are the x and y coordinates of the "center of mass" of the blob.

1.1.1.4. struct blobdata
struct blobdata{
  int width;
  int height;
  int nblobs;
  struct bitmap* blobmap;
  int* equivList;
  struct blob** bloblist;
};

The meat of the package. nblobs is the total number of blobs, and therefore the length of the bloblist array. equivList is used internally in the blob processing [should we take it out of the struct, and just make it a local var in Blobdata_init?]. blobmap has contains the number of the blob at each pixel in its image data, and bloblist is a an array of pointers to blobs, the indexes of which correspond to the data in blobmap.

1.1.1.5. playerblob_t
typedef struct player_blobfinder_data_varsize{
  uint16_t width, height;
  int n_channels;
  player_blobfinder_header_elt_t* header;
  player_blobfinder_blob_elt_t* blobs;
} playerblob_t;

This is a struct that is basically equivalent to the player_blobfinder_data_t from Player/Stage. However, unlike the Player/Stage version, its size is determined at runtime, and can contain an unlimited (well, limited to sizeof(int)) number of blobs.

1.1.2. Functions

1.1.2.1. Blob_*
void Blob_init(struct blob* theBlob, struct point* pixel);
void Blob_init_xy(struct blob* theBlob, int x, int y); 
void Blob_addpixel(struct blob* theBlob, struct point* pixel);
void Blob_addpixel_xy(struct blob* theBlob, int x, int y);
void Blob_joinblob(struct blob* theBlob, struct blob* other);

These are all called by Blobdata_init, and you shouldn't need to use them.

1.1.2.2. Bitmap_*
void Bitmap_init(struct bitmap* map, int w, int h);
void Bitmap_set(struct bitmap* map, int x, int y, uint16_t in);
uint16_t Bitmap_get(struct bitmap* map, int x, int y);
void Bitmap_del(struct bitmap* map);
int Bitmap_write_to_pgm(struct bitmap* map, char* filename, int levels);

Should be-self explanitory. To create a blank bitmap, you must allocate the memory for the bitmap struct, then call Bitmap_init on it. When you are done, call Bitmap_del on it, and then free the memory:

struct bitmap* bmp;
bmp = (struct bitmap*) malloc(sizeof(struct bitmap));
Bitmap_init(bmp, width, height);

// use bmp

Bitmap_del(bmp);
free(bmp);

or from python:

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
import pyrobot.vision.cblob.blob as blob
bmp = blob.bitmap()
blob.Bitmap_init(blob, width, height)

# use the blob

blob.Bitmap_del(bmp)
#bmp itself gets cleaned up automatically

1.1.2.3. Blobdata_*
void Blobdata_init(struct blobdata* data, struct bitmap* theBitmap);
void Blobdata_del(struct blobdata* data)

Use the same protocol as for bitmap. Blobdata_init is the function that actually does the processing to convert a bitmap into a list of blobs.

1.1.2.4. Transducer functions
struct bitmap* bitmap_from_cap(struct image_cap* image, int width, int height,
                               double (*filter)(double, double, double),
                               double threshold);

struct bitmap* bitmap_from_ppm(char* filename,
                               double (*filter)(double, double, double),
                               double threshold);

struct bitmap* bitmap_from_pgm(char* filename,
                               double (*filter)(double, double, double),
                               double threshold);

struct bitmap* bitmap_from_8bitGrayArray(uint8_t* array, int width, int height,
                                         double (*filter)(double, double, double),
                                         double threshold);

struct bitmap* bitmap_from_8bitRGBArray(uint8_t* array, int width, int height,
                                         double (*filter)(double, double, double),
                                         double threshold);

struct bitmap* bitmap_from_32bitPackedRGBArray(uint32_t* array, int width, int height,
                                               double (*filter)(double, double, double),
                                               double threshold);

These functions transform images into bitmap structs. The (*filter) argument is a callback that takes a function pointer to a filter function. These filter functions are described below. They output a float value in the range [0.0, 1.0]. If the value they return is greater than threshold at a pixel, the pixel is set to 1 in the bitmap, otherwise it's set to 0. Remember that you still have to call Bitmap_del on the bitmap returned by these functions and free the pointer, although you do not have to malloc or Bitmap_init the bitmap before you call a transducer.

bitmap_from_cap takes an image_cap struct from the pyro.camera.v4l package, and returns a bitmap of the current image. The others should be self-explanitory

1.1.2.5. filter functions
double filter_red (double r, double g, double b);
double filter_green (double r, double g, double b);
double filter_blue (double r, double g, double b);
double filter_hue (double r, double g, double b);
double filter_saturation (double r, double g, double b);
double filter_brightness (double r, double g, double b);

These functions are for use with the tranducer functions, described above. They take an rgb value as three doubles in the range [0.0, 1.0], and return a number in the same range. Because of how SWIG works, if you want to use these functions from python, you much use their name in all caps. For example:

import pyrobot.vision.cblob.blob as blob

bmp = blob.bitmap_from_ppm("cap.ppm", blob.FILTER_BRIGHTNESS, 0.5)

If you are planning on adding a new filter, you must modify the SWIG interface file blob.i. The file looks like this:

%module blob
%include blob.h
%{
#include "blob.h"

typedef double (*FILTER_FUNC)(double, double, double);
const FILTER_FUNC FILTER_RED = filter_red;
const FILTER_FUNC FILTER_BLUE = filter_blue;
const FILTER_FUNC FILTER_GREEN = filter_green;
const FILTER_FUNC FILTER_HUE = filter_hue;
const FILTER_FUNC FILTER_SATURATION = filter_saturation;
const FILTER_FUNC FILTER_BRIGHTNESS = filter_brightness;
%}
typedef double (*FILTER_FUNC)(double, double, double);
const FILTER_FUNC FILTER_RED = filter_red;
const FILTER_FUNC FILTER_BLUE = filter_blue;
const FILTER_FUNC FILTER_GREEN = filter_green;
const FILTER_FUNC FILTER_HUE = filter_hue;
const FILTER_FUNC FILTER_SATURATION = filter_saturation;
const FILTER_FUNC FILTER_BRIGHTNESS = filter_brightness;

To add a new funciton, add two new const FILTER_FUNC lines, one inside the %{}% brackets, and one outside them.

1.1.2.6. Player/Stage export functions
player_blobfinder_data_t* make_player_blob(struct blobdata** blobs, uint32_t* channels, int n_channels);
playerblob_t* make_player_blob_varsize(struct blobdata** blobs, uint32_t* channels, int n_channels);
void playerblob_del(playerblob_t* blobs);
These functions convert a list of blobdata structs, built on different channels, to a struct that Player/Stage could use.