画像からカラーヒストグラムを作成する ~Delphiでお手軽プログラミング
1ピクセルは8bit(0~255)×3(RGB)の24ビットで表現されますが、2Bit(0~3)×3(RGB)の6Bit(0~63)に変換し、
そのピクセル値(0~63)の頻度(割合)をカラーヒストグラムと呼ぶそうです
プロジェクトの作成と画面設計
プロジェクトを新規作成(VCLアプリケーション)し、フォーム(Form1)にTImageを1個、TChartを1個、TButtonを1個配置する。Image1の「Picture」プロパティにカラーヒストグラムを作成したい画像を読み込みます。
「ファイル」⇒「すべて保存」から任意にフォルダを作成してユニット「Unit1.pas」とプロジェクト「Project1.dproj」を保存します。
新しいユニットの作成とソースコードの記述
「ファイル」⇒「新規作成」⇒「ユニット -Delphi」をクリックし、以下ソースコードを記述して「UColorHistogram.pas」として保存する。unit UColorHistogram; interface uses Vcl.Graphics; type //カラーヒストグラムの型 TMamHistData=array[0..63] of Integer; //参考URL https://yuzurus.hatenablog.jp/entry/search-image //カラーヒストグラム作成関数 function GetHistogram(bmp:TBitmap):TMamHistData; implementation //カラーヒストグラム作成関数 function GetHistogram(bmp: TBitmap): TMamHistData; type TRGB =record B,G,R:byte; end; TRGBArr=array[0..32767] of TRGB; PRGBArr=^TRGBArr; var fbmp:TBitmap; x,y:Integer; rgb:PRGBArr; i: Integer; no:Integer; pxnum:Integer; begin //戻り値を初期化 for i := Low(Result) to High(Result) do Result[i]:=0; if not Assigned(bmp) then exit; fbmp:=TBitmap.Create; try fbmp.Assign(bmp); fbmp.PixelFormat:=pf24bit; for y := 0 to fbmp.Height-1 do begin rgb:=fbmp.ScanLine[y]; for x := 0 to fbmp.Width-1 do begin //RGBは8bit(0~255)×3だが、2Bit(0~3)×3の6Bit(0~63)に変換する no:=16*Trunc(rgb[x].R/64)+4*Trunc(rgb[x].G/64)+Trunc(rgb[x].B/64); inc(result[no]); end; end; finally fbmp.Free; end; //正規化(0~255)を行う pxnum:=fbmp.Width*fbmp.Height; for i := Low(Result) to High(Result) do Result[i]:=Trunc(255*Result[i]/pxnum); end; end.
ソースコードの記述
キーボードから「Shift+F12}を押して、「Form1(Unit1.pas)」を選択して「OK」ボタンを押します。 TButton1をダブルクリックして、以下ソースコードを記述する。unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, //TeeChart関連ユニット」 VclTee.TeeGDIPlus, VCLTee.TeEngine, VCLTee.TeeProcs, VCLTee.Chart,VclTee.Series, //グラフィックス関連ユニット Vcl.Imaging.jpeg,Vcl.Imaging.pngimage, //カラーヒストグラムのユニット UColorHistogram; type TForm1 = class(TForm) Image1: TImage; Button1: TButton; Chart1: TChart; procedure Button1Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var bmp:TBitmap; hist:TMamHistData; BarSeries:TBarSeries; i:Integer; begin if not Assigned(Image1.Picture.Graphic) then exit; bmp:=TBitmap.Create; try bmp.Assign(Image1.Picture.Graphic); //カラーヒストグラムを取得 hist:=GetHistogram(bmp); finally bmp.Free; end; //既存グラフの削除 while Chart1.SeriesCount>0 do Chart1.RemoveSeries(0); //タイトル設定 Chart1.Title.Text.Text:='カラーヒストグラム'; Chart1.LeftAxis.Minimum:=0; Chart1.Legend.Visible:=False; //棒グラフの追加 BarSeries:=TBarSeries.Create(Chart1); Chart1.AddSeries(BarSeries); Chart1.Series[0].Marks.Visible:=False; //棒グラフにカラーヒストグラムの棒を64個追加 for i := Low(hist) to High(hist) do Chart1.Series[0].AddXY(i,hist[i]); end; end.
実行する
実行ボタンを押して実行します。(デバッグ実行でもOK)Button1をクリックすると、カラーヒストグラムが作成されます。