ビットマップのデータで骨組みを取得するには


マーズ  2006-12-13 22:39:40  No: 24237

Delphiを使ってプログラムを作成しているのですが、

Delphiのプログラムに関してでなくてすみません。
アルゴリズムに関する質問ですがよろしくお願いします。

以下のように2値のビットマップのデータを編集して
画像データの骨組みを作成する方法もしくは
記述しているHP等を教えてください

●●●●●●●●●●  →  ○○○○○○○○○○
●●●●●●●●●●  →  ○●●●●●●●●○
●●●●●●●●●●  →  ○●○○○○○○●○
●●●        ●●●  →  ○●○○○○○○●○
●●●        ●●●  →  ○●○○○○○○●○
●●●●●●●●●●  →  ○●○○○○○○●○
●●●●●●●●●●  →  ○●●●●●●●●○
●●●●●●●●●●  →  ○●○○○○○○●○
●●●        ●●●  →  ○●○○○○○○●○
●●●        ●●●  →  ○●○○○○○○●○
●●●●●●●●●●  →  ○●○○○○○○●○
●●●●●●●●●●  →  ○●●●●●●●●○
●●●●●●●●●●  →  ○○○○○○○○○○

○○○○●●○○○○  →  ○○○○○●○○○○
○○○●●●●○○○  →  ○○○○●○●○○○
○○●●○○●●○○  →  ○○○●○○○●○○
○●●○○○○●●○  →  ○○●○○○○○●○
●●○○○○○○●●  →  ○●○○○○○○○●
○○●●●●●●○○  →  ○○○○○○○○○○
○○●●●●●●○○  →  ○○●●●●●●○○
○○○○●●○○○○  →  ○○○○○●○○○○
○○●●●●●●○○  →  ○○○○○●○○○○
○○●●●●●●○○  →  ○○●●●●●●○○
○○○○●●○○○○  →  ○○○○○●○○○○
○○●●●●●●○○  →  ○○○○○●○○○○
○○●●●●●●○○  →  ○○●●●●●●○○


orz  2006-12-13 23:16:11  No: 24238

骨組みって意味がよくわからないのですが、これって、いわゆる
ラスターからベクターへの変換でしょう(ラスベク変換)?
漢字OCRとか。

中身はよくわからんが、こういうことか?
ttp://sunak2.cs.shinshu-u.ac.jp/~miyao/Doctor/node8.html


ウォレス  2006-12-14 21:47:41  No: 24239

元ネタは、「C言語で学ぶ実践画像処理」
HPは  http://www.silphix.com/kaiba/image/4/
にありました。最後の  Hilditchの方法による二値画像の細線化例 のところです。

以下長いですがCからの移植コード。
ボタン1つとイメージ2つを貼って、細線化したいビットマップを用意します。
----------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Math;

type
  TRGBTripleArray = array[0..High(Integer) div 3 - 1] of RGBTRIPLE;
  PRGBTripleArray = ^TRGBTripleArray; //配列型のポインタ
  Tarray2d = array of array of Integer;

  TForm1 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    Image2: TImage;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    procedure thinning( var image_in , image_out :  Tarray2d);
    function  cconc( inb : array of Integer ): Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin

  Image1.Picture.LoadFromFile('gray002.bmp'); //適当にbmpのファイルをアサインすること
end;

function TForm1.cconc ( inb : array of Integer ) : Integer;
var
  i, icn :Integer;

begin
  icn := 0;

  i := 0;
  while( i < 8) do
  begin
    if (inb[i] = 0)then
    begin
      if (inb[i+1] = 255)  or  (inb[i+2] = 255)then
      begin
        Inc(icn);
      end;
    end;
    Inc(i,2);
  end;

  Result:= icn;
end;

procedure TForm1.thinning( var image_in , image_out :  Tarray2d);
var
   i, ix, iy, m, ir, iv, iw :Integer;
   ia ,ic : array[0..8] of Integer;
   X_SIZE, Y_SIZE :Integer;

begin

  image_out := image_in;

  X_SIZE := High(image_in[0]) +1;
  Y_SIZE := High(image_in   ) +1;

  m := 100; ir := 1 ;
  while (ir <> 0)do
  begin
    ir := 0;
    for iy := 1 to Y_SIZE-1 -1 do
    begin
      for ix := 1 to X_SIZE-1 -1 do
      begin
        if (image_out[iy][ix] <> 255)then  continue;
         ia[0] := image_out[iy  ][ix+1];
         ia[1] := image_out[iy-1][ix+1];
         ia[2] := image_out[iy-1][ix  ];
         ia[3] := image_out[iy-1][ix-1];
         ia[4] := image_out[iy  ][ix-1];
         ia[5] := image_out[iy+1][ix-1];
         ia[6] := image_out[iy+1][ix  ];
         ia[7] := image_out[iy+1][ix+1];
        for i := 0 to 8 -1 do
        begin
          if (ia[i] = m)then
          begin
            ia[i] := 255; ic[i] := 0;
          end
          else
          begin
            if (ia[i] < 255)then  ia[i] := 0;
            ic[i] := ia[i];
          end;
        end;
        ia[8] := ia[0]; ic[8] := ic[0];
        if (ia[0]+ia[2]+ia[4]+ia[6] = 255*4)then  continue;

        iv := 0; iw := 0;
        for i := 0 to 8 -1 do
        begin
          if (ia[i] = 255)then  Inc(iv);
          if (ic[i] = 255)then  Inc(iw);
        end;
        if (iv <= 1)then  continue;
        if (iw = 0 )then  continue;
        if (cconc(ia) <> 1)then  continue;
         if (image_out[iy-1][ix] = m)then
         begin
          ia[2] := 0;
          if (cconc(ia) <> 1)then  continue;
          ia[2] := 255;
        end;
        if (image_out[iy][ix-1] = m)then
        begin
          ia[4] := 0;
          if (cconc(ia) <> 1)then  continue;
          ia[4] := 255;
        end;
        image_out[iy][ix] := m; Inc(ir);
      end;
    end;
    Inc(m);

  end;

  for iy := 0 to Y_SIZE-1  do
  begin
    for ix := 0 to X_SIZE-1  do
    begin
      if (image_out[iy,ix] < 255)then  image_out[iy,ix] := 0;
    end;
  end;

end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Ps0, Ps1: PRGBTripleArray;
  thBMP: TBitMap;
  x ,y,d:Integer;

  image_in  : Tarray2d;
  image_out : Tarray2d;

begin

  thBMP := TBitMap.Create;
  thBMP.PixelFormat := pf24bit;
  Image1.Picture.Bitmap.PixelFormat := pf24bit;

  thBMP.Width  := Image1.Picture.Bitmap.Width;
  thBMP.Height := Image1.Picture.Bitmap.Height;

  Setlength( Image_in  , thBMP.Height,thBMP.Width );
  Setlength( Image_out , thBMP.Height,thBMP.Width );

  //水平のみ処理
  for y := 0 to Image1.Picture.Bitmap.Height - 1 do
  begin
    Ps0 := Image1.Picture.Bitmap.ScanLine[y];

    for x:= 0 to  Image1.Picture.Bitmap.Width -1  do //
    begin
      d := Ps0[x].rgbtGreen; //適当にGrennのデータ

      if d <128 then
        d:=0
      else
        d:=255;

      image_in[y,x] := d;
    end;
  end;

  thinning(image_in, image_out);

  for y := 0 to thBMP.Height - 1 do
  begin
    Ps0 := thBMP.ScanLine[y];

    for x:=0 to  thBMP.Width -1 do
    begin
      Ps0[x].rgbtRed   := image_out[y,x];
      Ps0[x].rgbtGreen := image_out[y,x];
      Ps0[x].rgbtBlue  := image_out[y,x];
    end;
  end;

  Image2.Picture.Bitmap.Assign(thBMP);

  thBMP.free;
end;
end.


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加