Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

// framegrabber stuffs

/* File name ......... : ELABOR.C
 * Project............ :
 * Object ............ :
 * Author ............ : Facchinetti Tullio
 * Language .......... : C
 * Compiler .......... : GNU C
 * Operative system .. : MS-DOS/HARTIK
 * Creation data ..... : 04/03/2000
 * Last modify ....... : 19/11/99
 */





#include <kernel/func.h>
#include <modules/cabs.h>
#include <stdio.h>
#include <drivers/pxc.h>
#include "demo.h"

PID camera_PID;
PID tracking_PID;

static CAB frameCAB;    // CAB di deposito delle immagini
static CAB trackingCAB; // CAB di deposito delle info di tracking


int img_border    =  10;
int window_width  =  40;
int window_height =  40;
TPixel pix_threshold = 128;

// a 256 grayscale palette
WORD gray_palette[256];

// the image to be putted on the screen
WORD converted_image[IMG_COL*IMG_ROW];

TDataObj sequence[N_FRAMES];



void border_up_function(KEY_EVT key)
{
  img_border++;
}

void border_down_function(KEY_EVT key)
{
  img_border--;
}

void threshold_up_function(KEY_EVT key)
{
  char st[50];
  pix_threshold++;
  sprintf(st, "threshold %4d", pix_threshold);
  mutex_lock(&mutex);
  grx_text(st, 400, 100, 255, 0);
  mutex_unlock(&mutex);
}

void threshold_down_function(KEY_EVT key)
{
  char st[50];
  pix_threshold--;
  sprintf(st, "threshold %4d", pix_threshold);
  mutex_lock(&mutex);
  grx_text(st, 400, 100, 255, 0);
  mutex_unlock(&mutex);
}

float distance(unsigned int x1, unsigned int y1,
               unsigned int x2, unsigned int y2)
{
  return(sqrt(((y2 - y1) * (y2 - y1)) + ((x2 - x1) * (x2 - x1))));
}

char scan_window_frame(TDataObj *data, TPixel *in_frame,
                       unsigned int xc, unsigned int yc, int border)
{
  unsigned long int offset;
  unsigned int i, j;
  TPixel pix;
  double sum_x = 0.0, sum_y = 0.0;
  unsigned int n_pix = 0;
  int x1, y1, x2, y2;  // Must be int!!!
  char found;

  data->x1 = N_COL;
  data->y1 = N_ROW;
  data->x2 = data->y2 = 0;
  data->xb = data->yb = -1;
  data->time_stamp = -1;

  found = 0;

  x1 = MAX_NUM((xc - window_width / 2), (border));
  y1 = MAX_NUM((yc - window_height / 2), (border));
  x2 = MIN_NUM((xc + window_width / 2), (N_COL - border));
  y2 = MIN_NUM((yc + window_height / 2), (N_ROW - border));

  for (i = y1; i < y2; i++) {
    for (j = x1; j < x2; j++) {
      offset = i * N_COL + j;
      pix = *(in_frame + offset);

#ifdef __BLACK_ON_WHITE
      // Pixel found (object is black, background is white)
      if (pix < pix_threshold) {
#else
      // Pixel found (object is white, background is black)
      if (pix > pix_threshold) {
#endif
        data->time_stamp = sys_gettime(NULL);
        found = 1;
        n_pix++;
        sum_x += j;
        sum_y += i;
//        *(in_frame + offset) = 0;
        if (i < data->y1)
          data->y1 = i;
        if (i > data->y2)
          data->y2 = i;
        if (j < data->x1)
          data->x1 = j;
        if (j > data->x2)
          data->x2 = j;

      } else {
//        *(in_frame + offset) = 255;
      }
    }
  }
  data->xb = sum_x / n_pix;
  data->yb = sum_y / n_pix;
  return(found);
}

char scan_all_frame(TDataObj *data, TPixel *in_frame)
{
  unsigned long int offset;
  unsigned int i, j;
  TPixel pix;
  double sum_x = 0.0, sum_y = 0.0;
  unsigned int n_pix = 0;
  char found;

  data->x1 = N_COL;
  data->y1 = N_ROW;
  data->x2 = data->y2 = 0;
  data->xb = data->yb = -1;
  data->time_stamp = -1;

  found = 0;

  // In a single image scanning it performs thresholding and computation
  for (i = img_border; i < N_ROW - img_border; i++) {
    for (j = img_border; j < N_COL - img_border; j++) {
      offset = i * N_COL + j;
      pix = *(in_frame + offset);

#ifdef __BLACK_ON_WHITE
      // Pixel found (object is black, background is white)
      if (pix < pix_threshold) {
#else
      // Pixel found (object is white, background is black)
      if (pix > pix_threshold) {
#endif
        data->time_stamp = sys_gettime(NULL);
        found = 1;
        n_pix++;
        sum_x += j;
        sum_y += i;
//        *(in_frame + offset) = 0;
        if (i < data->y1)
          data->y1 = i;
        if (i > data->y2)
          data->y2 = i;
        if (j < data->x1)
          data->x1 = j;
        if (j > data->x2)
          data->x2 = j;

      } else {
//        *(in_frame + offset) = 255;
      }
    }
  }
  data->xb = sum_x / n_pix;
  data->yb = sum_y / n_pix;
  return(found);
}

void tracking(int top_frame, int *track_x, int *track_y, int *int_vx, int *int_vy, int time_to)
{
  float vx, vy;

  vx = (float)(sequence[top_frame - 1].xb - sequence[top_frame - 2].xb) /
       (float)(sequence[top_frame - 1].time_stamp - sequence[top_frame - 2].time_stamp);
  vx *= 1000;

  vy = (float)(sequence[top_frame - 1].yb - sequence[top_frame - 2].yb) /
       (float)(sequence[top_frame - 1].time_stamp - sequence[top_frame - 2].time_stamp);
  vy *= 1000;

  *track_x = sequence[top_frame - 1].xb + vx * time_to;
  *track_y = sequence[top_frame - 1].yb + vy * time_to;

  *int_vx = vx * 1000;
  *int_vy = vy * 1000;
}

TASK tracking_task(void *arg)
{
//  static unsigned int n_frame = 0;
  char                found;
  TPixel              *grabber_frame;
  int                 top_frame = 0;
  TDataObj            current;
  TTracking           *track;

  frameCAB = PXC_GetCab();

  grabber_frame = cab_getmes(frameCAB);

  // Executes first time
  found = scan_all_frame(&current, grabber_frame);
  if (found) {
    memcpy(&sequence[top_frame], &current, sizeof(TDataObj));
    top_frame++;
  }

  cab_unget(frameCAB, grabber_frame);

  task_endcycle();

  while (1) {
    // Acquisizione immagine corrente
    grabber_frame = (TPixel *)cab_getmes(frameCAB);
    track = (TTracking *)cab_reserve(trackingCAB);

    // Estrazione della nuova trasformata sul frame corrente
    if (found) {
      found = scan_window_frame(&current, grabber_frame, current.xb, current.yb, img_border);
    } else {
      found = scan_all_frame(&current, grabber_frame);
    }

    track->found = found;

    if (found) {
      if (top_frame < N_FRAMES) {
        memcpy(&sequence[top_frame], &current, sizeof(TDataObj));
        top_frame++;
      } else {
        top_frame = 0;
        memcpy(&sequence[top_frame], &current, sizeof(TDataObj));
      }

      track->top_frame = top_frame;
      memcpy(&track->current, &current, sizeof(TDataObj));

      if (top_frame > 1) {
        tracking(top_frame, &track->predx, &track->predy,
                            &track->vx, &track->vy, 100);
      }
    } else {
      track->top_frame = top_frame = 0;
    }

    // Release CABs
    cab_putmes(trackingCAB, (char *)track);
    cab_unget(frameCAB, grabber_frame);

    task_endcycle();
  }
}







/*
 *
 *
 *
 * Camera task
 *
 *
 *
 *
 */



TASK camera_task(void *arg)
{
  register int        i,j,col,row;
  static unsigned int n_frame = 0;
  TPixel              *grabber_frame;
  TTracking           *track;
  char                st[50];

  // Inizializzazione del task
  frameCAB = PXC_GetCab();

  while (1) {
    n_frame++;
    sprintf(st, "frame n. %5d", n_frame);

    grx_text(st, 400, 224, white, 0);

    // Acquisizione immagine corrente
    grabber_frame = cab_getmes(frameCAB);

    for (i=1; i<IMG_ROW-1; i++)
      for (j=0; j<IMG_COL; j++) {
        col = (j*(N_COL-1))/(IMG_COL-1);
        row = (i*(N_ROW-1))/(IMG_ROW-1);
        converted_image[i*IMG_COL+j] = gray_palette[*(grabber_frame+row*N_COL+col)];
      }

    // Release CAB
    cab_unget(frameCAB, grabber_frame);

    for (j=0; j<IMG_COL; j++) {
      converted_image[j] = gray_palette[0];
      converted_image[(IMG_ROW-1)*IMG_COL+j] = gray_palette[0];
    }

    mutex_lock(&mutex);
    grx_putimage(IMG_X, IMG_Y, IMG_X+IMG_COL-1, IMG_Y+IMG_ROW-1,
                 (BYTE *)converted_image);
    mutex_unlock(&mutex);

    track = (TTracking *)cab_getmes(trackingCAB);

    if (track->found) {
      mutex_lock(&mutex);
//      sprintf(st, "found: %d", track->found);
//      grx_text(st, 400, 280, 255, 0);

      if (track->top_frame > 1) {
        int px, py;

//        sprintf(st, "top_frame %5d", track->top_frame);
//        grx_text(st, 400, 270, 255, 0);

        if (track->predx < img_border)
          px = img_border;
        else if (track->predx > N_COL-img_border)
          px = N_COL-img_border;
        else
          px = track->predx;

        if (track->predy < img_border)
          py = img_border;
        else if (track->predy > N_ROW-img_border)
          py = N_ROW-img_border;
        else
          py = track->predy;

        grx_disc(IMG_X+(px*2)/3, IMG_Y+(py*2)/3, 3, 127);

//        grx_disc(IMG_X+(current.xb*2)/3, IMG_Y+(current.yb*2)/3, 3, 127);
        grx_rect(IMG_X+(track->current.x1*2)/3, IMG_Y+(track->current.y1*2)/3,
                 IMG_X+(track->current.x2*2)/3, IMG_Y+(track->current.y2*2)/3, 127);

        sprintf(st, "speed = (%5d, %5d) pix/s", track->vx, track->vy);
        grx_text(st, 400, 232, white, 0);
      }
      mutex_unlock(&mutex);
    }
    cab_unget(trackingCAB, (char *)track);

    task_endcycle();
  }
}





/*
 *
 *
 *
 * Framegrabber Initialization
 *
 *
 *
 *
 */


void start_listener(TIME p);

void framegrabber_close(void *arg)
{
  PXC_Close();
}

void scenario_framegrabber()
{
  grx_text("Camera"              , 384, WAVE_Y-WAVE_HEIGHT-10, rgb16(0,0,255), black);
  grx_line(384,WAVE_Y-WAVE_HEIGHT-1,639,WAVE_Y-WAVE_HEIGHT-1,red);
}

void init_framegrabber(void)
{
  register int i;
  KEY_EVT my_key;
  TIME period;

  my_key.ascii = 'a';
  my_key.scan = KEY_A;
  keyb_hook(my_key, (void (*)(KEY_EVT *))threshold_up_function);

  my_key.ascii = 'z';
  my_key.scan = KEY_Z;
  keyb_hook(my_key, (void (*)(KEY_EVT *))threshold_down_function);

  my_key.ascii = 's';
  my_key.scan = KEY_S;
  keyb_hook(my_key, (void (*)(KEY_EVT *))border_up_function);

  my_key.ascii = 'x';
  my_key.scan = KEY_X;
  keyb_hook(my_key, (void (*)(KEY_EVT *))border_down_function);

  // Aggiusta la palette
    for (i = 0; i < 256; i++)
      gray_palette[i] = rgb16(i,i,i);
  //for (i = 0; i < 256; i++)
  //  grx_setcolor(i, i/4, i/4, i/4);

  mutex_lock(&mutex);
//  grx_text("Grabber enabled: no test!", 10, 10, 255, 0);

  // Some messages on screen
//  grx_text("A-Z change threshold", 400, 240, 255, 0);
//  grx_text("S-X change window borders", 400, 250, 255, 0);
  mutex_unlock(&mutex);

  period = PXC_Initiate(4);

  if (!period) {
    grx_close();
    cprintf("Problemi nell'inizializzazione del framegrabber\n");
        halt();
    sys_end();
  } else {
    TTracking *trdata;
    // tracking CAB init
    trackingCAB = cab_create("trackingCAB", sizeof(TTracking), 3);
    trdata = (TTracking *)cab_reserve(trackingCAB);
    trdata->found = 0;
    cab_putmes(trackingCAB, (char *)trdata);

    start_listener(period);
  }

  sys_atrunlevel(framegrabber_close, NULL, RUNLEVEL_BEFORE_EXIT);
}


void start_listener(TIME period)
{
  SOFT_TASK_MODEL m1, m2;

  soft_task_default_model(m1);
  soft_task_def_level(m1,1);
  soft_task_def_met(m1,WCET_TRACKING);
  soft_task_def_usemath(m1);
//  soft_task_def_aperiodic(m1);
  soft_task_def_period(m1,(PERIOD_TRACKING));
  soft_task_def_group(m1,1);
  soft_task_def_ctrl_jet(m1);
  soft_task_def_skip_arrivals(m1);
  tracking_PID = task_create("track", tracking_task, &m1, NULL);
  if (tracking_PID == -1) {
        grx_close();
        perror("FFTPlay: Could not create task <tra>\n");
        ll_abort(54);
    perror("FFTPlay: Could not create task <tracking>\n");
    sys_end();
  }

  soft_task_default_model(m2);
  soft_task_def_level(m2,1);
  soft_task_def_met(m2,WCET_CAMERA);
  soft_task_def_usemath(m2);
//  soft_task_def_aperiodic(m2);
  soft_task_def_period(m2,PERIOD_CAMERA);
  soft_task_def_group(m2,1);
  soft_task_def_ctrl_jet(m2);
//  soft_task_def_skip_arrivals(m2);
  camera_PID = task_create("cam", camera_task, &m2, NULL);
  if (camera_PID == -1) {
        grx_close();
        perror("FFTPlay: Could not create task <came>\n");
        ll_abort(54);
    perror("FFTPlay: Could not create task <camera>\n");
    sys_end();
  }

}

void start_framegrabber()
{
//  PXC_Push_Listener(tracking_PID,2);
  PXC_Start();
}