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

4近傍/8近傍による孤立点除去のサンプルコード(2値画像用)

画像に「4近傍/8近傍による孤立点除去」の処理をするサンプルです。ソースコードはDelphi5で作成しましたがその他の言語でも流用できるかと思います。

画像処理の結果

4近傍/8近傍による孤立点除去をすると下図のようになります。

左が元のイメージで右が処理後です。

4近傍による孤立点の除去をしていますがこのサンプル画像では少しわかりにくいです。説明しますと画面を正面として人物像の左頬辺りの髪の孤立点(白色)口の右下辺りの髪の2つの孤立点(白色)が除去されているのがわかると思います。その他にもありますので観察して見てください。

ソースコード

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

[4近傍/8近傍による孤立点除去の関数]

//-----------------------------------------------------------------------------
//■関数     EffectNoise_IsolatedPoint
//■用途     4点近傍/8点近傍による孤立点除去(2値画像用)
//■引数     hBMP   ... 転送元のビットマップのハンドル
//           Value  ... 1:4近傍 2:8近傍
//-----------------------------------------------------------------------------
function EffectNoise_IsolatedPoint(hBMP: HBitmap; Value :Byte):HBitmap;
var
  Row,Col,yRow,xCol,x,y,i,j: Integer;
  DestRow              : pRGBArray;
  SrcBitmap,DestBitmap : TBitmap;
  SourceRows           : PPBits;
  bR,bG,bB : Boolean;
  R,G,B : array [0..7] 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点近傍
    if Value = 1 then
    begin
        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;

                 bR :=False;   bG :=False;  bB :=False;
 
                 for j:= 0 to 3 do
                 begin
                   if R[j]=SourceRows[Row][Col].rgbtRed then
                   begin
                      bR :=True;
                      Break;
                   end;
                 end;

                 for j:= 0 to 3 do
                 begin
                   if G[j]=SourceRows[Row][Col].rgbtGreen then
                   begin
                     bG :=True;
                     Break;
                   end;
                 end;

                 for j:= 0 to 3 do
                 begin
                   if B[j]=SourceRows[Row][Col].rgbtBlue then
                   begin
                      bB :=True;
                      Break;
                   end;
                 end;

                 if bR then
                    DestRow[Col].rgbtRed :=SourceRows[Row][Col].rgbtRed
                 else
                  //   孤立点の埋め合わせを周囲の平均で行う
                  DestRow[Col].rgbtRed := ( R[0]+ R[1] +R[2] +R[3] ) div 4;

                 if bG then
                   DestRow[Col].rgbtGreen :=SourceRows[Row][Col].rgbtGreen
                 else
                   DestRow[Col].rgbtGreen := ( G[0]+ G[1] +G[2] +G[3]) div 4;

 
                 if bB then
                    DestRow[Col].rgbtBlue :=SourceRows[Row][Col].rgbtBlue
                 else
                   DestRow[Col].rgbtBlue := ( B[0]+ B[1] +B[2] +B[3]  )div 4;
 
            end;
        end;
    end
    else
    begin
        // 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 ((Y=0) 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;

                 bR :=False;   bG :=False;  bB :=False;
 
                 for j:= 0 to 7 do
                 begin
                   if R[j]=SourceRows[Row][Col].rgbtRed then
                   begin
                      bR :=True;
                      Break;
                   end;
                 end;
 
                 for j:= 0 to 7 do
                 begin
                   if G[j]=SourceRows[Row][Col].rgbtGreen then
                   begin
                      bG :=True;
                      Break;
                   end;
                 end;
 
                 for j:= 0 to 7 do
                 begin
                   if B[j]=SourceRows[Row][Col].rgbtBlue then
                   begin
                      bB :=True;
                      Break;
                   end;
                 end;
 
                 if bR then
                    DestRow[Col].rgbtRed :=SourceRows[Row][Col].rgbtRed
                 else
                    //  孤立点の埋め合わせを周囲の平均で行う
                    DestRow[Col].rgbtRed := ( R[0]+ R[1] +R[2] +R[3] +R[4] +R[5] + R[6] +R[7]) div 8;

                 if bG then
                    DestRow[Col].rgbtGreen :=SourceRows[Row][Col].rgbtGreen
                 else
                   DestRow[Col].rgbtGreen := ( G[0]+ G[1] +G[2] +G[3] +G[4] +G[5] + G[6] +G[7]) div 8;

 
                 if bB then
                    DestRow[Col].rgbtBlue :=SourceRows[Row][Col].rgbtBlue
                 else
                   DestRow[Col].rgbtBlue := ( B[0]+ B[1] +B[2] +B[3] +B[4] +B[5] + B[6] +B[7]) div 8;
 
            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;

[関数の呼び出し]

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





関連記事



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