画像の合成

 画像の合成は、二枚以上の画像を重ね合わせることですが、一番良く使われるのは、人の画像を違う背景に貼り付けることですが、一番有名な合成画像は、UFO画像です。
今まで、沢山のUFO画像が公開せれていますが、未だにUFOの存在を証明するものはありません。
丹念に時間をかけて、合成画像を作成すれば、誰でもかなりレペルの高い合成画像を作成することが出来ます。
映像の場合は、合成する画像の数が多いので、プログラムに頼る必要があります。
 合成画像作成のためのツールは、インターネットで検索すれば、出てきますが、ここではダウンロードツールを利用するのではなく、合成の仕組みと、プログラムついて検討します。
2つの画像を重ね合わせる場合、前景になる画像と、背景になる画像の二画像となりますが、前景画像の必要な部分をだけを残した画像が必要となります。
実際には、前景画像を残す部分を白として、背景を透過させる部分を黒とした、クロマキー(Chroma-Key)画像を作成します。

1. ペイントによる画像の合成

元画像エディターキー合成ゼロ
    前景画像            クロマキー            合成画像

  一番左側が、前景となる画像で、合成するのに不要となる前景画像の背景部分を黒で塗りつぶします。これが中央の画像です。
この作業は、Windows標準のペイントで行いましたので、必要な部分を丹念に黒で縁取り後、不必要な部分をブラシで塗りつぶしをしています。
ペイントの場合、透過色を、第二色(背景色)として、色の指定が出来ます。
背景となる画像を開いておき、透過色を黒に指定して、貼り付ければ、一番右の画像のような画像を作成することが出来ます。
 現在はデジタル処理なので、簡単に合成が出来ますが、アナログの時代は大変でした。
ブルー・スクリーンを使用して、青い背景の画像を作成し、青だけを透過するフィルターにより、不必要な画像部が黒となるフィルムとそれを反転したフィルムを作成
次に、背景用クロマキーフィルムにより、前景部が露光されないようにし、次に前景用クロマキーフィルムにより、前景だけ露光します。
手順は逆でも構いませんが。
ブルースクリーンの使用は、人の顔の色と対比状態にあるのは、青だからですが、必要に応じて違う色を使用しても良いでしょう。

2.プログラムによる画像の合成

  デジタル画像の合成の場合、どの色を透過色にするかを決定し、透過色を黒(値 0)にします。
(単にキー画像なので、赤でも青でも構いませんが、黒だと説明がし易いので黒にしています。)

2-1 輝度値によるクロマキーの作成

    輝度値 = 赤 × 赤系数 + 緑 × 緑系数 + 青 × 青系数

  輝度値の値により、透過させるか、画像として残すかの判別をします。
前景画像のバック色の色に対して、マイナスの係数を与えると良い結果が得られます。
画像の条件により、色係数の値と、閾値の調整をする事により、目的とするクロマーキーを作成します。

キー値
2値化キー合成
  各ピクセルの値 青には、-1.35を乗じ、赤には1を乗じ 緑には1.2を乗じて 合計、2値化キーの場合閾値より大きかったら、255とし、小さかったら0としクロマキーを作成します。
値は、255 と 0 の2値となります。

 最大値、最小値は、全ピクセルをキー色係数で計算した場合の最大値と最小値を表しています。
参考表示です。


2値化キー合成

 2値化キーによるクロマキーと、合成画像ですが、一応それなりに透明感は出ていますが、滑らかさは有りません。



多値化キー合成

多値化キー合成 上限値と下限値を設け、その間を中間濃度として、中間の透過率とします。
色に対する係数は一応2値化キーと同じです。

 多値化キーによるクロマキーと合成画像は、半透明画像部が出来 前景画像と背景画像が透過度に応じて、加算されるので、合成画像が、柔らかい感じの画像となります。
透過度は、255がゼロパーセントで0が百パーセントとなります。

 前景用画像として、赤をバックにしたものを用意してみました。
赤バックキー係数クロマキー合成
 赤のキー係数をマイナスにして、多値のクロマキーを作成、合成してみました。
グラスの色が赤みがかっていますが、綺麗に合成ができています。

2-2 色相によるクロマキーの作成

 色相を指定し、その色相に近い色を透過色にすることに簡単にクロマキーの作成が出来るのではないかと思い、プログラムを作成してみました。

色相
 最初の前傾画像のバック色の色相を取り出すと、上図の様になります。
色相誤差は、透過色として判別する時の許容誤差です。
色相2値画像多値化キー画像
  グラスの透明な部分が、消えすぎて、あまり良い結果が得られませんでした。
透明な部分は、バックの色相と同じで、明度の差のみのだからだと思われます。

クロマキーの作成は、各色にたいする係数を調整して計算した輝度値で判別して作成するのが良いようです。

サンプルプログラム

unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, system.Math, Vcl.ExtDlgs, Vcl.ExtCtrls, System.UIConsts,
  Vcl.StdCtrls, System.UITypes, Vcl.Imaging.GIFImg;

type
  TForm1 = class(TForm)
    FileOpenBtn: TButton;
    ScrollBox1: TScrollBox;
    ScrollBox2: TScrollBox;
    Image1: TImage;
    Image2: TImage;
    OpenPictureDialog1: TOpenPictureDialog;
    SavePictureDialog1: TSavePictureDialog;
    FileSaveBtn: TButton;
    GroupBox1: TGroupBox;
    hard_maskBtn: TButton;
    LabeledEdit1: TLabeledEdit;
    GroupBox2: TGroupBox;
    LabeledEdit3: TLabeledEdit;
    LabeledEdit2: TLabeledEdit;
    Soft_maskBtn: TButton;
    ScrollBox3: TScrollBox;
    Image3: TImage;
    ScrollBox4: TScrollBox;
    Image4: TImage;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    GroupBox3: TGroupBox;
    RedEdit: TLabeledEdit;
    GreenEdit: TLabeledEdit;
    BlueEdit: TLabeledEdit;
    BakFileOpenBtn: TButton;
    LabeledEdit4: TLabeledEdit;
    LabeledEdit5: TLabeledEdit;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FileOpenBtnClick(Sender: TObject);
    procedure FileSaveBtnClick(Sender: TObject);
    procedure hard_maskBtnClick(Sender: TObject);
    procedure Soft_maskBtnClick(Sender: TObject);
    procedure BakFileOpenBtnClick(Sender: TObject);
  private
    { Private 宣言 }
    procedure FileOpen(InF : Boolean);
    procedure hard_mask;
    procedure soft_mask;
    procedure composit;
    function key_coefficient: Boolean;
    procedure MaxMin;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TPrgbarry = array[0..0] of Trgbtriple;      // 24ビットカラーレコード 32ビット用はTRGBQuadArray
  Prgbarray  = ^TPrgbarry;                    // ポインター


const
// ファイル拡張子設定
  OpenFileFilter =
    '画像ファイル|*.png;*.jpg;*.gif;*.bmp;*.tif;*.ico;*.wdp'+
    '|*.png|*.png' +
    '|*.jpg|*.jpg' +
    '|*.gif|*.gif' +
    '|*.bmp|*.bmp' +
    '|*.tif|*.tif' +
    '|*.ico|*.ico' +
    '|*.wdp|*.wdp';

  SaveFileFilter =
    '画像ファイル|*.png;*.jpg;*.gif;*.bmp;*.tif;*.wdp' +
    '|*.png|*.png' +
    '|*.jpg|*.jpg' +
    '|*.gif|*.gif' +
    '|*.bmp|*.bmp' +
    '|*.tif|*.tif' +
    '|*.wdp|*.wdp';

var
  InpBitmap       : TBitmap;                 // 前景ビットマップ
  BakBitmap       : TBitmap;                 // 背景ビットマップ
  OutBitmap       : TBitmap;                 // 出力用ビットマップ
  GHeight, GWidth : Integer;                 // 前景画像サイズ
  BHeight, BWidth : Integer;                 // 背景画像サイズ
  ImageKey        : array of array of byte;  // マスク用キー配列
  FImage          : Byte;                    // イメージフラグ 1bit 前景  2bit 背景
  Rkey, Gkey, Bkey: double;                  // キー作成用色係数
  Dmax, Dmin      : smallint;                // 最大値最小値

//==============================
// キー作成用色係数 設定
//==============================
function TForm1.key_coefficient: Boolean;
var
  C : Integer;
begin
  Result := True;
  Val(Rededit.Text, Rkey, C);
  if C <> 0 then begin
    application.MessageBox('赤キーの値 数値ではありません。','注意', 0);
    Result := False;
    exit;
  end;
  val(Greenedit.Text, Gkey, C);
  if C <> 0 then begin
    application.MessageBox('緑キーの値 数値ではありません。','注意', 0);
    Result := False;
    exit;
  end;
  val(Blueedit.Text, Bkey, C);
  if C <> 0 then begin
    application.MessageBox('青キーの値 数値ではありません。','注意', 0);
    Result := False;
    exit;
  end;
end;

//==========================
// キー最大値最小値表示
//==========================
procedure TForm1.MaxMin;
begin
  LabeledEdit4.Text := intTostr(Dmax);
  LabeledEdit5.Text := intTostr(Dmin);
end;


//=======================================================
// 合成
// Key = 0 の場合 背景 255の場合前景
// 値に応じて、前景の値と背景の値を比率で加算
//=======================================================
procedure TForm1.composit;
var
  PinpB     : Prgbarray;
  PbakB     : Prgbarray;
  PoutB     : Prgbarray;
  YY, XX    : Integer;
  Key, Mkey : Byte;
begin
  for YY := 0 to GHeight - 1 do begin
    PinpB := InpBitmap.ScanLine[YY];
    PbakB := BakBitmap.ScanLine[YY];
    PoutB := OutBitmap.ScanLine[YY];
    for XX := 0 to GWidth - 1 do begin
      // 合成用キーデーター
      Key  := ImageKey[YY, XX];
      MKey := MaxByte - Key;
      // Keyの値で、各色の値設定
      PoutB[XX].rgbtBlue  := (PinpB[XX].rgbtBlue  * Key + PbakB[XX].rgbtBlue  * MKey) div MaxByte;
      PoutB[XX].rgbtGreen := (PinpB[XX].rgbtGreen * Key + PbakB[XX].rgbtGreen * MKey) div MaxByte;
      PoutB[XX].rgbtRed   := (PinpB[XX].rgbtRed   * Key + PbakB[XX].rgbtRed   * MKey) div MaxByte;
    end;
  end;
  image4.Picture.Bitmap := OutBitmap;                   // 画像表示
  FileSaveBtn.Enabled := True;
end;


//========================
// 二値化キーマスクの生成
//========================
procedure TForm1.hard_mask;
var
  thresh : Smallint;
  C      : Integer;
  PinpB  : Prgbarray;
  PoutB  : Prgbarray;
  YY, XX : Integer;
  Data   : Smallint;
begin
  val(LabeledEdit1.Text, thresh, C);
  if C <> 0 then begin
    application.MessageBox('二値化キーの値 整数の数値ではありません。','注意', 0);
    exit;
  end;
  Dmin :=  255 * 3;
  DMax := -255 * 3;
  for YY := 0 to GHeight - 1 do begin
    PinpB := InpBitmap.ScanLine[YY];
    PoutB := OutBitmap.ScanLine[YY];
    for XX := 0 to GWidth - 1 do begin
      Data := round(PinpB[XX].rgbtRed * Rkey + PinpB[XX].rgbtGreen * Gkey+ PinpB[XX].rgbtBlue * Bkey);
      if Dmin > Data then Dmin := Data;
      if DMax < Data then Dmax := Data;
      if Data >= thresh then ImageKey[YY, XX] := 255
                        else ImageKey[YY, XX] := 0;
      PoutB[XX].rgbtBlue  := ImageKey[YY, XX];
      PoutB[XX].rgbtGreen := ImageKey[YY, XX];
      PoutB[XX].rgbtRed   := ImageKey[YY, XX];
    end;
  end;
  image2.Picture.Bitmap := OutBitmap;                   // 画像表示
  MaxMin;
end;

//==========================
// 二値化キーによる合成
//==========================
procedure TForm1.hard_maskBtnClick(Sender: TObject);
begin
  if not key_coefficient then exit;
  hard_mask;
  composit;
end;

//========================
// 多値化キーマスクの生成
//========================
procedure TForm1.soft_mask;
var
  threshHi  : Smallint;
  threshLow : Smallint;
  C      : Integer;
  PinpB  : Prgbarray;
  PoutB  : Prgbarray;
  YY, XX : Integer;
  Data   : Integer;
  DK     : Integer;
begin
  val(LabeledEdit2.Text, threshHi, C);
  if C <> 0 then begin
    application.MessageBox('多値化キー閾値上 整数の数値ではありません。','注意', 0);
    exit;
  end;
  val(LabeledEdit3.Text, threshLow, C);
  if C <> 0 then begin
    application.MessageBox('多値化キー閾値下 整数の数値ではありません。','注意', 0);
    exit;
  end;
  if threshHi <= threshLow then begin
    application.MessageBox('閾値の値、上と下が同じか、下が大きいです。','注意', 0);
    exit;
  end;
  Dmin :=  255 * 3;
  DMax := -255 * 3;
  for YY := 0 to GHeight - 1 do begin
    PinpB := InpBitmap.ScanLine[YY];
    PoutB := OutBitmap.ScanLine[YY];
    for XX := 0 to GWidth - 1 do begin
      // 色係数による三色の値加算
      Data := Round(PinpB[XX].rgbtRed * Rkey + PinpB[XX].rgbtGreen * GKey + PinpB[XX].rgbtBlue * Bkey);
      if Dmin > Data then Dmin := Data;
      if DMax < Data then Dmax := Data;
      DK := Round((Data - threshLow) * 255 / (threshHi - threshLow));
      if DK > 255 then DK := 255;
      if DK < 0   then DK := 0;
      ImageKey[YY, XX] := DK;
      PoutB[XX].rgbtBlue  := DK;
      PoutB[XX].rgbtGreen := DK;
      PoutB[XX].rgbtRed   := DK;
    end;
  end;
  image2.Picture.Bitmap := OutBitmap;                   // 画像表示
  MaxMin;
end;

//================================
// 多値化キー合成
//================================
procedure TForm1.Soft_maskBtnClick(Sender: TObject);
begin
  if not key_coefficient then exit;
  soft_mask;
  composit;
end;

//========================================================
// ファイルの指定オープン
// オープン画像表示 Treuで前景オープン Fasleで背景オープン
// 前景と背景の画像サイズを同じにしておく必要があります
//========================================================
procedure TForm1.FileOpen(InF : Boolean);
var
  WIC         : TWICImage;
  InFilename  : String;
begin
  OpenPictureDialog1.Filter := OpenFileFilter;                // ファイルオープンフィルターの設定
  if OpenPictureDialog1.Execute then                          // ファイルが指定されたら
    begin
      WIC := TWICImage.Create;                                // TWICImageの生成
      try
        InFilename := OpenPictureDialog1.FileName;            // ファイル名の取得
        WIC.LoadFromFile(InFilename);                         // 画像の読み込み
        // 前景画像読み込み
        if InF then begin
          GHeight := WIC.Height;                              // 画像高さ取得
          GWidth  := WIC.Width;                               // 画像幅
          InpBitmap.Width   := GWidth;                        // 画像幅
          InpBitmap.Height  := GHeight;                       // 画像高さ
          InpBitmap.Canvas.Draw(0, 0, WIC);                   // DrawでInBitmapに入力画像設定フォーマット32ビットに変換されます
          image1.Picture.Bitmap := InpBitmap;                 // 前景画像表示
          FImage := FImage or 1;                              // イメージフラグ 1bit 前景  2bit 背景
        end
        // 背景画像読み込み
        else Begin
          BHeight := WIC.Height;                              // 画像高さ取得
          BWidth  := WIC.Width;                               // 画像幅
          BakBitmap.Width   := BWidth;                        // 画像幅
          BakBitmap.Height  := BHeight;                       // 画像高さ
          BakBitmap.Canvas.Draw(0, 0, WIC);                   // DrawでInBitmapに入力画像設定フォーマット32ビットに変換されます
          image3.Picture.Bitmap := BakBitmap;                 // 背景画像表示
          FImage := FImage or 2;                              // イメージフラグ 1bit 前景  2bit 背景
        end;
      finally
        WIC.Free;                                             // TWICImage 解放
      end;
    end
    else Exit;
  // 前景画像と背景画像のサイズ確認
  if (FImage and 3 = 3)
    and (GHeight = BHeight)
    and (GWidth = BWidth) then begin
      hard_maskBtn.Enabled := True;
      Soft_maskBtn.Enabled := True;
      OutBitmap.Width   := GWidth;                            // 出力画像幅
      OutBitmap.Height  := GHeight;                           // 出力画像高さ
      Setlength(ImageKey, GHeight, GWidth);
    end
    else begin
      hard_maskBtn.Enabled := False;
      Soft_maskBtn.Enabled := False;
      if FImage and 3 = 3 then
        application.MessageBox('前景画像のサイズと背景画像のサイズが違います', '注意', 0);
    end;
end;

//==================================
// 前景画像読み込み
//==================================
procedure TForm1.FileOpenBtnClick(Sender: TObject);
begin
  FileOpen(True);
end;

//==================================
// 背景画像読み込み
//==================================
procedure TForm1.BakFileOpenBtnClick(Sender: TObject);
begin
  FileOpen(False);
end;

//===================================
// 合成画像のファイルへの保存
//===================================
procedure TForm1.FileSaveBtnClick(Sender: TObject);
var
  WIC     : TWicImage;
  WICF    : TWicImageFormat;

  Fname   : String;
  ExeStr  : String;
  FnameTop: String;
  Findex  : integer;

  function WFormatSet: Boolean;                                             // 拡張子によるファイルフォーマット設定
  begin
    Result := false;
    ExeStr := LowerCase(ExeStr);
    if ExeStr = '.jpg'  then  begin WICF := Wifjpeg; Result := True; end;
    if ExeStr = '.jpeg' then  begin WICF := Wifjpeg; Result := True; end;
    if ExeStr = '.tif'  then  begin WICF := Wiftiff; Result := True; end;
    if ExeStr = '.tiff' then  begin WICF := Wiftiff; Result := True; end;
    if ExeStr = '.png'  then  begin WICF := Wifpng;  Result := True; end;
    if ExeStr = '.gif'  then  begin WICF := Wifgif;  Result := True; end;
    if ExeStr = '.bmp'  then  begin WICF := Wifbmp;  Result := True; end;
    if ExeStr = '.wdp'  then  begin WICF := WifWMPhoto; Result := True; end;
    if ExeStr = '.hdp'  then  begin WICF := WifWMPhoto; Result := True; end;
  end;

begin
  SavePictureDialog1.Filter := SaveFileFilter;
//  SavePictureDialog1.DefaultExt := GraphicExtension(TWicImage);
  if not SavePictureDialog1.Execute then exit;
  ExeStr := ExtractFileExt(SavePictureDialog1.FileName);
  if ExeStr = '' then begin                                                 // 拡張子がなかったら
    Findex := SavePictureDialog1.FilterIndex;                               // FilterIndexによる拡張子の設定
    case Findex of
      1, 3 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.jpg');    // 拡張子の設定
         2 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.png');
         4 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.gif');
         5 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.bmp');
         6 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.tif');
         7 : Fname := ChangeFileExt(SavePictureDialog1.FileName,'.wdp');
    end;
  end
  else
    Fname := SavePictureDialog1.FileName;
  ExeStr := ExtractFileExt(Fname);                                          // 拡張子だけ取り出し
  if not WFormatSet then begin                                              // 拡張子によるファイルフォーマット設定と確認
    application.MessageBox('ファイルの拡張子が間違っています。','注意', 0);
    exit;
  end;
  FnameTop := ExtractFileName(Fname);                                       // ファイル名だけ取り出し
  if Length(FnameTop) = Length(ExeStr) then begin                           // ファイル名の長さ確認
    application.MessageBox('ファイル名がありません。','注意', 0);
    exit;
  end;

  if FileExists(Fname) then                                                 // ファイル名によるファイル検索
    if MessageDlg('既に同じ名前のファイルがあります上書きしますか ' + ExtractFileName(Fname) + '?',
                                                      mtConfirmation, [mbYes, mbNo], 0, mbNo) = IDNo then exit;

  WIC := TWicImage.Create;                                                  // TWicImage生成
  try
    WIC.Assign(OutBitmap);                                                  // TWicImageにビットマップデーター割り付け
    WIC.ImageFormat := WICF;                                                // 保存フォーマットセット
    WIC.SaveTofile(Fname);                                                  // ファイルの書き出し
  finally                                                                   // XE3,XE4の場合はアンシャープマスキングを参照してください
    WIC.Free;                                                               // TWicImage解放
  end;
end;

//============
// 初期設定
//============
procedure TForm1.FormCreate(Sender: TObject);
begin
  Top  := (Screen.Height - Height) div 2;     // 表示位置設定
  Left := (Screen.Width - Width)   div 2;
  InpBitmap     := TBitmap.Create;            // 前景画像用
  BakBitmap     := TBitmap.Create;            // 背景画像用
  OutBitmap     := TBitmap.Create;            // 出力画像用
  InpBitmap.PixelFormat   := pf24bit;         // 24ビットカラーに設定
  BakBitmap.PixelFormat   := pf24bit;         // 24ビットカラーに設定
  OutBitmap.PixelFormat   := pf24bit;         // 24ビットカラーに設定
  FImage := 0;                                // イメージフラグ 1bit 前景  2bit 背景
  FileSaveBtn.Enabled := False;               // 画像入力フラグリセット
  hard_maskBtn.Enabled := False;
  Soft_maskBtn.Enabled := False;
end;

//===============
// 終了処理
//===============
procedure TForm1.FormDestroy(Sender: TObject);
begin
  InpBitmap.Free;
  BakBitmap.Free;
  OutBitmap.Free;
end;

end.

 RGBtoHSL変換を利用して色相の値から、透過色を決める例

//==========================
// 前景画像から透過色抽出
//==========================
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  Pcolor: TAlphacolor;
  S, L  : Single;
  Spos  : Integer;
begin
  Pcolor := image1.Canvas.Pixels[X, Y];
  RGBtoHsl(Pcolor, huein, S, L);
  Spos := Round(huein * 360);
  if Spos >= 360 then Spos := 0;
  ScrollBar1.Position := Spos;
  Maxhue := huein + 0.05;
  if Maxhue >= 1 then Maxhue := Maxhue - 1;
  MinHue := huein - 0.05;
  if MinHue < 0 then MinHue := Minhue + 1;
end;



//========================
// 二値化キーマスクの生成
//========================
procedure TForm1.hard_mask;
var
  C      : Integer;
  PinpB  : Prgbarray;
  PoutB  : Prgbarray;
  YY, XX : Integer;
  DColor : Tcolor;
  Data   : Single;
  S, L   : Single;
  MaXL   : Single;
  GosaHu : Single;
begin
  if ScrollBar1.Position < 0 then begin
    application.MessageBox('透明色の指定がされていません。', '注意', 0);
    exit;
  end;
  val(LabeledEdit1.Text, MaXL, C);
  if C<>0 then begin
    application.MessageBox('閾値入力が数値ではありません', '注意', 0);
    exit;
  end;
  val(LabeledEdit4.Text, GosaHu, C);
  if C<>0 then begin
    application.MessageBox('色相誤差値が数値ではありません', '注意', 0);
    exit;
  end;
  maxhue := huein + GosaHu;
  minhue := huein - GosaHu;
  for YY := 0 to GHeight - 1 do begin
    PinpB := InpBitmap.ScanLine[YY];
    PoutB := OutBitmap.ScanLine[YY];
    for XX := 0 to GWidth - 1 do begin
      DColor := RGB(PinpB[XX].rgbtRed, PinpB[XX].rgbtGreen, PinpB[XX].rgbtBlue);
      RGBtoHSL(DColor, Data, S, L);
      if Data = 1 then Data := 0;
      if maxhue < minhue then begin
        if ((Data < maxhue) or (Data > minhue)) and (L <= MaXL) then ImageKey[YY, XX] := 0
          else ImageKey[YY, XX] := 255;
      end
      else begin
        if (Data < maxhue) and (Data > minhue)  and (L <= MaXL) then ImageKey[YY, XX] := 0
          else ImageKey[YY, XX] := 255;
      end;
      PoutB[XX].rgbtBlue  := ImageKey[YY, XX];
      PoutB[XX].rgbtGreen := ImageKey[YY, XX];
      PoutB[XX].rgbtRed   := ImageKey[YY, XX];
    end;
  end;
  image2.Picture.Bitmap := OutBitmap;                   // 画像表示
  composit;
end;

    download Digital_composit.zip

画像処理一覧へ戻る

      最初に戻る