ホーム > カテゴリ > 画像処理工学 >

エッジ検出(Laplacian ラプラシアン8近傍)のサンプルコード(画像フィルタ)

画像に「エッジ検出(Laplacian ラプラシアン8近傍)」の処理をするサンプルです。ソースコードはDelphi5で作成しましたがその他の言語でも流用できるかと思います。

画像処理の結果

エッジ検出(Laplacian ラプラシアン8近傍)をすると下図のようになります。

画像フィルターのマスク

このフィルターのマスクは下図になります。

ソースコード

[EffectBass.pas - 汎用モジュール]

//Bass Unit
unit EffectBass;

interface
uses
 Windows,SysUtils, Classes, Graphics;

type
 //24bitアクセス用ポインタ
 pRGBarray  = ^TRGBarray;
 TRGBarray  = array[0..0] of TRGBTriple; //None リテラル

type
 //24bitアクセス用ダブルポインタ
 PPBits = ^TPBits;
 TPBits = array[0..0] of pRGBarray; //None リテラル

//汎用プロシージャ
procedure Set24bit(Src,Dest :TBitmap);
function  Set255(Value : integer) : BYTE;

implementation


/////////
procedure Set24bit(Src,Dest :Tbitmap);
begin
  Src.PixelFormat :=pf24bit;
  Dest.PixelFormat:=pf24bit;
  Dest.Width:=Src.Width;
  Dest.Height:=Src.Height;
end;

/////////
function Set255(Value:Integer):Byte;
begin
 if Value>=255 then
  Result:=255
 else if Value<=0 then
 Result:=0
 else Result:=Value;
end;
end.

[エッジ検出(Laplacian ラプラシアン8近傍)の関数 - 汎用カスタムフィルタ]

//-----------------------------------------------------------------------------
//■関数     EffectCustom
//■用途     カスタムフィルタ
//■引数     hBMP             ...転送元のビットマップのハンドル
//           MaskBits         ...マスクビット(必ず25つの配列を作成する)
//                               値は「-255」~「255」まで
//           Divisor          ...除数(1-255)
//           Addition         ...加算(0-255)
//■戻り値
//            新しいビットマップのハンドル
//-----------------------------------------------------------------------------

function EffectCustom
    (hBMP:HBitmap;MaskBits:array of Smallint;Divisor,Addition:Byte):HBitmap;
var
  SrcBitmap,DestBitmap : TBitmap;
  DestRow    : pRGBArray;
  SourceRows : PPBits;
  _Height,_Width  : Integer;
  Row,Col,yRow,xCol,r,g,b,x,y,iMask: Integer;
begin

  SrcBitmap   :=TBitmap.Create;
  DestBitmap  :=TBitmap.Create;

  SrcBitmap.Handle  :=hBMP;
  Set24bit(SrcBitmap,DestBitmap);

  // 少しでも高速化の為、先にサイズを取得
  _Height := SrcBitmap.height-1;
  _Width  := SrcBitmap.width-1;

  GetMem(SourceRows, SrcBitmap.Height * SizeOf(pRGBArray));
  try
    for Row:= 0 to SrcBitmap.Height - 1 do  SourceRows[Row]:=SrcBitmap.Scanline[Row];

    for Row := 0 To _Height do
    begin

      DestRow:=DestBitmap.ScanLine[Row];

      for Col := 0 To _Width do
      begin

        R:=0; G:=0; B:=0; iMask:=0;

        // 5x5
        for y:= -2 to 2 do
        begin
          for x:= -2 to 2 do
          begin

            //Y軸
            if Row+(y) > _Height then yRow:= _Height
            else if Row+(y) <  0 then yRow:= 0
            else                      yRow:= Row+(y);

            //X軸
            if Col+(x) > _Width then  xCol:= _Width
            else if Col+(x) < 0 then  xCol:= 0
            else                      xCol:= Col+(x);

            R := R + (SourceRows[yRow][xCol].rgbtRed   * MaskBits[iMask]);
            G := G + (SourceRows[yRow][xCol].rgbtGreen * MaskBits[iMask]);
            B := B + (SourceRows[yRow][xCol].rgbtBlue  * MaskBits[iMask]);
            inc(iMask);
          end;
        end;

        DestRow[Col].rgbtRed   :=Set255((R div Divisor)+ Addition);
        DestRow[Col].rgbtGreen :=Set255((G div Divisor)+ Addition);
        DestRow[Col].rgbtBlue  :=Set255((B div Divisor)+ Addition);
      end;
    end;

    FreeMem(SourceRows); SourceRows:=nil;
    Result :=DestBitmap.ReleaseHandle;

  except
     if Assigned(SourceRows) then FreeMem(SourceRows);
     Result :=SrcBitmap.ReleaseHandle;
  end;
  SrcBitmap.Free;
  DestBitmap.Free;
end;

[関数の呼び出し]

procedure TForm1.Button1Click(Sender: TObject);
var
 MaskBits : array [0..24] of SmallInt;
 Divisor,Addition,i:integer;
begin

  // 初期化
  for i:= 0 to 24 do  MaskBits[i]:=0;
  Divisor := 1; Addition := 0;

  // エッジ検出(Laplacian ラプラシアン8近傍)
  MaskBits[6]  := -1;   MaskBits[7]  := -1;  MaskBits[8]   := -1 ;
  MaskBits[11] := -1;   MaskBits[12] :=  8;  MaskBits[13]  := -1 ;
  MaskBits[16] := -1;   MaskBits[17] := -1;  MaskBits[18]  := -1 ;

  Image1.Picture.Bitmap.Handle :=
    EffectCustom(Image1.Picture.Bitmap.ReleaseHandle,
                 MaskBits,
                 Divisor,
                 Addition);
end;

演算処理について

重い演算処理を行う為、インラインアセンブラで記述した方が高速です。またマスクは「5x5」ではなく「3x3」にすれば演算処理が軽減されます。(Scanlineでポインターを使用していますので重いのはMaskBits、Divisor、Additionの部分です)

このフィルターをテストできるソフトウェア

このフィルター処理をテストできる無料ソフトウェアをご紹介します。

<操作方法>
1.下記からダウンロードして実行します。
2.画像ファイルを適宜読み込みます。
3.メニューの[イメージ]から[カスタムフィルタ]を選択します。
4.そのカスタムフィルタ画面で[テンプレート]を任意に選択する。
5.OKボタンを押せばフィルターの実行となります。

疾風-tokikaze- v1.60
http://papy.world.coocan.jp/o1.html
高校や大学などの画像処理関連の授業で使用されていた事もあるようです。





関連記事



公開日:2015年02月21日 最終更新日:2016年06月29日
記事NO:00266