4

ここで欲しいのは、現在のコードの機能し、最適化されたバージョンです。私の関数は実際の結果を含む配列を返しますが、それらが正しいかどうかはわかりません(私は数学の第一人者ではなく、結果を既知の実装と比較するJavaコードもわかりません)。次に、関数がカスタムテーブルサイズを受け入れることができるようにしたいのですが、その方法がわかりません。テーブルサイズは画像のリサンプリングと同等ですか?係数を正しく適用していますか?

// a lot of processing is required for large images
$image = imagecreatetruecolor(21, 21);
$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);
imagefilledellipse($image, 10, 10, 15, 15, $white);

print_r(imgDTC($image));

function imgDTC($img, $tableSize){
    // m1 = Matrix1, an associative array with pixel data from the image
    // m2 = Matrix2, an associative array with DCT Frequencies
    // x1, y1 = coordinates in matrix1
    // x2, y2 = coordinates in matrix2
    $m1 = array();
    $m2 = array();

    // iw = image width
    // ih = image height
    $iw = imagesx($img);
    $ih = imagesy($img);

    // populate matrix1
    for ($x1=0; $x1<$iw; $x1++) {
        for ($y1=0; $y1<$ih; $y1++) {
            $m1[$x1][$y1] = imagecolorat($img, $x1, $y1) & 0xff;
        }
    }

    // populate matrix2
    // for each coordinate in matrix2
    for ($x2=0;$x2<$iw;$x2++) {
        for ($y2=0;$y2<$ih;$y2++) {

        // for each coordinate in matrix1
            $sum = 1;
            for ($x1=0;$x1<$iw;$x1++) {
                for ($y1=0;$y1<$ih;$y1++) {
                    $sum += 
                        cos(((2*$x1+1)/(2*$iw))*$x2*pi()) * 
                        cos(((2*$y1+1)/(2*$ih))*$y2*pi()) * 
                        $m1[$x1][$y1]
                    ;
                }
            }

            // apply coefficients
            $sum *= .25;
            if ($x2 == 0 || $y2 == 0) {
                $sum *= 1/sqrt(2);
            }

            $m2[$x2][$y2] = $sum;
        }
    }
    return $m2;
}

私のPHP関数は、Javaのこの投稿から派生したものです:JavaのDCTおよびIDCTアルゴリズムの問​​題。phpと読みやすさのためにコードを書き直しました。最終的に、私は画像を比較して類似点を見つけることができるスクリプトに取り組んでいます。この手法の概要は次のとおりです:http ://www.hackerfactor.com/blog/index.php?/ archives/432-Looks-Like-It.html 。

ありがとう!

4

2 に答える 2

1

これが私がDCTを実行した方法です。ここで行っているのは、各行で1次元のDCTを実行することです。次に、結果を取得して、各列でDTCを実行しました。

function dct1D($in) {
    $results = array();
    $N = count($in);
    for ($k = 0; $k < $N; $k++) {
        $sum = 0;
        for ($n = 0; $n < $N; $n++) {
             $sum += $in[$n] * cos($k * pi() * ($n + 0.5) / ($N));
        }
        $sum *= sqrt(2 / $N);
        if ($k == 0) {
            $sum *= 1 / sqrt(2);
        }
        $results[$k] = $sum;
    }
    return $results;
}

function optimizedImgDTC($img) {
    $results = array();

    $N1 = imagesx($img);
    $N2 = imagesy($img);

    $rows = array();
    $row = array();
    for ($j = 0; $j < $N2; $j++) {
        for ($i = 0; $i < $N1; $i++)
            $row[$i] = imagecolorat($img, $i, $j);
        $rows[$j] = dct1D($row);
    }

    for ($i = 0; $i < $N1; $i++) {
        for ($j = 0; $j < $N2; $j++)
            $col[$j] = $rows[$j][$i];
        $results[$i] = dct1D($col);
    }
    return $results;
}

私がインターネットで見つけたほとんどのアルゴリズムは、入力行列が8x8であると想定しています。そのため、0.25を掛けました。一般に、1D行列にsqrt(2 / N)を掛ける必要があります。ここでは、2Dであるため、sqrt(2 / N1)* sqrt(2 / N2)です。N1=8およびN2=8に対してこれを行う場合:sqrt(2/8)^ 2 = 2/8 = 1/4 = 0.25

もう1つは、1 / sqrt(2)X0を乗算することでした。これは2Dであるため、k1=0またはk2=0の場合に乗算します。k1=0およびk2=0の場合は、2回実行する必要があります。

于 2013-01-17T18:26:20.540 に答える
0

まず、関数をテストする必要があるので、機能する実装を見つけます。そして、実装の結果を(同じ入力で)実際の実装の結果と比較します。

コードをより高速にしたい場合は、このペーパーhttp://infoscience.epfl.ch/record/34246/files/Vetterli85.pdf(最初の2つの部分)を参照してください。

あなたの場合、カスタムテーブルサイズは画像サイズと一致する必要があるため使用できません(間違っている可能性があります)。

于 2013-01-17T09:20:44.290 に答える