C++のDCTプログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kehos12
記事: 11
登録日時: 10年前

C++のDCTプログラムについて

#1

投稿記事 by kehos12 » 9年前

C++でDCTを行うプログラムを以下の2つのように作成しました。
①cvLine等で描写した図をDCTする。
②画像を読み込みDCTする。
処理の部分はまったく変更せず、ソース画像を変えただけなのですが二つの結果が違う結果となります。
また①のほうが正しく出力されています。
これはどうしてなのでしょうか?
どなたかご指摘いただきたいです。
以下ソースとなります、よろしくお願いしますm(__)m

コード:

#include "opencv/cv.h"
#include "opencv/cxcore.h"
#include "opencv/highgui.h"


#define PI 3.1415926
//////////////////////////////////////////////////////////////////////////////
///DCT////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

void DCT(IplImage *src=0,IplImage*image=0,IplImage*dctImage=0){
	
	int x,y;
	cvCvtColor(src,image,CV_BGR2GRAY);

	double CosTable[8][8]	= {0.0};
	double SqrtValue = 1.0/sqrt(2.0);
	double Cu, Cv = 0.0;
	double DCTValue = 0.0;
	CvMat*DCTImage=0;
	DCTImage = cvCreateMat(image->height, image->width, CV_64FC1);

  int a, b, i, j, u, v;

	//make cosTable
	for(i = 0; i < 8; i++){
		for(j = 0; j < 8; j++){
			CosTable[i][j] = cos(PI * (2.0 * (double)j + 1.0)* (double)i / 16.0);
		}
	}
	//DCT
	for(a = 0; a < image->height; a += 8){
		for(b = 0; b < image->width; b += 8){

			for(u = 0; u < 8; u++){

				if(u == 0){
					Cu = SqrtValue;
				}
				else{
					Cu = 1.0;
				}

				for(v = 0; v < 8; v++){

					DCTValue = 0.0;

					if(v == 0){
						Cv = SqrtValue;
					}
					else{
						Cv = 1.0;
					}

					for(i = 0; i < 8; i++){
						for(j = 0; j < 8; j++){
							DCTValue += image->imageData[ image->widthStep*(a + i)+ b + j]* CosTable[u][i] * CosTable[v][j];							
						}
					}
					cvmSet(DCTImage,a+u,b+v,Cu*Cv*DCTValue);
				}
			}
		}
	}

   for(y=0; y<dctImage->height; y++){
    for(x=0; x<dctImage->width; x++){
      dctImage->imageData[dctImage->widthStep * y + x] =(unsigned char)cvmGet(DCTImage,y,x);
	}
   }
}
 
///////////////////////////////////////////////////////////////////////////////////////////
////////////main////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv){
	
	////Size
	int width = 640;
	int height = 480;

	////IplImage
	IplImage*dct=0,*gray=0;
	IplImage*src=0;
    int key;    
    int n = 0;  

    ////make IplImage 
	src=cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
	gray=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
	dct=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    ////make window name
    cvNamedWindow("Line Sample", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("DCT", CV_WINDOW_AUTOSIZE);
	////Drow Line
		cvSetZero(src);
        cvLine(src, cvPoint(0, height/2), cvPoint(width,height/2), cvScalar(255, 0, 0), 1, 8, 0);
		//cvLine(src, cvPoint(0,2), cvPoint(WIDTH-2, HEIGHT), cvScalar(255, 0, 0), 1, 8, 0);
		//cvLine(src, cvPoint(2, 0), cvPoint(WIDTH, HEIGHT-2), cvScalar(255, 0, 0), 1, 8, 0);
	////DCT
		IplImage*tmp=cvCloneImage(src);
		DCT(tmp,gray,dct);
	////Save Images
		//cvSaveImage("test.jpg",src);
		//cvSaveImage("test_DCT.jpg",dct);
    
	//maek window roop
    while(true){
        cvShowImage("Line Sample", src);
		cvShowImage("DCT", dct);

        //key
        key = cvWaitKey(10);

        //End@ESC_key
        if(key==0x1b)
            break;
        
   }

    //Release
    cvDestroyWindow("Line Sample");
	cvDestroyWindow("DCT");

    return 0;
}

コード:

#include "opencv/cv.h"
#include "opencv/cxcore.h"
#include "opencv/highgui.h"


#define PI 3.1415926
//////////////////////////////////////////////////////////////////////////////
///DCT////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

void DCT(IplImage *src=0,IplImage*image=0,IplImage*dctImage=0){
	
	int x,y;
	cvCvtColor(src,image,CV_BGR2GRAY);

	double CosTable[8][8]	= {0.0};
	double SqrtValue = 1.0/sqrt(2.0);
	double Cu, Cv = 0.0;
	double DCTValue = 0.0;
	CvMat*DCTImage=0;
	DCTImage = cvCreateMat(image->height, image->width, CV_64FC1);

  int a, b, i, j, u, v;

	//make cosTable
	for(i = 0; i < 8; i++){
		for(j = 0; j < 8; j++){
			CosTable[i][j] = cos(PI * (2.0 * (double)j + 1.0)* (double)i / 16.0);
		}
	}
	//DCT
	for(a = 0; a < image->height; a += 8){
		for(b = 0; b < image->width; b += 8){

			for(u = 0; u < 8; u++){

				if(u == 0){
					Cu = SqrtValue;
				}
				else{
					Cu = 1.0;
				}

				for(v = 0; v < 8; v++){

					DCTValue = 0.0;

					if(v == 0){
						Cv = SqrtValue;
					}
					else{
						Cv = 1.0;
					}

					for(i = 0; i < 8; i++){
						for(j = 0; j < 8; j++){
							DCTValue += image->imageData[ image->widthStep*(a + i)+ b + j]* CosTable[u][i] * CosTable[v][j];							
						}
					}
					cvmSet(DCTImage,a+u,b+v,Cu*Cv*DCTValue);
				}
			}
		}
	}

   for(y=0; y<dctImage->height; y++){
    for(x=0; x<dctImage->width; x++){
      dctImage->imageData[dctImage->widthStep * y + x] =(unsigned char)cvmGet(DCTImage,y,x);
	}
   }
}
 
///////////////////////////////////////////////////////////////////////////////////////////
////////////main////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv){
	
	////Size
	int WIDTH = 640;
	int HEIGHT = 480;

	////IplImage
	IplImage*dct=0,*gray=0;
	IplImage*src=cvLoadImage("src.jpg",CV_LOAD_IMAGE_COLOR);
    int key;    
    int n = 0;  

    ////make IplImage 
	gray=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
	dct=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    ////make window name
    cvNamedWindow("Line Sample", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("DCT", CV_WINDOW_AUTOSIZE);
	////DCT
		IplImage*tmp=cvCloneImage(src);
		DCT(tmp,gray,dct);
	////Save Images
		//cvSaveImage("test.jpg",src);
		//cvSaveImage("test_DCT.jpg",dct);
    
	//maek window roop
    while(true){
        cvShowImage("Line Sample", src);
		cvShowImage("DCT", dct);

        //key
        key = cvWaitKey(10);

        //End@ESC_key
        if(key==0x1b)
            break;
        
   }

    //Release
    cvDestroyWindow("Line Sample");
	cvDestroyWindow("DCT");

    return 0;
}

アバター
usao
記事: 1887
登録日時: 11年前

Re: C++のDCTプログラムについて

#2

投稿記事 by usao » 9年前

>処理の部分はまったく変更せず、ソース画像を変えただけなのですが二つの結果が違う結果となります。

入力が異なれば出力が異なるのは 当たり前のことではないでしょうか?

それとも
①と②が,「絵の内容としては同じハズなのに」結果が異なる ということをおっしゃっているのでしょうか?
仮にそういう話だとしたら…
>IplImage*src=cvLoadImage("src.jpg",CV_LOAD_IMAGE_COLOR);
ここで読んでいるjpg画像が,非可逆圧縮によって変化(劣化)してしまっているということはありませんか?

kehos12
記事: 11
登録日時: 10年前

Re: C++のDCTプログラムについて

#3

投稿記事 by kehos12 » 9年前

usaoさん
言葉足らずで申し訳ありません。
掲載したソースでは異なっていますが基本的には①で生成した画像を使用して比較しています。
上が①の結果で、下が②の結果なのですが劣化のみが原因ではなさそうな気がして・・・。
http://www.fastpic.jp/images.php?file=1522312727.png
お手数ですができたらご意見をいただきたいです・・・。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: C++のDCTプログラムについて

#4

投稿記事 by h2so5 » 9年前

②の画像はだいぶ劣化しているようにみえるのでこの結果でもおかしくないような気がしますが。
MATLABかGNU Octaveで画像のDCTができるはずなので、比較してみてはいかがでしょうか。

kehos12
記事: 11
登録日時: 10年前

Re: C++のDCTプログラムについて

#5

投稿記事 by kehos12 » 9年前

h2so5さん
なるほど、ご指摘ありがとうございます。近いうちにMATLABとの比較を行ってみたいと思います。
別の質問になってしまうかもしれませんが、OpenCVで劣化のない読み込み方法があればご教授いただきたいです。
実はこれを作る際に参考にしたプログラムがありまして、今回の②と同じ画像を読み込んだ結果として①のような結果が得られるものとなっています。
しかしその部分のソースは読めなくなっているために質問させていただきました。
何度も申し訳ありません。
ご存知の方がいれば是非ご教授をお願いいたします。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: C++のDCTプログラムについて

#6

投稿記事 by h2so5 » 9年前

保存するときにjpegではなくてpngにすれば劣化しません。拡張子を.pngに変更するだけです。

アバター
usao
記事: 1887
登録日時: 11年前

Re: C++のDCTプログラムについて

#7

投稿記事 by usao » 9年前

>OpenCVで劣化のない読み込み方法

「画像を読み込む方法」に問題があるのではなくて,
それ以前に 「画像ファイルの内容が既に」 劣化(変化)している, という話です.

(DCTを行っているプログラムとは関係ない話で)
その入力画像を作ったとき(画像をファイルとして保存した時)に,
jpg圧縮した時点で劣化した(jpgは不可逆圧縮なので,保存しようとした画像内容 と 保存された画像内容 とが違ったものになってる)
ということ.

つまり
ノイズの無いきれいな画像でアルゴリズムの動作を見よう とかいう話をしている際に
jpg画像を入力として用いているのが間違い.


画像ファイルの種類について,例えば…

bmp : 基本.無圧縮(一応ランレングス圧縮ができるらしいが). ファイルサイズでかすぎ.
png : 可逆圧縮. ファイルサイズはあまり縮まないけど,画像劣化しないのが利点.今回のような用途向き.
jpg : 非可逆圧縮. 画像劣化しちゃうけど,ファイルサイズ超小さい. 写真とかの自然画像のファイルサイズを小さくする用途向きのもの.

…みたいなのを少し調べてみた方が良いと思います.

kehos12
記事: 11
登録日時: 10年前

Re: C++のDCTプログラムについて

#8

投稿記事 by kehos12 » 9年前

h2so5さん
usaoさん
ご指摘どうもありがとうございます。形式を変えてみたところ改善が見られました。
何度もありがとうございました。
これからも是非お力添えをよろしくお願いいたします。

閉鎖

“C言語何でも質問掲示板” へ戻る