2017-02-15 3 views
0

У меня есть результат сегментации изображения, в котором у меня есть разные объекты, имеющие отдельные границы. Т.е. у меня может быть несколько контуров над изображением. Я хочу написать алгоритм, который будет отслеживать весь контур и выдавать выходные данные в виде связанных точек пикселя для каждого контура. Есть ли какой-либо ранее определенный алгоритм для этой проблемы?Найти подключенные пиксельные точки нескольких контуров

ответ

0

Да, в библиотеке обработки двоичного изображения

https://github.com/MalcolmMcLean/binaryimagelibrary

Это довольно ломоть кода

#define CNT_TOPLEFT 0x80 
#define CNT_TOPRIGHT 0x40 
#define CNT_BOTTOMRIGHT 0x20 
#define CNT_BOTTOMLEFT 0x10 

#define CNT_RIGHT 1 
#define CNT_DOWN 2 
#define CNT_LEFT 3 
#define CNT_UP 4 

static int walkcontour(unsigned char *binary, int width, int height, int x, int y, int dir, double **cx, 
         double **cy, int *Nret); 


/** 
    Go round a binary image, extracting the contours of the set pixels. 

    @param[in] binary - the image 
    @param width - image width 
    @param height - image height 
    @param[out] x - return for x co-ordinates of contours (malloced) 
    @param[out] y - return for y co-ordinates of contours (malloced) 
    @param[out] Nret - return for contour lengths (malloced) 
    @returns Number contours found, -1 on out of memory. 
*/ 
int getcontours(unsigned char *binary, int width, int height, double ***x, double ***y, int **Nret) 
{ 
    int xi, yi; 
    int i; 
    unsigned char neighbours[9]; 
    int N; 
    double *cx, *cy; 
    int cN; 
    void *temp; 
    double **contourx = 0; 
    double **contoury = 0; 
    int *contourN = 0; 
    int err; 
    int answer = 0; 
    int capacity = 0; 

    for(yi=0;yi<height;yi++) 
    { 
     for(xi=0;xi<width;xi++) 
     { 
      if(binary[yi*width + xi] & 0x01) 
      { 
       get2x2(neighbours, binary, width, height, xi, yi, 0); 
       N = 0; 
       for(i=0;i<4;i++) 
        N += neighbours[i] & 0x01; 
       if(N != 4) 
       { 
        if((binary[yi*width+xi] & CNT_TOPLEFT) == 0 && 
         (neighbours[0] & neighbours[1] & neighbours[3] &0x01) == 0) 
        { 
         err = walkcontour(binary, width, height, xi, yi, CNT_RIGHT, &cx, &cy, &cN); 
         if(err == 0) 
         { 
          if(answer >= capacity) 
          { 
           capacity = capacity + capacity/2 + 10; 
           temp = realloc(contourN, capacity * sizeof(int)); 
           contourN = temp; 
           temp = realloc(contourx, capacity * sizeof(double *)); 
           contourx = temp; 
           temp = realloc(contoury, capacity * sizeof(double *)); 
           contoury = temp; 
          } 
          contourN[answer] = cN; 
          contourx[answer] = cx; 
          contoury[answer] = cy; 
          answer++; 
         } 
        } 
        /* 
        if((binary[yi*width+xi] & CNT_TOPRIGHT) == 0 && 
         (neighbours[1] & neighbours[2] & neighbours[5] &0x01) == 0) 
        { 
         walkcontour(binary, width, height, xi +1, yi, CNT_DOWN, &cx, &cy, &cN); 

        } 
        if((binary[yi*width+xi] & CNT_BOTTOMRIGHT) == 0 && 
         (neighbours[5] & neighbours[7] & neighbours[8] &0x01) == 0) 
        { 
         walkcontour(binary, width, height, xi, yi+1, CNT_LEFT, &cx, &cy, &cN); 

        } 
        if((binary[yi*width+xi] & CNT_BOTTOMLEFT) == 0) 
        { 
         if((binary[yi*width+xi] & CNT_BOTTOMRIGHT) == 0 && 
          (neighbours[5] & neighbours[7] & neighbours[8] &0x01) == 0) 
         walkcontour(binary, width, height, xi+1, yi+1, CNT_UP, &cx, &cy, &cN); 

        } 
        */ 

       } 
      } 
     } 
    } 

    for(yi=0;yi<height;yi++) 
    { 
     for(xi=0;xi<width;xi++) 
      binary[yi*width+xi] &= 0x01; 
    } 
    *x = contourx; 
    *y = contoury; 
    *Nret = contourN; 

    return answer; 
} 

static int walkcontour(unsigned char *binary, int width, int height, int x, int y, int dir, double **cx, 
       double **cy, int *Nret) 
{ 
    int N = 0; 
    int advance; 
    int capacity = width + 3; 
    double *xwalk, *ywalk; 
    double *temp; 
    unsigned char neighbours[9]; 
    int xi, yi; 
    int mask; 

    switch(dir) 
    { 
     case CNT_RIGHT: mask = CNT_TOPLEFT; break; 
     case CNT_DOWN: mask = CNT_TOPRIGHT; break; 
     case CNT_LEFT: mask = CNT_BOTTOMRIGHT; break; 
     case CNT_UP: mask = CNT_BOTTOMLEFT; break; 

    } 
    mask = CNT_TOPLEFT; 

    xwalk = malloc(capacity * sizeof(double)); 
    ywalk = malloc(capacity * sizeof(double)); 
    if(!xwalk || ! ywalk) 
     goto out_of_memory; 
    xi = x; 
    yi = y; 
    while(1) 
    { 
     get2x2(neighbours, binary, width, height, xi, yi, 0); 
     advance = 0; 
     while(advance == 0) 
     { 
      switch(dir) 
      { 
       case CNT_RIGHT: 
        if(neighbours[1] & 0x01) 
         dir = CNT_UP; 
        else 
         advance = 1; 
        break; 
       case CNT_DOWN: 
        if(neighbours[3] & 0x01) 
         dir = CNT_RIGHT; 
        else 
         advance = 1; 
        break; 
       case CNT_LEFT: 
        if(neighbours[2] & 0x01) 
         dir = CNT_DOWN; 
        else 
         advance = 1; 
        break; 
       case CNT_UP: 
        if(neighbours[0] & 0x01) 
         dir = CNT_LEFT; 
        else 
         advance = 1; 
        break; 

      } 
     } 

     xwalk[N] = xi; 
     ywalk[N] = yi; 
     N++; 
     if(N >= capacity) 
     { 
      capacity += capacity/2; 

      temp = realloc(xwalk, capacity * sizeof(double)); 
      if(!temp) 
       goto out_of_memory; 
      xwalk = temp; 

      temp = realloc(ywalk, capacity * sizeof(double)); 
      if(!temp) 
       goto out_of_memory; 
      ywalk = temp; 
     } 
     advance = 0; 

     if(yi < height && xi < width) 
      binary[yi*width+xi] |= CNT_TOPLEFT; 
     if(yi < height && xi > 0) 
      binary[yi*width+xi-1] |= CNT_TOPRIGHT; 
     if(yi > 0 && xi < width) 
      binary[(yi-1)*width+xi] |= CNT_BOTTOMLEFT; 
     if(xi > 0 && yi > 0) 
       binary[(yi-1)*width+xi-1] |= CNT_BOTTOMRIGHT; 

     switch(dir) 
     { 
      case CNT_RIGHT: xi++; break; 
      case CNT_DOWN: yi++; break; 
      case CNT_LEFT: xi--; break; 
      case CNT_UP: yi--; break; 
     } 

     get2x2(neighbours, binary, width, height, xi, yi, 0); 
     while(advance == 0) 
     { 
      switch(dir) 
      { 
       case CNT_RIGHT: 
        if(!(neighbours[3] & 0x01)) 
         dir = CNT_DOWN; 
        else 
         advance = 1; 
        break; 
       case CNT_DOWN: 
        if(!(neighbours[2] & 0x01)) 
         dir = CNT_LEFT; 
        else 
         advance = 1; 
        break; 
       case CNT_LEFT: 
        if(!(neighbours[0] & 0x01)) 
         dir = CNT_UP; 
        else 
         advance = 1; 
        break; 
       case CNT_UP: 
        if(!(neighbours[1] & 0x01)) 
         dir = CNT_RIGHT; 
        else 
         advance = 1; 
        break; 

      } 
     } 
     if(yi == y && xi == x && (binary[yi*width+xi] & mask)) 
      break; 

    } 
    *cx = xwalk; 
    *cy = ywalk; 
    *Nret = N; 
    return 0; 
out_of_memory: 
    free(xwalk); 
    free(ywalk); 
    *cx = 0; 
    *cy =0; 
    *Nret = 0; 
    return -1; 

} 
Смежные вопросы