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

ノーマライズ(ヒストグラムの引き伸ばし)のサンプルコード

画像に「ノーマライズ(ヒストグラムの引き伸ばし)」の処理をするサンプルです。ソースコードは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.

[ノーマライズ(ヒストグラムの引き伸ばし)の関数]

//-----------------------------------------------------------------------------
//■関数     EffectHistogramNormalize
//■用途     ノーマライズ(ヒストグラムの引き伸ばし)
//■引数     hBMP             ...転送元のビットマップのハンドル
//■戻り値
//            新しいビットマップのハンドル
//-----------------------------------------------------------------------------
function  EffectHistogramNormalize(hBMP:HBitmap):HBitmap;
var
  Row,Col        : Integer;
  DestRow,SrcRow : pRGBArray;
  SrcBitmap,DestBitmap:TBitmap  ;
  aMin,aMax : TRGBTriple;
  R_ratio,G_ratio,B_ratio :Single;
begin

//------------------------------------------------------------------------------
//
//                           ――線形濃度変換――
//
//  原画像のヒストグラムにおける濃度の最小値をmin、最大値をmaxとしたとき、
//  次の式により変換する。
//
//                 (新しい濃度値)=255/max-min*(現画像の濃度値)
//------------------------------------------------------------------------------

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

  FillChar(aMin,Sizeof(TRGBTriple),255);
  FillChar(aMax,Sizeof(TRGBTriple),0);

  try


    for Row := 0 to SrcBitmap.Height - 1 do
    begin
      SrcRow  := SrcBitmap.Scanline[Row];
      for Col := 0 to SrcBitmap.Width - 1 do
      begin
          //  最小値の入れ替え
          if (SrcRow[Col].rgbtRed   < aMin.rgbtRed)   then aMin.rgbtRed     :=SrcRow[Col].rgbtRed;
          if (SrcRow[Col].rgbtGreen < aMin.rgbtGreen) then aMin.rgbtGreen   :=SrcRow[Col].rgbtGreen;
          if (SrcRow[Col].rgbtBlue  < aMin.rgbtBlue)  then aMin.rgbtBlue    :=SrcRow[Col].rgbtBlue;

          // 最大値の入れ替え
          if (SrcRow[Col].rgbtRed   > aMax.rgbtRed)   then  aMax.rgbtRed     :=SrcRow[Col].rgbtRed;
          if (SrcRow[Col].rgbtGreen > aMax.rgbtGreen) then  aMax.rgbtGreen   :=SrcRow[Col].rgbtGreen;
          if (SrcRow[Col].rgbtBlue  > aMax.rgbtBlue)  then  aMax.rgbtBlue    :=SrcRow[Col].rgbtBlue;
      end;
    end;

    R_ratio :=  255 / (aMax.rgbtRed   - aMin.rgbtRed);
    G_ratio :=  255 / (aMax.rgbtGreen - aMin.rgbtGreen);
    B_ratio :=  255 / (aMax.rgbtBlue  - aMin.rgbtBlue);

    for Row := 0 to SrcBitmap.Height - 1 do
    begin
      SrcRow  := SrcBitmap.Scanline[Row];
      DestRow := DestBitmap.Scanline[Row];
      for Col := 0 to SrcBitmap.Width - 1 do
      begin
         // maxはMath.pasにあるのでuses節にMathを追加する
         DestRow[Col].rgbtRed   := Set255( Round(R_ratio * max( (SrcRow[Col].rgbtRed   - aMin.rgbtRed  ),0)) );
         DestRow[Col].rgbtGreen := Set255( Round(G_ratio * max( (SrcRow[Col].rgbtGreen - aMin.rgbtGreen),0)) );
         DestRow[Col].rgbtBlue  := Set255( Round(B_ratio * max( (SrcRow[Col].rgbtBlue  - aMin.rgbtBlue ),0)) );
      end;   
    end;
        
  Result :=DestBitmap.ReleaseHandle;

  except
     Result :=SrcBitmap.ReleaseHandle;
  end;
  
  SrcBitmap.Free ;
  DestBitmap.Free;
end;

[関数の呼び出し]

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





関連記事



公開日:2015年02月24日
記事NO:00280