⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 marching.c

📁 Trung Nguyen 编写的一个简单的fast marching 算法
💻 C
字号:
/*--------------------------- Commande MegaWave -----------------------------*//* mwcommand   name = {marching};   author = {"Trung Nguyen"};   version = {"1.0"};   function = {"Fast Marching Level Set"};   usage = {        'l':[l=-1]->l               "level to print out (default: all levels)",     'e':error<-error                  "image of error",     in->in                      "input Fcurve",     size->size                  "size of image output",     out<-out                    "distance image"   };*/#include <stdio.h>#include <math.h>#include <time.h>#include "mw.h"#define PI 3.141592#define INFINITY 10000.0#define max(x, y) (x > y ? x : y)#define min(x, y) (x < y ? x : y)#define ARRAY_2D_ALLOC(array, iWidth, iHeight, type) \(array) = (type**) malloc((iHeight)*sizeof(type*)); \if((array) == NULL) mwerror(FATAL, 1, "ARRAY_2D_ALLOC --> memory"); \(array)[0] = (type*) calloc((iWidth)*(iHeight), sizeof(type)); \if((array)[0] == NULL) mwerror(FATAL, 1, "ARRAY_2D_ALLOC --> memory"); \for(i = 1; i < (iHeight); i++) \  (array)[i] = (array)[i-1]+(iWidth);enum Status {ALIVE, NARROW_BAND, FAR_AWAY};int MAX;typedef struct {  int    x;  int    y;} Element;Element*        heap;int*            heap_size;enum Status**   stat;double**        T;        /* distance of points */int**           pos;         /* position of a grid point in the heap */float sqr(float x) { return (x * x); }/*** Manipulate a heap at node i ***/void Heapify(Element* h, int N, int i) {  int       l, r, smallest;  Element   tmp;  l = 2 * i;   r = 2 * i + 1;  /* Find the smallest value between 3 nodes */  if (l <= *heap_size && T[h[l].x + MAX/2][h[l].y + MAX/2] < T[h[i].x + MAX/2][h[i].y + MAX/2])    smallest = l;  else smallest = i;    if (r <= *heap_size && T[h[r].x + MAX/2][h[r].y + MAX/2] < T[h[smallest].x + MAX/2][h[smallest].y + MAX/2])     smallest = r;  if (smallest != i) {        tmp = h[i];    h[i] = h[smallest];    h[smallest] = tmp;    pos[h[i].x + MAX/2][h[i].y + MAX/2] = i;    pos[h[smallest].x + MAX/2][h[smallest].y + MAX/2] = smallest;    Heapify(h, N, smallest);  }    }/* Extract the smallest value of a heap */Element Heap_Extract_Min(Element* h, int *N) {  Element min;    if (*N < 1) {    printf("error: heap underflow\n");    return min;  }    min = h[1];  pos[h[1].x + MAX/2][h[1].y + MAX/2] = 0;  h[1] = h[*N];  pos[h[1].x + MAX/2][h[1].y + MAX/2] = 1;    (*N)--;  Heapify(h, *N, 1);    return min;}/*** Insert an element into a heap ***/void Heap_Insert(Element* h, int* N, Element e) {  int i;  i = (N != NULL) ? ++(*N) : 0;    /* Find the best place for e */  while (i > 1 && T[h[i / 2].x + MAX/2][h[i / 2].y + MAX/2] > T[e.x + MAX/2][e.y + MAX/2]) {    h[i] = h[i / 2];    pos[h[i].x + MAX/2][h[i].y + MAX/2] = i;    i = i / 2;  }    h[i] = e;  pos[e.x + MAX/2][e.y + MAX/2] = i;}/*** Return G(A, B, C, D) at the value T ***/float G(float A, float B, float C, float D, float T) {  return (sqr(max(max(T - B, 0), -min(D - T, 0))) +    sqr(max(max(T - A, 0), -min(C - T, 0))));}/*** Approximate the gradient of a point (cf. Rouy and Tourin) ***/float Distance(float A, float B, float C, float D, float F) {  float low = -INFINITY;  float upp = INFINITY;  float time;  time = (low + upp) / 2;  while (low < upp &&  G(A, B, C, D, time) != F)     if (G(A, B, C, D, time) < F) {      low = time + 0.0001;      time = (low + upp) / 2;    }    else {      upp = time - 0.0001;      time = (low + upp) / 2;    }        return time;  }/*** Marching algorithm (cf. Sethian) ***/void Marching() {  Element p, e;  int i, j, k, fix;  while (*heap_size > 0) {    p = Heap_Extract_Min(heap, heap_size);    stat[p.x + MAX/2][p.y + MAX/2] = ALIVE;        for (k = 0; k < 4; k++) {      i = (k < 2 ? (k * 2 - 1) : 0);       j = (k < 2 ? 0 : k * 2 - 5);        if (p.x + i - 1 > -MAX/2 && p.x + i + 1 < MAX/2 && 	  p.y + j - 1 > -MAX/2 && p.y + j  + 1< MAX/2 &&	  stat[p.x + i + MAX/2][p.y + j + MAX/2] != ALIVE) {		T[p.x + i + MAX/2][p.y + j + MAX/2] 	  = Distance(T[p.x + i + MAX/2][p.y + j - 1 + MAX/2],		     T[p.x + i - 1 + MAX/2][p.y + j + MAX/2],		     T[p.x + i + MAX/2][p.y + j + 1 + MAX/2],		     T[p.x + i + 1 + MAX/2][p.y + j + MAX/2], 1.0);		for (fix = pos[p.x + i + MAX/2][p.y + j + MAX/2] / 2; fix >= 1; fix = fix / 2) 	  Heapify(heap, *heap_size, fix);	if (stat[p.x + i + MAX/2][p.y + j + MAX/2] == FAR_AWAY) {	  stat[p.x + i + MAX/2][p.y + j + MAX/2] = NARROW_BAND;	  e.x = p.x + i;	  e.y = p.y + j;	  Heap_Insert(heap, heap_size, e);	}	      }    }   }}/*** MAIN PROGRAM ***/void marching(in, l, size, out, error)      Fcurve in;     Fimage out, error;     int size;     int *l;{   int x, y, d, i, j, nb_points = 0;  double medx = 0, medy = 0;  float sum_error = 0;  Point_fcurve p;  Element e;  int print_error;  clock_t tick;  if (error) print_error = 1; else print_error = 0;  MAX = size + 2;  ARRAY_2D_ALLOC(T, MAX, MAX, double);  ARRAY_2D_ALLOC(pos, MAX, MAX, int);  ARRAY_2D_ALLOC(stat, MAX, MAX, enum Status);  for (i = 0; i < MAX; i++)    for (j = 0; j < MAX; j++) {      stat[i][j] = FAR_AWAY;      T[i][j] = INFINITY;    }    heap = (Element*) malloc(MAX * MAX * sizeof(Element));  heap_size = (int*) malloc(sizeof(int));  *heap_size = 0;    for (p = in->first; p; p = p->next) {    medx += p->x;    medy += p->y;    nb_points++;  }  medx /= nb_points;  medy /= nb_points;  for (p = in->first; p; p = p->next) {    x = (int)(p->x - medx);    y = (int)(p->y - medy);    if (x + MAX/2 < 0 || y + MAX /2 < 0 || x + MAX/2 > MAX || y + MAX/2 > MAX)      mwerror(FATAL, 1, "Output image size is too small");    stat[x + MAX/2][y + MAX/2] = ALIVE;    T[x + MAX/2][y + MAX/2] = 0.0;  }    for (x = -MAX/2; x < MAX/2; x++)    for (y = -MAX/2; y < MAX/2; y++)       if (stat[x + MAX/2][y + MAX/2] == ALIVE) {	for (i = -1; i <= 1; i++)	  for (j = -1; j <= 1; j++)	    if (stat[x + i + MAX/2][y + j + MAX/2] == FAR_AWAY)	      if (x * x + y * y < (x + i) * (x + i) + (y + j) * (y + j)) {		stat[x + i + MAX/2][y + j + MAX/2] = NARROW_BAND;		T[x + i + MAX/2][y + j + MAX/2] = i * i + j * j;		e.x = x + i;		e.y = y + j;		Heap_Insert(heap, heap_size, e);	      }	          }    Marching();  if  ((out = mw_change_fimage(out ,size, size)) == NULL)   mwerror(FATAL, 1, "Not enough memory !\n");  if  ((error = mw_change_fimage(error, size, size)) == NULL)   mwerror(FATAL, 1, "Not enough memory !\n");    for (x = 1; x < MAX - 1; x++)    for (y = 1; y < MAX - 1; y++) {      error->gray[(MAX - y - 2) * size + x - 1] = (T[x][y] == INFINITY) ? 0 :  fabs(T[x][y] - sqrt(sqr(x - MAX/2) + sqr(y - MAX/2)));      sum_error += sqr(error->gray[(MAX - y - 2) * size + x - 1]);      if (*l == -1)	out->gray[(MAX - y - 2) * size + x - 1] = (T[x][y] == INFINITY) ? 0 : T[x][y];      else	if (((int)(T[x][y])) == *l) 	  out->gray[(MAX - y - 2) * size + x - 1] = 255;	else	  out->gray[(MAX - y - 2) * size + x - 1] = 0;    }  if (print_error)    printf("Total squared error: %f\n", sum_error / (size * size));  free(heap);  free(heap_size);  free(stat[0]);  free(stat);  free(T[0]);  free(T);  free(pos[0]);  free(pos);  printf("%f seconds\n", (float)clock() / CLOCKS_PER_SEC);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -