[Delphi:90072] グレースケールの画像をもとにしたマスク処理

290 views
Skip to first unread message

Hiroyuki Nakano

unread,
Nov 16, 2007, 9:22:18 PM11/16/07
to Delphi ML
nappaといいます。

グレースケールの画像をもとにマスク処理をして
その濃度に合わせて透明処理をして
AとBの2つの画像を合成したいと考えています。

白黒2値の画像をもとにマスク処理をして
AとBの2つの画像を合成することはできます。

グレースケールのピクセルを1つずつ調べて
その値によって合成していく方法もありかとは思いましたが、
大きな画像になると時間がかかります。
よい方法がないかと探してみましたが、
見つけることができませんでした。

環境は、WindowsXP+Delphi5です。
Vistaでも可能な方法であれば幸甚です。
新しいバージョンならできるということであればできる
ということでも結構です。

よろしくご教授ください。

高木太郎

unread,
Nov 17, 2007, 8:42:18 AM11/17/07
to Del...@ml.users.gr.jp
 こんばんは、イマジオムの高木です。

nappaさん:
> グレースケールの画像をもとにマスク処理をして
> その濃度に合わせて透明処理をして
> AとBの2つの画像を合成したいと考えています。


>
> グレースケールのピクセルを1つずつ調べて
> その値によって合成していく方法もありかとは思いましたが、
> 大きな画像になると時間がかかります。
> よい方法がないかと探してみましたが、
> 見つけることができませんでした。

 いわゆる「アルファブレンド」処理ですね。 下記にポイントを記します。

1.まず絶対に必要なのが、TCanvas.Pixels[] プロパティを使わない
  ことです。 TBitMap.ScanLine プロパティを使ってください。

2.もうすでに TBitMap.ScanLine プロパティを使っているのでしたら、
  1ピクセルあたりの処理にかかっている時間を調べてください。 10
  [μs]もかかっているようでしたら、アルゴリズムを見直す価値が
  ありそうです。

3.1ピクセルあたり0.1[μs]以下の時間しかかかっておらず、さらに
  早くしたいということですと、OpenGL を使った手法というのがあります。
  これは OpenGL のテクスチャマッピング関数を使い、複数枚の画像を重ね
  合わせる手法です。 できることは限られ、またシステムが特異な挙動を
  するリスクが生じます(※)が、相当早くなると思います。

   ※:OpenGL ユニットは、CPUの浮動小数点演算ユニット(FPU)の
     フラグを書き換え、浮動小数点例外を抑止します。 そのため浮動
     小数点例外を利用しているプログラムが正しく動作しなくなることが
     あるのです。

4.それでも遅いということでしたら、並列処理の出番です。 プログラムを
  マルチスレッド化し、複数のCPUコアを持つハイエンドのPCで処理を
  行わせれば、4~8倍の処理速度が得られるかもしれません(手前味噌
  ですが、これが弊社の本業です)。

5.4の代わりに、特殊な画像処理ハードウェアを使う手もあります。 しかし
  コストがかかるので、単にアルファブレンドだけに使うのはもったいない
  気もします。 最後の手段としてご検討ください。
――――――――――――――――――――――――――――――――――――
株式会社イマジオム 代表取締役 高木太郎
〒316-0024 茨城県 日立市 水木町 1-11-10
電話:0294-28-0147
ファクシミリ:0294-28-0148
電子メール:tarou_...@imageom.co.jp
ホームページ:http://www.imageom.co.jp/


khe00221

unread,
Nov 17, 2007, 8:19:11 PM11/17/07
to Del...@ml.users.gr.jp
KHE00221

アルファブレンド合成の方法自体が 分からないのかな?

AlphaBlendを含まない画像にAlphaBlendを含む画像を描画

AB := AlphaBlendRow[X];
R2 := SaveRow[X].Red ;
G2 := SaveRow[X].Green ;
B2 := SaveRow[X].Blue ;
R1 := BitmapRow[X].Red ;
G1 := BitmapRow[X].Green;
B1 := BitmapRow[X].Blue ;
SaveRow[X].Red := ( (R1 - R2) * AB div 255 + R2);
SaveRow[X].Green := ( (G1 - G2) * AB div 255 + G2);
SaveRow[X].Blue := ( (B1 - B2) * AB div 255 + B2);

AlphaBlendを含む画像にAlphaBlendを含む画像を描画

AB2 := LayerAlphaBlendRow[X];
if AB2 <> 0 then
begin
AB1 := AlphaBlendRow[X];
AB3 := (AB1 + AB2) - AB1 * AB2 div 255;
R1 := BitmapRow[X].Red ;
G1 := BitmapRow[X].Green;
B1 := BitmapRow[X].Blue ;
R2 := LayerRow[X].Red ;
G2 := LayerRow[X].Green ;
B2 := LayerRow[X].Blue ;
BitmapRow[X].Red := Set255( (R2 * AB2 + R1 * AB1 * (255 - AB2) div 255)
div AB3);
BitmapRow[X].Green := Set255( (G2 * AB2 + G1 * AB1 * (255 - AB2) div 255)
div AB3);
BitmapRow[X].Blue := Set255( (B2 * AB2 + B1 * AB1 * (255 - AB2) div 255)
div AB3);
AlphaBlendRow[X] := AB3;
end;

------------------------------
http://khe00221.image.coocan.jp/
------------------------------

Hiroyuki Nakano

unread,
Nov 18, 2007, 12:05:59 AM11/18/07
to Del...@ml.users.gr.jp
高木さん、KHE00221さん ありがとうございます。

 > アルファブレンド合成の方法自体が 分からないのかな?

はい。
 難しいことはわからないので、
 つぎのような手順をイメージしておりました。

(1)画像データを指定
     aBitmap:='AAA.BMP';

(2)その画像へのマスク画像を指定
   ※Mask.BMPはグレースケール画像になっている
     aBitmap.Mask:='Mask.BMP';

(3)背景データ(BBB.BMP)にaBitmapを描画すると
   指定したマスク画像によって半透明処理される

私には手に負えるレベルではないようですが
 よい知恵がありましたらご教授願えれば幸いです。


khe00221

unread,
Nov 18, 2007, 1:31:00 AM11/18/07
to Del...@ml.users.gr.jp
KHE00221 です 

90074 で分かってもらえなかったようなので・・・・

ABitmap (24bit画像データ) を AlphaBlendBitmap (AlphaBlend 8bitビットマップ)

を考慮して BBitmap(24bit画像データ) に描画する。

ABitmap と BBitmapは同じサイズとする

(*) BBitmap に AlphaBlend を含んだ画像の場合これはで出来ません

type

TRGB = packed record
Blue : Byte;
Green : Byte;
Red : Byte;
end;

PRGBArray = ^TRGBarray;
TRGBArray = array[0..0] of TRGB;

var
AlphaBlendRow : pArrayByte;
ABitmaoRow,BBitmapRow : pRGBArray;
X,Y,AB,R1,R2,G1,G2,B1,B2 : Integer;
begin
for Y :=0 to BBitmap.Height -1 do
begin
ABitmapRow := ABitmap.Scanline[Y];
AlphaBlendRow := AlphaBlendBitmap.Scanline[Y];
BBitmapRow := BBitmap.Scanline[Y];
for X := 0 to BBitmap.Width -1 do
begin
AB := AlphaBlendRow[X];
R2 := ABitmapRow[X].Red ;
G2 := ABitmapRow[X].Green ;
B2 := ABitmapRow[X].Blue ;
R1 := BBitmapRow[X].Red ;
G1 := BBitmapRow[X].Green;
B1 := BBitmapRow[X].Blue ;
ABitmapRow[X].Red := ( (R1 - R2) * AB div 255 + R2);
ABitmapRow[X].Green := ( (G1 - G2) * AB div 255 + G2);
ABitmapRow[X].Blue := ( (B1 - B2) * AB div 255 + B2);
end;
end;

end;

(*) 手書きなのでチェックはしていません

------------------------------
http://khe00221.image.coocan.jp/
------------------------------

----- Original Message -----
From: "Hiroyuki Nakano" <na...@kisnet.or.jp>

tknak...@brain-tokyo.jp

unread,
Nov 18, 2007, 1:24:14 AM11/18/07
to Del...@ml.users.gr.jp
中村@ブレーンです。

以下のコードで合成すると Celeron 3GB で 5msec 程度ですね。
1200 X 1000pixel 換算でで 140msec (1秒間に7枚程度)
参考になれば幸いです。

var
x, y: Integer;
gb, bm1, bm2, bm3: TBitmap; // gb: グレイスケールビットマップ pf8bit
// bm1, bm2: 合成元画像 pf24bit
// bm3: 合成先画像 pf24bit
// 全て 240 X 180 pixel
pByteGS: ^Byte;
pByte1, pByte2, pByte3: ^Byte;
alpha: Integer;
:
:

bm3 := TBitmap.Create;
bm3.PixelFormat := pf24bit;
bm3.Width := gb.Width;
bm3.Height := gb.Height;

for y := 0 to gb.Height - 1 do
begin
pByteGS := gb.Scanline[y];
pByte1 := bm1.Scanline[y];
pByte2 := bm2.Scanline[y];
pByte3 := bm3.Scanline[y];

for x := 0 to gb.Width -1 do
begin
alpha := pByteGS^;

pByte3^ := pByte1^ * alpha div 255 + pByte2^ * (255 - alpha) div 255;
Inc(pByte1); Inc(pByte2); Inc(pByte3);
pByte3^ := pByte1^ * alpha div 255 + pByte2^ * (255 - alpha) div 255;
Inc(pByte1); Inc(pByte2); Inc(pByte3);
pByte3^ := pByte1^ * alpha div 255 + pByte2^ * (255 - alpha) div 255;
Inc(pByte1); Inc(pByte2); Inc(pByte3);
Inc(pByteGS);
end;
end;

Quoting Hiroyuki Nakano <na...@kisnet.or.jp>:

----------
(株)ブレーン 中村拓男

tknak...@brain-tokyo.jp

unread,
Nov 18, 2007, 2:13:30 AM11/18/07
to Del...@ml.users.gr.jp
Quoting tknak...@brain-tokyo.jp:

> 中村@ブレーンです。
>
> 以下のコードで合成すると Celeron 3GB で 5msec 程度ですね。
> 1200 X 1000pixel 換算でで 140msec (1秒間に7枚程度)
> 参考になれば幸いです。

誤りがありました。Celeron 3GHz ですね(^^; もうしわけない。


----------
(株)ブレーン 中村拓男

Hiroyuki Nakano

unread,
Nov 18, 2007, 6:27:10 AM11/18/07
to Del...@ml.users.gr.jp
KHE00221さん、中村さん

 貴重なコードをありがとうございました。
 理解できるレベルではありませんが、
 いただいたコードをもとに試してみたいと思います。

mori kohta

unread,
Nov 19, 2007, 12:35:13 PM11/19/07
to Del...@ml.users.gr.jp
現在、MS Wordと連携するアプリケーションの作成を検討中です。
Word のVBAを利用するのがいいか、DelphiでTWordApplicationやTWordDocumentを介して作るのがいいか、考えているのですが、そもそもCOMオブジェクトで何ができるのか情報が少なすぎて決めかねています。Helpも、少なくとも自分の使っているTurbo Delphi 2006にはついていないですし。。。
 
出来ることなら独立したアプリケーションとしてDelphiで作成できることが理想です。実現が難しい場合に、VBAによる方法をとりたいと考えています。
 
そこで伺いたいのは次の2点です。
(1) COMオブジェクトについて学べる書籍・HPはないか(英語でも構いません)。
(2) WordのVBAでできることと、COMによる連携で出来ることに、差はどれほどあるのか。特に、「ページ設定・書式設定・目次作成・索引作成」などの可否について。
 
以上、知恵を貸していただけると幸いです。
 
森浩太
 


New Design Yahoo! JAPAN 2008/01/01

tknak...@brain-tokyo.jp

unread,
Nov 20, 2007, 5:33:43 AM11/20/07
to Del...@ml.users.gr.jp
中村@ブレーンです。

Quoting mori kohta <kmo...@yahoo.co.jp>:

> (1) COMオブジェクトについて学べる書籍・HPはないか(英語でも構いません)。

やっぱりこれだと思います。
「Delphi COM Programming」
http://www.amazon.com/Delphi-COM-Programming-Eric-Harmon/dp/1578702216

こいつのオートメーションに関する解説は秀逸です。
#日本のAmazon での価格は恐ろしく高額ですね。

> (2) WordのVBAでできることと、COMによる連携で出来ることに、
> 差はどれほどあるのか。特に、「ページ設定・書式設定・目次作成・
> 索引作成」などの可否について。

VBA自身COMで動作しているので、基本的にはできることの差は無いはずです。
各論は良く知らないので、マクロ記録等で VBA のソースを Word に吐かせて
みてください。VBA のソースは COM に機械的に変換できます。

手での操作を VBA/COM で100% 実現できるわけではなかったと思います。

----------
(株)ブレーン 中村拓男

qs2...@inter7.jp

unread,
Nov 20, 2007, 5:49:22 AM11/20/07
to Del...@ml.users.gr.jp
サイミです。

> (2) WordのVBAでできることと、COMによる連携で出来ることに、差はどれほどあるのか。特に、「ページ設定・書式設定・目次作成・索引作成」などの可否について。

あなたのしたいことは、多分どちらでもできるでしょう。特に、オートメーショ
ンの部分は、そっくりなコードになるはずです。最も大きな差異は、Basicで書
くか、Pascalで書くかということだと思います。

> (1) COMオブジェクトについて学べる書籍・HPはないか(英語でも構いません)。

Word Objectのマニュアルならば、Wordに付属している筈です。少なくとも、Word2002には付いていま
す。オンラインマニュアルの、
<Microsoft Wordのヘルプ>
-<プログラミング情報>
-<Microsoft Word Visual Basic リファレンス>
以下です。

MSDN Onlineなら、以下のURLです。
http://msdn2.microsoft.com/en-us/library/bb244391.aspx

COM全般についての参考書ですと、"Inside Ole2", "Inside COM", "Essential
COM"などの名著があるのですが、翻訳版はみな絶版のようです。

--
qs2...@inter7.jp <qs2...@inter7.jp>


junki

unread,
Nov 20, 2007, 11:43:49 AM11/20/07
to Del...@ml.users.gr.jp
こんにちは、junki です。

おそレスですが、表題どおりのことを以前HPに書きました。
参考になれば幸いです。

http://junki.lix.jp/delphigr/079MaskedOverlay2.htm

------------------------
junki junki@yahoo.co.jp

Hiroyuki Nakano

unread,
Nov 20, 2007, 8:11:35 PM11/20/07
to Del...@ml.users.gr.jp
junkiさん こんにちは

> おそレスですが、表題どおりのことを以前HPに書きました。
> 参考になれば幸いです。
>
> http://junki.lix.jp/delphigr/079MaskedOverlay2.htm

 まさにこのとおりのことがやりたかったのです。
 junkiさんのページは以前から知っており
 参考にしておりましたが、
 この部分は見落としておりました。

 感謝、感謝です。

Reply all
Reply to author
Forward
0 new messages