Visual Basic でOpenCV⑩ - ヒストグラム

Visual BasicOpenCVを使ったプログラムを紹介します。Visual BasicOpenCVで紹介したクラスを使用し、ヒストグラムの表示を行います。

ヒストグラムの表示

画像のヒストグラムを表示するプログラムを紹介します。Visual BasicOpenCVと異なるのは派生クラスのCCvFunc.vb のみですので、そのソースリストの一部を示します。

        : 
        Public Function DoCvFunction() As Bitmap
            If mSrc Is Nothing Then Return Nothing

            'CalcHist
            mDst = New Mat(400, 256 * 2, MatType.CV_8UC3, Scalar.White)
            Dim hist = New Mat(2) {}
            Dim color = New Scalar() {Scalar.Blue, Scalar.Green, Scalar.Red}
            Dim _hdims = {256}
            Dim _ranges As Rangef() = {New Rangef(0, 256)}
            For ch = 0 To hist.Length - 1
                hist(ch) = New Mat()
                Cv2.CalcHist(New Mat() {mSrc}, New Integer() {ch},
                                            Nothing, hist(ch), 1, _hdims, _ranges)
                Cv2.Normalize(hist(ch), hist(ch), 0, mDst.Height, NormTypes.MinMax)
                DrawHist(mDst, hist(ch), color(ch))
            Next
            Return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mDst)
        End Function

        ' draw
        Private Sub DrawHist(histMat As Mat, hist As Mat, color As Scalar)
            Dim LLPoint As New List(Of List(Of Point))()
            Dim LPoint As New List(Of Point)()

            For i = 0 To 255
                Dim v As Single = hist.Get(Of Single)(i, 0)
                Dim _bin = histMat.Width / 256
                LPoint.Add(New Point(i * _bin, histMat.Height - v - 1))
            Next
            LLPoint.Add(LPoint)
            mDst.Polylines(LLPoint, False, color)
        End Sub
        : 

ヒストグラムをMat オブジェクトmDst に描くため、背景が白のMatオブジェクトを生成します。ヒストグラムを0 ~ 255 の配列で保持するため、mDst の横幅は256 の整数倍とします。ここでは256*2 で512 を指定します。mDst の高さについては正規化しますので任意の値で構いません。
B、G、R それぞれについてヒストグラムを描くため、ヒストグラム値を保持するhist や、ヒストグラムを描く線の色を保持するcolor は要素数が3 の配列です。B、G、R それぞれをCv2.CalcHist メソッドで計算します。得られたヒストグラムは32 ビットの浮動小数点の1次元(サイズ=256)のMat オブジェクトです。これを、折れ線で描画しますが、そのままでは使えないため、hist をCv2.Normalize メソッドで画像の高さへ正規化します。そして、DrawHist メソッドを呼び出し、対応する色でヒストグラムを描きます。これをB、G、R ごとに行い、最後にBitmapオブジェクトへ変換します。
DrawHist メソッドは、ヒストグラムを描くMat オブジェクトhistMat と、ヒストグラム値が格納されているMat オブジェクトhist、そして線の色を表すcolor を受け取ります。ヒストグラムをMat.Polylines メソッドで描きます。頂点の座標をList(Of Point) オブジェクトLPoint へ格納します。座標のx 軸は、ヒストグラムを描く画像の横幅を256 で除算し、その結果を乗算します。y 軸は値を上下逆にする必要があるため、ヒストグラムを描く画像の高さから引数で渡された値を減算します。この座標をAdd メソッドでLPoint へ追加します。すべての処理が完了したら、このLPoint をList(Of List(Of Point)) オブジェクトであるLLPoint へAdd メソッドで追加します。最後にMat オブジェクトmDst のPolylines メソッドで、B、G、R それぞれのヒストグラムを描きます。

実行

以降に、実行例を示します。

画像を変更したものも示します。