如何在包含数字的.bmp(二进制图像)中执行组件标记9 4 3 6

How to perform component labelling in a .bmp(binary image) containing digits 9 4 3 6?

本文关键字:组件 执行 图像 包含 数字 二进制 bmp      更新时间:2023-10-16

i具有284x1280尺寸的二进制BMP图像。图像包含数字9 4 3 6.我想在图像上执行组件标签,并在数字发生时标记标签。最初,它是一个二进制图像,在2D数组中仅0和1(0标记为背景,标记为数字(

我尝试编写一个组件标记功能(检查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. 您永远不会递增c,因此您被卡在标签2。

  2. 解决此问题后,您会发现单个对象被分解为许多标签。这是因为您仅检查递归功能中的3个邻居。您需要检查所有8个(或4个连接的社区(。是的,您的递归功能还必须能够向左和向上行驶以遵循复杂的形状。

  3. 此递归函数效率非常低,并且对象足够大,可能会导致堆栈溢出。而是可以编写一个循环,该循环沿着对象中的整个行传播。对象标签的最佳算法使用Union-Find算法,我鼓励您查找。