画像からカラーヒストグラムを作成する ~Delphiでお手軽プログラミング

画像からカラーヒストグラムを作成する ~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をクリックすると、カラーヒストグラムが作成されます。
カラーヒストグラム