今、画像圧縮の勉強をしてるんですが、離散コサイン変換(DCT)のプログラムが
分からないので、サンプルプログラムなどがあれば見てみたいのですが、誰か
しらないでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (2件)

高速フーリエ・コサイン・サイン変換(FFT)でよければプログラムはあります。


FFT とは離散フーリエ変換に関連する変換を高速に実行する一連の計算方法のことです。参考になればよいのですが。

参考URL:http://momonga.t.u-tokyo.ac.jp/~ooura/fftman/
    • good
    • 0

以下のサイトはどうでしょうか。



それと本なども出ております。
「マルチメディア技術の基礎DCT(離散コサイン変換)入門」
http://www.cqpub.co.jp/hanbai/books/36791.htm

参考にされてください。

参考URL:http://www.mathworks.com/access/helpdesk/jhelp/t …

この回答への補足

もっとプログラムのことについて詳しく載っているサイトってないんでしょうか?

補足日時:2001/01/17 16:38
    • good
    • 0
この回答へのお礼

本の紹介ありがとうございます。さっそく購入してみます。

お礼日時:2001/01/17 13:32

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q画像圧縮の離散コサイン変換,量子化について

画像圧縮について勉強していてあやふやなところがあり教えて頂きたいです.

変換前
|126, 138, 135, 118, 118, 126, 126, 130|
|150, 168, 161, 122, 105, 109, 100, 118|
|150, 150, 126, 150, 142, 126, 126, 117|
|150, 161, 168, 130, 134, 150, 138, 130|
|130, 118, 134, 142, 157, 142, 117, 126|
|115, 117, 108, 117, 101, 99, 117, 126|
|122, 130, 130, 138, 117, 108, 108, 138|
|142, 118, 134, 117, 109, 91, 126, 109|

変換後
|1029, 52, 10, -21, -1, -3, 2, 1|
| 39, 21, 0, 6, -22, -17, 4, -7|
| -40, 12, 24, -19, -2, 7, -4, 5|
| -32, -34, -1, -7, 5, -8, 5, -7|
| 22, -14, -10, 16, -12, 4, 12, 18|
| 19, -17, 1, -3, -6, -3, -2, -8|
| -24, -18, 3, 15, 9, 15, -20, 1|
| 9, -16, -30, 14, 29, -2, -5, -5|

URLから参考にしたものですが,変換すると右下から左上へと値が高くなっています.
これは圧縮することで,左上の情報量が大きくなる方法ということはわかります.
ですが,量子化する方法がよくわかりません.
この値を使ってどうすればいいのでしょうか.
変換前は濃度あたりだと思うんですが,変換後はマイナスの値がついててさっぱりです.

検索していろいろでてきたのですが,
難しくてわからないところもあったので
一言“量子化する”とかじゃなくて
“離散コサイン変換後の量子化方法はこうするものだ”という具体的なものができればききたいです.

最終的に画像圧縮プログラムを組もうと思っています.
圧縮までに必要な仮定を教えてください.

あと,プログラムはVisualC++OpenCVで組もうと思うのですが,勉強ですので関数を使うつもりはありません.
おまけですが,JPEGで離散コサイン変換するという方法があるみたいですが,IPLimageを使用するのは不可能ですか?

質問する場所がわからなかったのでここでさせて頂いたのですが,間違っていたら移動させますので教えて頂けるとありがたいです.

よろしくお願いします.

参考URL:http://fussy.web.fc2.com/algo/algo8-6.htm

画像圧縮について勉強していてあやふやなところがあり教えて頂きたいです.

変換前
|126, 138, 135, 118, 118, 126, 126, 130|
|150, 168, 161, 122, 105, 109, 100, 118|
|150, 150, 126, 150, 142, 126, 126, 117|
|150, 161, 168, 130, 134, 150, 138, 130|
|130, 118, 134, 142, 157, 142, 117, 126|
|115, 117, 108, 117, 101, 99, 117, 126|
|122, 130, 130, 138, 117, 108, 108, 138|
|142, 118, 134, 117, 109, 91, 126, 109|

変換後
|1029, 52, 10, -21, -1, -3, 2, 1|
| 39, 21, 0, 6...続きを読む

Aベストアンサー

> URLから参考にしたものですが,変換すると右下から左上へと値が高くなっています.
> これは圧縮することで,左上の情報量が大きくなる方法ということはわかります.

まず、一つ指摘をしておきます。離散コサイン変換は、情報量を減らしません。つまり、この変換は情報の圧縮を行っているわけではないのです。しかも、

> 変換前は濃度あたりだと思うんですが,変換後はマイナスの値がついててさっぱりです.

だとすると、”離散コサイン変換”が何をするものなのか、残念ながら理解できていないと思います。

> ですが,量子化する方法がよくわかりません.
> この値を使ってどうすればいいのでしょうか.

参考URL に、
> 画素ブロックの各要素に対して、量子化テーブルの同じ行列にある要素を使って量子化/逆量子化するため、
> 画素ブロックの各要素をSuv、量子化テーブルの各要素をQuvとすると、量子化・逆量子化変換式は次のようになります。

> 量子化 : Ruv = Suv / Quv
> 逆量子化 : Suv = Ruv X Quv

と、書かれています。
つまり、量子化テーブルの値で割り算をすればよいのです。

> URLから参考にしたものですが,変換すると右下から左上へと値が高くなっています.
> これは圧縮することで,左上の情報量が大きくなる方法ということはわかります.

まず、一つ指摘をしておきます。離散コサイン変換は、情報量を減らしません。つまり、この変換は情報の圧縮を行っているわけではないのです。しかも、

> 変換前は濃度あたりだと思うんですが,変換後はマイナスの値がついててさっぱりです.

だとすると、”離散コサイン変換”が何をするものなのか、残念ながら理解できていないと思います。

>...続きを読む

Q離散フーリエ変換のプログラムについて

今DFTのプログラムをC言語で書いているんですが、うまく動いてくれません。
DFTの式はX(k)=1/N{Σx(k)*e^(-j2πkn/N)}のシグマの中をn=0からN-1まで足し合わせればいいと思っているのですがちがいますか。
下にプログラムを書きますのでお願いします。

void DFTcore(double x[],int N,double A[],double fai[],double a_rl[],double a_im[]){

    x[]はデータ
    Nはデータ数
    A[]は振幅
    fai[]は位相差
    a_rl[]は実数部、a_im[]は虚数部

double w,a;
int k,n,t;

for(k=0;k<N;k++){  //初期化
   a_rl[k]=0.0;  //実数部
   a_im[k]=0.0;  //虚数部
  }
    時間間隔は1秒
for(k=0;k<N;k++){
      for(n=0;n<N;n++){
  w=((2*PI)/N)*k*n;
        a_rl[k]=a_rl[k]+x[k]*cos(w);
  a_im[k]=-a_im[k]+x[k]*sin(w);
 }
  a_rl[k]=a_rl[k]/(double)N;実数部
  a_im[k]=-a_im[k]/(double)N; 虚数

  A[k]=sqrt(a_rl[k]*a_rl[k]+a_im[k]*a_im[k]);//振幅
   fai[k]=atan(a_im[k]/a_rl[k]);//位相

}
}

今DFTのプログラムをC言語で書いているんですが、うまく動いてくれません。
DFTの式はX(k)=1/N{Σx(k)*e^(-j2πkn/N)}のシグマの中をn=0からN-1まで足し合わせればいいと思っているのですがちがいますか。
下にプログラムを書きますのでお願いします。

void DFTcore(double x[],int N,double A[],double fai[],double a_rl[],double a_im[]){

    x[]はデータ
    Nはデータ数
    A[]は振幅
    fai[]は位相差
    a_rl[]は実数部、a_im[]は虚数部

double w,a;
...続きを読む

Aベストアンサー

正しくは、X(k)=1/N{Σx(n)*e^(-j2πkn/N)}
(ただし、k=f*N/f_sample , fは調べたい周波数、f_sampleはサンプリング周波数)
です。
とりあえずは、
a_rl[k]=a_rl[k]+x[n]*cos(w);
a_im[k]=a_im[k]+x[n]*sin(w);
とすれば動作確認はできます。
あとはご自分のプログラムの中でのkの意味(f*N/f_sampleは整数でなくてもよい)、f<(f_sample/2)、に注意し、プログラムを書きなおしてみてください。またきれいなスペクトルを得るには窓関数処理をお忘れなく。

数学、数式が大の苦手の私ですが、DFTはおぼろげに理解できたので、以前N88BASICという言語で(今は知っている人が少ないらしい)、DFTのプログラムを書いたことがあります。なにせクロック周波数12MHzのパソコンだったので、サインテーブルを作って積和演算の部分はマシン語で書いたり、いろいろやりました。
きれいなスペクトルが出ると感動しますよ。ご健闘を祈ります。
 

正しくは、X(k)=1/N{Σx(n)*e^(-j2πkn/N)}
(ただし、k=f*N/f_sample , fは調べたい周波数、f_sampleはサンプリング周波数)
です。
とりあえずは、
a_rl[k]=a_rl[k]+x[n]*cos(w);
a_im[k]=a_im[k]+x[n]*sin(w);
とすれば動作確認はできます。
あとはご自分のプログラムの中でのkの意味(f*N/f_sampleは整数でなくてもよい)、f<(f_sample/2)、に注意し、プログラムを書きなおしてみてください。またきれいなスペクトルを得るには窓関数処理をお忘れなく。

数学、数式が大の苦手の私ですが、DFTはおぼろ...続きを読む

Qjpeg の DCT 変換がうまくいきません。

jpeg の DCT 変換がうまくいきません。

jpegを作りたいのですが、DCT変換で詰まってしまいました。
よろしければ、ご教授いただけませんでしょうか?

http://www.ann.hi-ho.ne.jp/jiro/assyuku2.htm

のDCT変換の例を見て、プログラムを作ってみましたが、
変換例と同じ値に変換されませんでした。

作ってみたプログラムです。

#include <iostream>
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>

using namespace std;


void main(int argc, char** argv)
{

  double cu = 1.0;
  double cv = 1.0;
    double long sum = 0.0;
  
  int before[8][8] ={
    {57,49,44,39,33,28,23,22},
    {55,45,39,33,28,21,21,19},
    {55,44,37,31,20,17,17,16},
    {58,44,37,29,17,15,16,14},
    {66,46,31,22,16,14,12,10},
    {71,49,32,24,14,12,21,19},
    {69,50,30,22,12,4,-1,-2},
    {62,42,25,17,7,1,-16,-16}
  
  };
  int after[8][8];
  ZeroMemory(after,sizeof(int)*64);

  for(int v =0; v < 8; v++)
  {
    if(v) cv =1.0;
    if(!v) cv = 1 / sqrt(2.0);
    for(int u = 0; u < 8; u++)
    {
      if(u) cu =1.0;
      if(!u) cu = 1 / sqrt(2.0);
      sum = 0.0;
      for(int y = 0; y < 8; y++)
      {
        for(int x = 0; x < 8; x++)
        {
          double long a = cos((2 * x + 1)*u*M_PI/16) * cos(( 2 * y + 1)*v*M_PI/16);
          double long d = before[x][y];
          sum += d * a;
        }
      }
      after[u][v] = int(cu*cv*sum/4);
    }
  }

  for(int j = 0; j < 8; j++)
  {
    for(int i = 0; i < 8; i++)
    {
      cout << after[i][j] << ",";
    }
    cout << endl;
  }

  int b;
  cin >> b ;


}

jpeg の DCT 変換がうまくいきません。

jpegを作りたいのですが、DCT変換で詰まってしまいました。
よろしければ、ご教授いただけませんでしょうか?

http://www.ann.hi-ho.ne.jp/jiro/assyuku2.htm

のDCT変換の例を見て、プログラムを作ってみましたが、
変換例と同じ値に変換されませんでした。

作ってみたプログラムです。

#include <iostream>
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>

using namespace std;


void main(int argc, char** argv)
{

  double cu = 1.0;
 ...続きを読む

Aベストアンサー

ちょっとだけ補足しておきます。

> int(floor(cu*cv*sum/4+0.5));

floor は「引数値を超えない最大の整数」を返す関数であり、
それに0.5足した値を入れることで、四捨五入になります。

修正前> double long d = before[x][y];
修正後> double long d = before[y][x];

修正前> after[u][v] = int(cu*cv*sum/4);
修正後> after[v][u] = int(floor(cu*cv*sum/4+0.5));

修正前> cout << after[i][j] << ",";
修正後> cout << after[j][i] << ",";

この3行の修正で、質問者さんが挙げたリンク先の実行例と同じ結果になることは確認済です。

Qどんなプログラムになるのかわからないのでプログラムを作って頂けませんか

どんなプログラムになるのかわからないのでプログラムを作って頂けませんか?

3分間英単語タイプ練習プログラム作ってを5日以上にわけて計25回以上実行します。

1 単語ファイルword.txtを単語数未知として読み込むこと.3975単語含まれているが,単語数をプログラムに直接書き込むことや実行時に与えることは禁止.
2 単語は一様乱数を用いてランダムに呈示すること.プログラム完成後,プログラムの先頭に「srand((unsigned)time(NULL));」を付加しなさい.これにより,実行時刻によって乱数シードが変わるから,異なった単語(系列)が呈示されることになる.
3 各回の得点は「正答した単語の文字数の総和」とする.
4 毎回「月/日/年-時:分:秒,得点」を結果ファイルscore.csvに追加的に書き込む(追記モード)。秒と得点の間のカンマは半角にする必要があることを注意しておく.

Aベストアンサー

とりあえず使いそうな関数だけ書いておきます。あとは調べてください。

fgets, fseek

とりあえずこれだけで作れる・・・かな?word.txtの中身が分からないですが、一行につき一単語のみが書いてあると仮定するとfgetsをループすれば単語数は求められます。

単語をメモリに格納した方が速度は早くなるのでそのときはfgets, malloc, freeで作れるかと。

ポインタは分かっていますか?
ポインタ分かってないとちょっと厳しいかも・・・

がんばってください。

Q離散フーリエ変換について

G(n/Nτ)= Σ[k=0->N-1] {τ*f(kτ)*e^(-i2πkn/N)}
上記の式は離散フーリエ変換の式らしいですが、
これを関数化しようとしてつまずいています。
どのように解釈すれば、関数化できるのでしょうか?
特に、複素数iがよくわかりません。
e^iが点を左に90度回転させるくらいはわかります。
e^(-i2πkn/N)を関数powで表現できなくて困っていますが、多分見当違いだとは思います。
フーリエ級数展開はわかります。
最終的にはFFTを行いたいのですが、
その理解の前に離散フーリエ変換ができないといけないと思っています。
よろしくお願いします。

void GraphClass::ScatteredFourierConvert()
{
/*
N-1
G(n/Nτ)= Σ {τ*f(kτ)*e^(-i2πkn/N)}
k=0
k=何番目の値か?
τ=値を読んだ間隔
N=値を読んだ数
*/
int Tau=10;
int N=RangeSize.cx*2/Tau;
double Sum=0;
double e=2.7182818;
for(int k=0;k<N-1;k++)
{
Sum+=Tau*Data[k*Tau]*pow(e,-i*2*PI*k*n/N);
}
}

G(n/Nτ)= Σ[k=0->N-1] {τ*f(kτ)*e^(-i2πkn/N)}
上記の式は離散フーリエ変換の式らしいですが、
これを関数化しようとしてつまずいています。
どのように解釈すれば、関数化できるのでしょうか?
特に、複素数iがよくわかりません。
e^iが点を左に90度回転させるくらいはわかります。
e^(-i2πkn/N)を関数powで表現できなくて困っていますが、多分見当違いだとは思います。
フーリエ級数展開はわかります。
最終的にはFFTを行いたいのですが、
その理解の前に離散フーリエ変換ができないといけないと思って...続きを読む

Aベストアンサー

その式の「eのべき」の部分は、複素数を実部と虚部に分けて書くとsinとcosで表すことができます。

プログラミング向けの参考書であれば必ず書いてあります。また、「フーリエ変換 sin cos」で検索すると参考になるページがたくさん出てきます。

がんばってください。

#「離散フーリエ変換」はDiscrete Fourier Transformと表現するのが一般的です


人気Q&Aランキング

おすすめ情報