openCVでDCTとIDCT

概要


openCVを使ってDCT変換と逆DCT変換するサンプルソースです。 cvDCTを使用した場合、画像中心に高周波成分が表示され、周辺に向かうにつれて低周波成分になっていきます。 したがって、下図に示すフィルタはどちらも低周波成分を通し高周波成分をカットするローパスフィルタとして 機能します。左側のフィルタは理想的なLPF、右側のフィルタはガウシアンフィルタになります。

  

下図に理想LPFとガウシアンフィルタを使用したそれぞれの場合の結果を示します。理想LPFを使用した場合 周波数ドメインの関数に不連続な部分ができてしまうため、変換後の画像にリンギングが生じています。 それに対してガウシアンフィルタを使用した場合には、フィルタ関数が連続関数で記述可能なため、リンギングは生じていません。(ガウシアンの係数によっては生じる場合もある)

  

source code


#include 
#include 
#include 
#include 

#define PIXVAL(iplimagep, x, y) (*(uchar *)((iplimagep)->imageData + (y) * (iplimagep)->widthStep + (x)))

int main(int argc, char ** argv)
{
	IplImage *invImage;
	CvMat *dct,*idct;
	
	IplImage *image = cvLoadImage("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	IplImage *mask = cvLoadImage("mask1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	invImage = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1);

	dct = cvCreateMat(image->height, image->width, CV_64FC1);
	idct = cvCreateMat(image->height, image->width, CV_64FC1);
	
	// DCT
	int x, y;
	for(y=0; yheight; y++){
		for(x=0; xwidth; x++){
			cvmSet(dct,
				   y,
				   x,
				   (double)(unsigned char)(image->imageData[image->widthStep
															* y + x]));
		}
	}
	
	cvDCT( dct, dct, CV_DXT_FORWARD);
	
	// マスク値をDCT結果に乗算
	for(int x = 0; x < dct->width; ++x){
		for(int y = 0; y < dct->height; ++y){
			double scale = PIXVAL(mask, x, y) / 255.0;
			double value = cvmGet(dct, y, x) * scale;
			cvmSet(dct, y, x, value);
		}
	}
	
	// 逆変換
	cvDCT( dct, idct, CV_DXT_INVERSE);
	for(y=0; yheight; y++){
		for(x=0; xwidth; x++){
			invImage->imageData[invImage->widthStep * y + x] = cvmGet(idct,y,x);
		}
	}

	cvWaitKey(0);
	return 0;
}

参考URL


http://d.hatena.ne.jp/momo_dev/20071120/p1

iPhoneアプリWorkshop

Copyright (C) Kazuma Kitamura All right reserved.