[BlueLeaf1336]> PROBLEMS> パターン認識への長い道のり>
| history | TOP |
2006/04/17:作成
| 2006/04/17 | TOP |
いきなりですが、パターン認識をやりたいと考えています。どんなパターンかというと顔です。画像の中の顔を見つけ出したいと、そう考えています。なぜか。それは、今オフラインなんでリンクを示せないのでまた別の時に書きます。
そこで、グレースケール変換です。カラー画像を直接扱うパターン認識処理って、勝手に思ってるだけですが、ないんじゃないかと。多分処理が重たいだけじゃないかと。ひょっとしたら2値画像で認識してしまうのかもしれませんが、とりあえず256色のグレースケールでやってみます。
とっかかりにふさわしく、完全無欠にパクってきました。
| ソースコード | TOP |
//-----------------------------------------------------------------------------
// グレースケール変換を行うクラス
type
TTest = class
protected
FWork: TBitmap;
FImage: TBitmap;
public
constructor Create();
destructor Destroy(); override;
procedure SetImage(Source: TBitmap);
public
property Image: TBitmap read FImage;
end;
//-----------------------------------------------------------------------------
// コンストラクタ
constructor TTest.Create();
begin
FWork := TBitmap.Create();
FImage := TBitmap.Create();
end;
//-----------------------------------------------------------------------------
// デストラクタ
destructor TTest.Destroy();
begin
FWork.Free();
FImage.Free();
end;
//-----------------------------------------------------------------------------
type
TTriple = packed record B, G, R: Byte; end;
PTriple = ^TTriple;
//-----------------------------------------------------------------------------
// 原画像セット
// Subject: [Delphi:48275] Re: はじめまして
// NTSC 加重平均法 最も品質が良さそう
procedure TTest.SetImage(Source: TBitmap);
var
x, y, i: Integer;
LogPalette: TMaxLogPalette;
pSource: PTriple;
pDest: PByte;
begin
// 加工のためにイメージを転記
FWork.Assign(Source);
FWork.PixelFormat := pf24bit;
// 最終イメージを設定
FImage.PixelFormat := pf8Bit;
FImage.Width := FWork.Width;
FImage.Height := FWork.Height;
with LogPalette do
begin
palNumEntries := 256;
palVersion := $0300;
for i := 0 to 255 do
begin
palPalEntry[i].peRed := 255 - i;
palPalEntry[i].peGreen := 255 - i;
palPalEntry[i].peBlue := 255 - i;
end;
end;
FImage.Palette := CreatePalette(PLogPalette(@LogPalette)^);
for y := 0 to FWork.Height - 1 do
begin
pSource := FWork.ScanLine[y];
pDest := FImage.ScanLine[y];
for x := 0 to FWork.Width - 1 do
begin
pDest^ := Round(255 - pSource.R * 0.298912 -
pSource.G * 0.586611 -
pSource.B * 0.114478);
Inc(pSource);
Inc(pDest);
end;
end;
// イメージを解放(2006.04.24 したらだめ?)
// FWork.FreeImage();
// FWork.ReleaseHandle();
end;
//-----------------------------------------------------------------------------
// 1000回変換してその平均時間を表示するテスト関数
procedure TForm1.Button1Click(Sender: TObject);
var
Test: TTest;
Tick: Cardinal;
i: Integer;
begin
Test := TTest.Create();
Tick := GetTickCount();
for i := 0 to 999 do
begin
Test.SetImage(Image1.Picture.Bitmap);
end;
Label1.Caption := FormatFloat('0.00[msec]', (GetTickCount() - Tick) / 1000);
Image2.Picture.Bitmap.Assign(Test.Image);
Test.Free();
end;
| 実行結果 | TOP |
その前に、上のコードでは、グレースケール変換を行うだけのクラスを何の脈絡もなく作ってますが、将来的にはパターン認識を行うクラスに画像を渡して、その時点で必要ならグレースケール変換を行うような感じで考えているので、こんな妙な事になってます。
ですが、今のところメインの処理は SetImage メソッドであり、そのメソッドになんらオリジナルなところはありません。
300pixel x 400pixel のフルカラー画像ですが、多分 13msec というのは、画像処理にかかる時間としては破格に長いような気がします。多分ですけど。でも、この時間が問題になるのは、まだまだ先のことだろうと思いますので、とりあえずこれで良しとします。それに、どこをチューニングできるかもわかりませんし。
| EOF | TOP |