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