TOP > カテゴリ > 画像処理工学 >

収縮と膨張によるノイズ除去のサンプルコード(2値画像用)

画像に「収縮と膨張によるノイズ除去」の処理をするサンプルです。ソースコードはDelphi5で作成しましたがその他の言語でも流用できるかと思います。

画像処理の結果

収縮と膨張によるノイズ除去をすると下図のようになります。

ソースコード

[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.

[収縮と膨張によるノイズ除去の関数]

//-----------------------------------------------------------------------------
//■関数     EffectContraction
//■用途     収縮
//■引数     hBMP  ...転送元のビットマップのハンドル
//-----------------------------------------------------------------------------
function EffectContraction(hBMP: HBitmap):HBitmap;
var
  Row,Col,yRow,xCol,x,y,i,j: Integer;
  DestRow              : pRGBArray;
  SrcBitmap,DestBitmap : TBitmap;
  SourceRows           : PPBits;
  bRGB :Boolean;
  R,G,B : array [0..3] of Byte;
begin

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

  GetMem(SourceRows, SrcBitmap.Height * SizeOf(pRGBArray));
  
  try

    for Row:= 0 to SrcBitmap.Height - 1 do  SourceRows[Row] := SrcBitmap.Scanline[Row];

    // 8点近傍
    for Row := 0 To SrcBitmap.Height-1 do
    begin

         DestRow := DestBitmap.ScanLine[Row];
         for Col := 0 To SrcBitmap.Width-1 do
         begin
             //-------------
             // 0 - 1 - 2
             //-------------
             // 3 -   - 4
             //-------------
             // 5 - 6 - 7

             i:=0;

             for y:= -1 to 1 do
             begin
               for x:= -1 to 1 do
               begin
                 if not ( ((y=-1) and (x= 0)) or
                          ((y= 0) and (x=-1)) or
                          ((y= 0) and (x= 1)) or
                          ((y= 1) and (x= 0))  )   then
                  continue;
 
                  // Y軸
                  if  (Row+ y ) > SrcBitmap.Height-1 then yRow:=SrcBitmap.Height-1
                  else if Row+(y)< 0                 then yRow:=0
                  else                                    yRow:=Row+(y);
 
                  // X軸
                  if      Col+(x)> SrcBitmap.Width-1 then xCol:=SrcBitmap.Width-1
                  else if Col+(x)< 0                 then xCol:=0
                  else                                    xCol:=Col+(x);
 
                  B[i]:=SourceRows[yRow][xCol].rgbtBlue;
                  G[i]:=SourceRows[yRow][xCol].rgbtGreen;
                  R[i]:=SourceRows[yRow][xCol].rgbtRed;
 
                  inc(i);
               end;
             end;

             bRGB := False;
             for j:= 0 to 3 do
             begin
               if R[j] =255 then
               begin
                bRGB :=True;
                Break;
               end;
             end;

             if bRGB then
             begin
               DestRow[Col].rgbtRed   := 255;
               DestRow[Col].rgbtGreen := 255;
               DestRow[Col].rgbtBlue  := 255;
             end
             else
             begin
               DestRow[Col].rgbtRed   := SourceRows[Row][Col].rgbtRed;
               DestRow[Col].rgbtGreen := SourceRows[Row][Col].rgbtGreen;
               DestRow[Col].rgbtBlue  := SourceRows[Row][Col].rgbtBlue;
             end;
        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;

//-----------------------------------------------------------------------------
//■関数     EffectExpansion
//■用途     膨張
//■引数     hBMP  ...転送元のビットマップのハンドル
//-----------------------------------------------------------------------------
function EffectExpansion(hBMP: HBitmap):HBitmap;
var
  Row,Col,yRow,xCol,x,y,i,j: Integer;
  DestRow              : pRGBArray;
  SrcBitmap,DestBitmap : TBitmap;
  SourceRows           : PPBits;
  bRGB :Boolean;
  R,G,B : array [0..3] of Byte;
begin

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

  GetMem(SourceRows, SrcBitmap.Height * SizeOf(pRGBArray));
  try

    for Row:= 0 to SrcBitmap.Height - 1 do  SourceRows[Row] := SrcBitmap.Scanline[Row];
   
    // 4点近傍
    for Row := 0 To SrcBitmap.Height-1   do
    begin

        DestRow:=DestBitmap.ScanLine[Row];
        for Col := 0 To SrcBitmap.Width-1 do
        begin
            //-------------
            // 0 - 1 - 2
            //-------------
            // 3 -   - 4
            //-------------
            // 5 - 6 - 7

            i:=0;

            for y:= -1 to 1 do
            begin
              for x:= -1 to 1 do
              begin
                if not ( ((y=-1) and (x= 0)) or
                         ((y= 0) and (x=-1)) or
                         ((y= 0) and (x= 1)) or
                         ((y= 1) and (x= 0))  )   then
                 continue;

                 // Y軸
                 if  (Row+ y ) > SrcBitmap.Height-1 then  yRow:=SrcBitmap.Height-1
                 else if Row+(y)< 0                 then  yRow:=0
                 else                                     yRow:=Row+(y);

                 // X軸
                 if      Col+(x)> SrcBitmap.Width-1 then  xCol:=SrcBitmap.Width-1
                 else if Col+(x)< 0                 then  xCol:=0
                 else                                     xCol:=Col+(x);

                 B[i] := SourceRows[yRow][xCol].rgbtBlue;
                 G[i] := SourceRows[yRow][xCol].rgbtGreen;
                 R[i] := SourceRows[yRow][xCol].rgbtRed;

                 inc(i);
              end;
            end;

            bRGB := False;
            for j:= 0 to 3 do
            begin
              if R[j] =0 then
              begin
                bRGB :=True;
                Break;
              end;
            end;

            if bRGB then
            begin
               DestRow[Col].rgbtRed   := 0;
               DestRow[Col].rgbtGreen := 0;
               DestRow[Col].rgbtBlue  := 0;
            end
            else
            begin
               DestRow[Col].rgbtRed   := SourceRows[Row][Col].rgbtRed;
               DestRow[Col].rgbtGreen := SourceRows[Row][Col].rgbtGreen;
               DestRow[Col].rgbtBlue  := SourceRows[Row][Col].rgbtBlue;
            end;
        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;

//-----------------------------------------------------------------------------
//■関数     EffectNoise_ExCon
//■用途     収縮と膨張によるノイズ除去(2値画像用)
//■引数     hBMP  ...転送元のビットマップのハンドル
//-----------------------------------------------------------------------------
function EffectNoise_ExCon(hBMP :HBitmap):HBitmap;
Var
 aBMP : HBitmap;
begin
    // 4近傍による収縮
    aBMP   := EffectContraction(hBMP);
    // 4近傍による膨張
    Result := EffectExpansion(aBMP) ;
end;

[関数の呼び出し]

procedure TForm1.Button1Click(Sender: TObject);
begin
  Image1.Picture.Bitmap.Handle :=
    EffectNoise_ExCon(Image1.Picture.Bitmap.ReleaseHandle);
end;





関連記事



公開日:2015年02月25日
記事NO:00303