参考資料 1B
2010/05/01

ラベルファイルの構成


ラベリングファイルに記録されている情報

ラベリングデータファイルは、2つのファイルから構成されている。
1、ラベリング情報の補助ファイル(拡張子:.cfg)

2、ラベリングデータの実体(拡張子:.lbl)

ラベリングデータは、1画素あたり4バイト(unsigned int)で構成されたデータで、
記録形式は、32ビットBMPファイルの形式を流用している。ラベリングデータは、
入力画像中の画像の隅及び背景(輝度0)により分離されている部分を対象物と
認識し、対象物の連結性を8連結により解析して、各対象物に固有の番号の割り
当てを行った番号群である。(輝度0以外を対象物と認識 カラー、モノクロ共通)


ラベリング情報の補助ファイルは、BMPファイルの BITMAPFILEHEADER と、
BITMAPINFOHEADER を1つに纏めたもので、54バイトのデータで構成される。
32ビットBMPファイル(
biBitCount ≡ 32)であり、カラーマップは存在しない。
このファイルからは、画像の縦横の大きさを知る事が出来る。
32ビットBMPファイルでは画素の輝度を RGBQUAD で表しているが、ARGBは、
各1バイトの unsigned char により、R,G,B の色成分と1バイトの予約データの
構成をとっている。ラベリングデータは、この4バイトを一纏めにし、unsigned
int として、対象物の識別番号を格納するのに使用している。

 
CFG ファイルは、以下の構造を持っている (#pragma pack(push,2) でアライメントを2バイトにする)
ファイルヘッダー部
typedef struct LABELINGCFGA {
  WORD  bfType;        // unsigned short  2byte "BM"  0x4D42
  DWORD bfSize;        // unsigned long   4byte ファイル全体の大きさ[byte]
  WORD  bfReserved1;   // unsigned short  2byte  0 Fixed
  WORD  bfReserved2;   // unsigned short  2byte  0 Fixed
  DWORD bfOffBits;     // unsigned long   4byte
54 Fixed
LABELINGCFGA ;
ファイルヘッダー部
typedef struct LABELINGCFGB {                 //sizeof(BITMAPINFOHEADER)
  DWORD biSize;         // unsigned long  4byte 40 Fixed
  LONG  biWidth;        // long           4byte 画像の幅
  LONG  biHeight;       // long           4byte 画像の高さ±で画像の配置が逆
  WORD  biPlanes;       // unsigned short 2byte  1 Fixed
  WORD  biBitCount;     // unsigned short 2byte
32 Fixed
  DWORD biCompression;  // unsigned long  4byte  0:Fixed BI_RGB(無圧縮)
  DWORD biSizeImage;    // unsigned long  4byte 画像データのバイト数
  LONG  biXPelsPerMeter;// long           4byte  
0 Fixed
  LONG  biYPelsPerMeter;// long           4byte 
0 Fixed
  DWORD biClrUsed;      // unsigned long  4byte  0 Fixed
  DWORD biClrImportant; // unsigned long  4byte  0 Fixed
LABELINGCFGB ;
 
LBL ファイルは、以下の構造を持っている
ラベルデータ部
 
ラベルデータ数 = LABELINGCFGB->biWidth * abs(LABELINGCFGB->biHeight)
総データバイト数 = sizeof
(unsigned int) * ラベルデータ数

データの並び方(32ビットカラーBMPファイルと同等)
画像の横一列分のデータ(左から右方向)を単位にファイルに記録されている
BITMAPINFOHEADER-> biHeight が正の値の場合は、画像の最下部のデータから順に画像の
上部に向かって記録され、負の場合は、画像の上部のデータから、画像の最下部に向かって、
記録されている。
(実質的には、マイナスを用いた記録は行わない方針)
簡易的にデータを確認する方法としては、cfg 部と lbl 部をバイナリーデータとして結合させ、
BMP として映像で確認する方法がある。 ただし、対象物が少ないと画面はほぼ真っ黒。
 
copy /B
labelingCryst.cfg + labelingCryst.lbl  labelingCryst.bmp
%SystemRoot%\system32\mspaint.exe
labelingCryst.bmp
 


具体例による構造の確認

32ビットカラーの5x5 画素で構成されている画像から
ラベリングデータを作成した例

グレー部の値は、 (A,R,G,B)= (0x00,0x80,0x80,0x80)
白い部分の値は、 (A,R,G,B)= (0x00,0xFF,0xFF,0xFF)
背景(0)部の値は、(A,R,G,B)= (0x00,0x00,0x00,0x00)

輝度が0の部分を背景、0以外の輝度を持つ画素が対象物となる。
画像の縁と背景で囲まれた、独立した部分が個々の対象物と認識される。上記の例では
四つの対象物が存在する事になる。 ラベリング処理した結果を確認する。

labelingCryst.cfg をBMPヘッダーと見なしての情報表示
-- BITMAPFILEHEADER -- (14 Byte)
  unsigned short 2byte  "BM"     bfType        = 0x4D42
  unsigned long  4byte  ※1     bfSize        = 154
  unsigned short 2byte  0 Fixed  bfReserved1   = 0
  unsigned short 2byte  0 Fixed  bfReserved2   = 0
  unsigned long  4byte  ※2     bfOffBits     = 54
-- BITMAPINFOHEADER -- (40 Byte)
  unsigned long  4byte  40 byte  biSize          = 40
  long           4byte  画像の幅 biWidth         = 5
  long     ※3  4byte  画像の高 biHeight        = 5
  unsigned short 2byte  1 Fixed  biPlanes        = 1
  unsigned short 2byte  ※4     biBitCount      = 32
  unsigned long  4byte  ※5     biCompression   = 0
  unsigned long  4byte  ※6     biSizeImage     = 100
  long           4byte H解像度   biXPelsPerMeter = 0
  long           4byte V解像度   biYPelsPerMeter = 0
  unsigned long  4byte  ※7     biClrUsed       = 0
  unsigned long  4byte 重要色数  biClrImportant  = 0
labelingCryst.cfg, labelingCryst.lbl ファイルのダンプ
C:\>hexdump -C labelingCryst.cfg
00000000  42 4d 9a 00 00 00 00 00  00 00 36 00 00 00 28 00  |BM........6...(.|
00000010  00 00 05 00 00 00 05 00  00 00 01 00 20 00 00 00  |............ ...|
00000020  00 00 64 00 00 00 00 00  00 00 00 00 00 00 00 00  |..d.............|
00000030  00 00 00 00 00 00                                 |......|
00000036
C:\>hexdump -C labelingCryst.lbl
00000000  01 00 00 00 01 00 00 00  00 00 00 00 02 00 00 00  |................|
00000010  02 00 00 00 01 00 00 00  01 00 00 00 00 00 00 00  |................|
00000020  02 00 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 03 00 00 00  |................|
00000040  03 00 00 00 00 00 00 00  04 00 00 00 04 00 00 00  |................|
00000050  03 00 00 00 03 00 00 00  00 00 00 00 04 00 00 00  |................|
00000060  04 00 00 00                                       |....|
00000064


LABEL # 3  → ← LABEL # 4
LABEL # 1  → ← LABEL # 2

ラベルに擬似カラーを割り当てた画像


同胞されているコマンド(Label2colorBMP.exe)により作成
使用方法: Label2colorBMP labelingCryst PseudoColor.bmp

C:\>hexdump -C PseudoColor.bmp (擬似カラーBMPファイル化されたラベル情報)
00000000  42 4d 9a 00 00 00 00 00  00 00 36 00 00 00 28 00  |BM........6...(.|
00000010  00 00 05 00 00 00 05 00  00 00 01 00 20 00 00 00  |............ ...|
00000020  00 00 64 00 00 00 00 00  00 00 00 00 00 00 00 00  |..d.............|
00000030  00 00 00 00 00 00 80 00  00 00 80 00 00 00 00 00  |................|
00000040  00 00 00 80 00 00 00 80  00 00 80 00 00 00 80 00  |................|
00000050  00 00 00 00 00 00 00 80  00 00 00 80 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000070  00 00 80 80 00 00 80 80  00 00 00 00 00 00 00 00  |................|
00000080  80 00 00 00 80 00 80 80  00 00 80 80 00 00 00 00  |................|
00000090  00 00 00 00 80 00 00 00  80 00                    |..........|
0000009a

ラベルデータと対象物の擬似カラー表示に関して

ラベルデータは連続した単なる数値であり、視覚性には優れていない。
また、隣接した異なる対象物に同じ色(類似した色)が割り当てられると、識別が困難になる。

本環境では、ラベルデータと視覚性に優れた擬似カラーの間で、可逆変換が可能な方式を採用し、
2**24 = 4,294,967,295 個のラベルデータに対して、個別の色の割り当てが可能である。
(ビットの入れ替え操作を行っている)
今回提供しているプログラムの処理対象の画像データの大きさは、144,000,000 画素までの画像 (12,000x12,000画素相当の画像)に制限されているので、色変換の上限を超える事は無く、必ず
逆変換で元のラベルデータ値を知る事が可能である。
ただし、今回の計測データですら、ファイルに記録した時の最大容量は、500MB を超えてしまう
しまうので注意が必要である。

ラベルデータと擬似カラーの相互変換の関数を示す

ラベルデータを擬似カラーデータに変換するプログラム
unsigned int int2PseudoColor( unsigned int v )
{register unsigned int r=0, g=0, b=0 ;
    if( (v&0xff000000) != 0 ) return 0xffffffff ;
    if( (v&0x00ffffff) == 0 ) return 0 ;
    if( v & 0x000001 ) b |= 0x80 ;
    if( v & 0x000002 ) g |= 0x80 ;
    if( v & 0x000004 ) r |= 0x80 ;
    if( v & 0x000008 ) b |= 0x40 ;
    if( v & 0x000010 ) g |= 0x40 ;
    if( v & 0x000020 ) r |= 0x40 ;
    if( v & 0x000040 ) b |= 0x20 ;
    if( v & 0x000080 ) g |= 0x20 ;
    if( v & 0x000100 ) r |= 0x20 ;
    if( v & 0x000200 ) b |= 0x10 ;
    if( v & 0x000400 ) g |= 0x10 ;
    if( v & 0x000800 ) r |= 0x10 ;
    if( v & 0x001000 ) b |= 0x08 ;
    if( v & 0x002000 ) g |= 0x08 ;
    if( v & 0x004000 ) r |= 0x08 ;
    if( v & 0x008000 ) b |= 0x04 ;
    if( v & 0x010000 ) g |= 0x04 ;
    if( v & 0x020000 ) r |= 0x04 ;
    if( v & 0x040000 ) b |= 0x02 ;
    if( v & 0x080000 ) g |= 0x02 ;
    if( v & 0x100000 ) r |= 0x02 ;
    if( v & 0x200000 ) b |= 0x01 ;
    if( v & 0x400000 ) g |= 0x01 ;
    if( v & 0x800000 ) r |= 0x01 ;
    return (r <<16) | (g << 8) | b ;
}


擬似カラーデータをラベルデータに変換するプログラム
unsigned int pseudoColor2Int( unsigned int v )
{register unsigned int c=0 ;
    if( (v&0xff000000) != 0 ) return 0xffffffff ;
    if( (v&0x00ffffff) == 0 ) return 0 ;
    if ((v&0x00800000)) c|= 0x00000004 ;
    if ((v&0x00400000)) c|= 0x00000020 ;
    if ((v&0x00200000)) c|= 0x00000100 ;
    if ((v&0x00100000)) c|= 0x00000800 ;
    if ((v&0x00080000)) c|= 0x00004000 ;
    if ((v&0x00040000)) c|= 0x00020000 ;
    if ((v&0x00020000)) c|= 0x00100000 ;
    if ((v&0x00010000)) c|= 0x00800000 ;
    if ((v&0x00008000)) c|= 0x00000002 ;
    if ((v&0x00004000)) c|= 0x00000010 ;
    if ((v&0x00002000)) c|= 0x00000080 ;
    if ((v&0x00001000)) c|= 0x00000400 ;
    if ((v&0x00000800)) c|= 0x00002000 ;
    if ((v&0x00000400)) c|= 0x00010000 ;
    if ((v&0x00000200)) c|= 0x00080000 ;
    if ((v&0x00000100)) c|= 0x00400000 ;
    if ((v&0x00000080)) c|= 0x00000001 ;
    if ((v&0x00000040)) c|= 0x00000008 ;
    if ((v&0x00000020)) c|= 0x00000040 ;
    if ((v&0x00000010)) c|= 0x00000200 ;
    if ((v&0x00000008)) c|= 0x00001000 ;
    if ((v&0x00000004)) c|= 0x00008000 ;
    if ((v&0x00000002)) c|= 0x00040000 ;
    if ((v&0x00000001)) c|= 0x00200000 ;
    return c ;
}


go to TopPage go to CategoryTop