Как выполнить маркировку компонентов в формате .bmp (двоичное изображение), содержащем цифры 9 4 3 6? - PullRequest
0 голосов
/ 27 июня 2019

У меня двоичное изображение BMP размером 284x1280. Изображение содержит цифры 9 4 3 6. Я хочу выполнить маркировку компонентов на изображении и отмечать метки всякий раз, когда появляются цифры. Первоначально это двоичное изображение, в массиве которого только 0 и 1 (0 помечено как фон, а 1 - цифры)

Я пытался написать функцию маркировки компонента (проверка 8 соседей) и увеличивать счетчик всякий раз, когда нахожу компонент с меткой 1:

#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
int func(int w, int h, int a[][1280], int i, int j, int c)
{
 if(i==h||j==w)
  {
   return 0;
  }
 if(a[i][j+1]==1)
  {
a[i][j+1]=c; return func(w,h,a,i,j+1,c);
  }
 if(a[i+1][j]==1)
  {
a[i+1][j]=c; return func(w,h,a,i+1,j,c);
  }
 if(a[i+1][j+1]==1)
  {
a[i+1][j+1]=c; return func(w,h,a,i+1,j+1,c);
  }
 else
  {
    return 0;
  }
  }

 unsigned char* read_bmp(char *fname, int* _w, int* _h)
   {
    unsigned char head[54];
    FILE *f=fopen(fname,"rb");
    //BMP header is 54 bytes
    fread(head,1,54,f);
    int w=head[18]+(((int)head[19]) << 8)+(((int)head[20]) << 16)+ 
    (((int)head[21]) << 24);
    int h=head[22]+(((int)head[23]) << 8)+(((int)head[24]) << 16)+ 
    (((int)head[25]) << 24);
    //lines are aligned on 4-byte boundary
    int lineSize = (w / 8 + (w / 8) % 4);
    int fileSize=lineSize * h;
    unsigned char *img, *data;
    img =(unsigned char*)malloc(w * h), data =(unsigned 
    char*)malloc(fileSize);
    //skip the header
    fseek(f,54,SEEK_SET);
    //skip palette - two rgb quads, 8 bytes
    fseek(f,8,SEEK_CUR);
    //read data
    fread(data,1,fileSize,f);
    //decode bits
    int i, j, k, rev_j;
    for(j=0, rev_j=h-1;j<h;j++,rev_j--)
    {
      for(i=0;i<w/8;i++)
      {
        int fpos= j * lineSize + i, pos = rev_j * w + i * 8;
         for(k=0;k<8;k++)
          {
           img[pos+(7-k)]=(data[fpos] >> k) & 1;
          }
       }
    }
     free(data);
     *_w = w; *_h = h;
     return img;
   }


   int main()
   {
    int w, h, i, j, c1=0, c2=0, c3=0, c4=0, c5=0, c6=0;
    unsigned char* img=read_bmp("binary.bmp",&w,&h);
    int array[h][1280];
    char ch;
    for(j=0;j<h;j++)
     {
       for(i=0;i<1280;i++)
       {
        array[j][i]=(int(img[j * w + i])==0);
       }
     }
      register int c=2;
      for(i=0;i<h;i++)
      {
        for(j=0;j<1280;j++)
        {
          if(array[i][j]==1)
          {
            array[i][j]=c;
            func(w,h,array,i,j,c);
          }
       }
     }
      for(i=0;i<h;i++)
      {
       for(j=0;j<w;j++)
       {
         printf("%d",array[i][j]);
       }
      printf("\n");
     }
     return 0;
 }   

Я получаю массив из 0 и 2, тогда как он должен содержать 0,2,3,4,5 меток для других цифр. Как это исправить?

1 Ответ

0 голосов
/ 27 июня 2019
  1. Вы никогда не увеличиваете c, поэтому вы застреваете на ярлыке 2.

  2. Как только вы исправите это, вы заметите, что отдельные объекты разбиваютсяна многих этикетках.Это потому, что вы проверяете только 3 соседей в своей рекурсивной функции.Вам нужно проверить все 8 (или 4 для 4-х подключенного соседства).Да, ваша рекурсивная функция должна также иметь возможность перемещаться влево и вверх, чтобы следовать сложным формам.

  3. Эта рекурсивная функция очень неэффективна и с достаточно большим объектом она может вызвать стекпереполнение.Вместо этого вы можете написать цикл, который распространяется вдоль всей линии внутри объекта.Лучшие алгоритмы для маркировки объектов используют алгоритм объединения-поиска, я рекомендую вам посмотреть на это.

...