cvCalcHistを用いたエントロピーフィルタ
最近OpenCVを始めて、ふとエントロピーフィルタを書いてみようと思い立った。
ここではROIをずらしながらcvCalcHistでヒストグラムを求めるエントロピーフィルタについて書く。
#include <math.h> #include "cv.h" #include "highgui.h" void EntropyFilter(IplImage *src, IplImage* dst, int w_size); int main(int argc, char *argv[]){ IplImage *img, *dst; img = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE); /* 画像をグレースケールで読み込む */ dst = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_8U, 1); EntropyFilter(img, dst, 3); /* エントロピーフィルタ */ cvSaveImage("result.jpg", dst, 0); /* 結果画像の保存 */ /* メモリの解放 */ cvReleaseImage(&img); cvReleaseImage(&dst); return 0; } /* エントロピーフィルタ 引数: src: 入力画像 dst: 出力先 w_size: ウィンドウサイズ */ void EntropyFilter(IplImage *src, IplImage* dst, int w_size){ int i, j, k, hist_size = 256; double e, f, e_max; float range[] = { 0, 256 }; float *ranges[] = { range }; CvHistogram *hist; hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, 0, 1); /* ヒストグラムを生成する */ f = 1.0 / (w_size*w_size); e_max = f * log(f) * w_size * w_size; /* エントロピーの最大値 */ for(i=0; i<src->height; i++){ for(j=0; j<src->width; j++){ cvSetImageROI(src, cvRect(j, i, w_size, w_size)); /* ROIをセット */ cvCalcHist(&src, hist, 0, NULL); /* ヒストグラムを計算する */ /* エントロピーの計算 */ e = 0.0; for(k=0; k<256; k++){ if(f = cvQueryHistValue_1D(hist, k)){ f /= w_size*w_size; e += f * log(f); } } dst->imageData[dst->widthStep * i + j] = e/e_max*255; /* 0〜255で正規化して格納 */ } } cvResetImageROI(src); /* ROIの解除 */ cvReleaseHist(&hist); /* ヒストグラムを解放する */ return; }