OpenCV CvHistogram - eiichiromomma/CVMLAB GitHub Wiki

(OpenCV) CvHistogram

CvHistogramを使ったヒストグラムの算出

多次元ヒストグラムを想定して作られた関数のようで、普通のヒストグラムを作ろうとすると結構面倒。

cvQueryHistValue_1Dが無い

最近のバージョンではマクロが消えたので

#define cvQueryHistValue_1D( hist, idx0 ) cvGetReal1D( (hist)->bins, (idx0) )

を書いておくかcvGetReal1Dに合うように書き換える

※レンジの上限数は含まれないらしい

処理の流れ

  1. ビン(頻度を入れる箱)の数を決定
  2. レンジの決定
  3. cvCreateHistでCvHistogramを作成
  4. cvCalcHistでヒストグラムを算出
  5. cvQueryHistValue_1Dでヒストグラムを参照

ビンの数

8ビット画像(256階調)で1階調ごとのヒストグラムを求めたい場合は、 :ビン:256 :レンジ:0,256 となる。

もっとおおまかなヒストグラムにする場合は :ビン:26 :レンジ:0,256 のようにすると濃度幅が約10ごとのヒストグラムになるが、等分割されるのでハンパな間隔になってしまう。 10刻みにするには

float g_range[27];
for(int x=0; x<bins; x++){
  g_range[x]=x*10.0f;
}
g_range[bins]=255.0;
CvHistogram *h = cvCreateHist(dim,size,CV_HIST_ARRAY,range,0)

みたいな感じで0-10,10-20,...,240-250,250-255のレンジを指定してcvCreateHistの第4引数を0にする。 が、境界の値の場合どっちに含まれるかは面倒なので確かめていない。

サンプル

    #include<cv.h>
    #include<highgui.h>
    #include<stdio.h>
    void main()
    {
      //白黒
      IplImage *src = cvLoadImage("lena_std.png)",0);
      //ビン(ヒストグラムを何刻みにするか)
      int bins = 256; //256刻みのヒストグラムを作成(0~255)。16ビット画像の場合はこれとrangeを弄る
      float g_range[] = {0,256}; //0~255の範囲。16ビット画像の場合は上限を増やす
      
      //1次元のヒストグラムなので要素1つの配列
      int size[] = {bins};
      float *range[] = {g_range}; 
      IplImage *imgs[] = {src};
      
      int x=0;
      int dim=1;
      CvHistogram *h = cvCreateHist(dim,size,CV_HIST_ARRAY,range,1); //等間隔の場合
      
      cvCalcHist(imgs,h);
      
      for (x=0; x<bins; x++){
        //1次元のヒストグラムの参照はcvQueryHistValue_1Dで
        fprintf(stdout,"%d,%f\n",x,cvQueryHistValue_1D(h,x));
      }
      //片付け
      cvReleaseHist(&h);
      cvReleaseImage(&src);
    }

SIDBAのlenna

cvCalcBackProject

ヒストグラムを基に、原画像の各画素を濃度値に対応した頻度に置き換えた画像を作成。 要するに頻度の高い濃度値が明るい画素として表示される。

    #include<cv.h>
    #include<highgui.h>
    #include<stdio.h>
    void main()
    {
      //白黒
      IplImage *src = cvLoadImage("lena_std.png)",0);
      IplImage *dst = cvCloneImage(src);
      //ビン(ヒストグラムを何刻みにするか)
      int bins = 26; //26刻みのヒストグラム
      //不等間隔のrangeを作成
      float g_range[27];
      for(int x=0; x<bins; x++){
        g_range[x]=x*10.0f;
      }
      g_range[bins]=255.0;

      //1次元のヒストグラムなので要素1つの配列
      int size[] = {bins};
      float *range[] = {g_range}; 
      IplImage *imgs[] = {src};
      
      int x=0;
      int dim=1;
      float max=0;
      CvHistogram *h = cvCreateHist(dim,size,CV_HIST_ARRAY,range,0);
      
      cvCalcHist(imgs,h);
      
      for (x=0; x<bins; x++){
        //1次元のヒストグラムの参照はcvQueryHistValue_1Dで
        fprintf(stdout,"%d,%f\n",x,cvQueryHistValue_1D(h,x));
      }
      //ヒストグラムの最大値を求める
      cvGetMinMaxHistValue(h,NULL,&max,NULL,NULL);
      //最大値が255になるように総画素数*255/maxで正規化
      cvNormalizeHist(h,src->width * src->height * 255/max);
      //BackProject画像を作成
      cvCalcBackProject(imgs,dst,h);
      cvNamedWindow("src",1);
      cvNamedWindow("dst",1);
      cvShowImage("src",src);
      cvShowImage("dst",dst);
      cvWaitKey(0);
      //片付け
      cvReleaseHist(&h);
      cvReleaseImage(&src);
    }

バックプロジェクション(26ビン)

バックプロジェクション(256ビン)

⚠️ **GitHub.com Fallback** ⚠️