エッジ検出(Sobel ゾーベル水平)のサンプルコード(画像フィルター)
画像に「エッジ検出(Sobel ゾーベル水平)」の処理をするサンプルです。ソースコードはDelphi5で作成しましたがその他の言語でも流用できるかと思います。
画像処理の結果
エッジ検出(Sobel ゾーベル水平)をすると下図のようになります。
画像フィルターのマスク
このフィルターのマスクは下図になります。
ソースコード
[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.
[エッジ検出(Sobel ゾーベル水平)の関数 - 汎用カスタムフィルタ]
//----------------------------------------------------------------------------- //■関数 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; // エッジ検出(Sobel ゾーベル水平) MaskBits[6] := -1 ; MaskBits[7] := 0; MaskBits[8] := 1 ; MaskBits[11] := -2 ; MaskBits[12] := 0; MaskBits[13] := 2 ; MaskBits[16] := -1 ; MaskBits[17] := 0; 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
高校や大学などの画像処理関連の授業で使用されていた事もあるようです。