Delphiを使ってプログラムを作成しているのですが、
Delphiのプログラムに関してでなくてすみません。
アルゴリズムに関する質問ですがよろしくお願いします。
以下のように2値のビットマップのデータを編集して
画像データの骨組みを作成する方法もしくは
記述しているHP等を教えてください
●●●●●●●●●● → ○○○○○○○○○○
●●●●●●●●●● → ○●●●●●●●●○
●●●●●●●●●● → ○●○○○○○○●○
●●● ●●● → ○●○○○○○○●○
●●● ●●● → ○●○○○○○○●○
●●●●●●●●●● → ○●○○○○○○●○
●●●●●●●●●● → ○●●●●●●●●○
●●●●●●●●●● → ○●○○○○○○●○
●●● ●●● → ○●○○○○○○●○
●●● ●●● → ○●○○○○○○●○
●●●●●●●●●● → ○●○○○○○○●○
●●●●●●●●●● → ○●●●●●●●●○
●●●●●●●●●● → ○○○○○○○○○○
○○○○●●○○○○ → ○○○○○●○○○○
○○○●●●●○○○ → ○○○○●○●○○○
○○●●○○●●○○ → ○○○●○○○●○○
○●●○○○○●●○ → ○○●○○○○○●○
●●○○○○○○●● → ○●○○○○○○○●
○○●●●●●●○○ → ○○○○○○○○○○
○○●●●●●●○○ → ○○●●●●●●○○
○○○○●●○○○○ → ○○○○○●○○○○
○○●●●●●●○○ → ○○○○○●○○○○
○○●●●●●●○○ → ○○●●●●●●○○
○○○○●●○○○○ → ○○○○○●○○○○
○○●●●●●●○○ → ○○○○○●○○○○
○○●●●●●●○○ → ○○●●●●●●○○
骨組みって意味がよくわからないのですが、これって、いわゆる
ラスターからベクターへの変換でしょう(ラスベク変換)?
漢字OCRとか。
中身はよくわからんが、こういうことか?
ttp://sunak2.cs.shinshu-u.ac.jp/~miyao/Doctor/node8.html
元ネタは、「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.
ツイート | ![]() |