OpenCV CvHistogram - eiichiromomma/CVMLAB GitHub Wiki
(OpenCV) CvHistogram
CvHistogramを使ったヒストグラムの算出
多次元ヒストグラムを想定して作られた関数のようで、普通のヒストグラムを作ろうとすると結構面倒。
最近のバージョンではマクロが消えたので
#define cvQueryHistValue_1D( hist, idx0 ) cvGetReal1D( (hist)->bins, (idx0) )
を書いておくかcvGetReal1Dに合うように書き換える
※レンジの上限数は含まれないらしい
- ビン(頻度を入れる箱)の数を決定
- レンジの決定
- cvCreateHistでCvHistogramを作成
- cvCalcHistでヒストグラムを算出
- 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
ヒストグラムを基に、原画像の各画素を濃度値に対応した頻度に置き換えた画像を作成。 要するに頻度の高い濃度値が明るい画素として表示される。
#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ビン)