cvAvgを用いた標本分散フィルタ

指定したサイズのROIをずらしながら、ROI内の画素の標本分散を出力するフィルタを書いた。

#include <math.h>
#include "cv.h"
#include "highgui.h"

void VarianceFilter(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);

  VarianceFilter(img, dst, 3); /* 標本分散フィルタ */

  cvSaveImage("result.jpg", dst, 0); /* 結果画像の保存 */

  /* メモリの解放 */
  cvReleaseImage(&img);
  cvReleaseImage(&dst);

  return 0;
}

/*
  標本平均フィルタ
  引数:
    src: 入力画像
    dst: 出力先
    w_size: ウィンドウサイズ
 */
void VarianceFilter(IplImage *src, IplImage* dst, int w_size){
  int i, j, wi, wj;
  double avg, e;
  uchar f;

  for(i=0; i<src->height; i++){
    for(j=0; j<src->width; j++){
      cvSetImageROI(src, cvRect(j, i, w_size, w_size)); /* ROIをセット */
      avg = cvAvg(src, NULL).val[0]; /* ROI内の画素の標本平均 */

      /* 標本分散の計算 */
      e = 0.0;
      for(wi=i; wi<i+w_size; wi++){
        for(wj=j; wj<j+w_size; wj++){
          f = CV_IMAGE_ELEM(src, uchar, wi, wj);
          e += pow(avg-f, 2);
        }
      }
      e /= w_size * w_size;

      dst->imageData[dst->widthStep * i + j] = e; /* 出力 */
    }
  }

  cvResetImageROI(src); /* ROIの解除 */

  return;
}

入力画像

結果