首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在PHP中计算离散余弦变换(DCT)?

如何在PHP中计算离散余弦变换(DCT)?
EN

Stack Overflow用户
提问于 2013-01-01 08:16:31
回答 2查看 4.3K关注 0票数 4

我在这里想要的是我当前代码的一个工作的,优化的版本。虽然我的函数确实返回一个包含实际结果的数组,但我不知道它们是否正确(我不是数学专家,我也不懂Java代码来将我的结果与已知的实现进行比较)。其次,我希望该函数能够接受自定义的表大小,但我不知道如何做到这一点。表大小是否等同于对图像进行重采样?我是否正确地应用了系数?

代码语言:javascript
复制
// 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:Problems with DCT and IDCT algorithm in java这篇文章中派生出来的。我已经为php和可读性重写了代码。最终,我正在编写一个脚本,它将使我能够比较图像并找到相似之处。这里概述了该技术:http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-18 02:26:21

这就是我执行DCT的方法,我在这里做的是在每一行上执行一维DCT。然后我把结果取出来,在每一列上执行DTC,这样更快。

代码语言:javascript
复制
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的原因。一般来说,你应该乘以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/ X0 (2),这是一维矩阵,这里是2D矩阵,所以当k1 = 0或k2 =0时乘法。当k1 =0和k2 =0时,您必须执行两次。

票数 1
EN

Stack Overflow用户

发布于 2013-01-17 17:20:44

首先,您需要测试您的函数,以便找到任何可用的实现。并将您的实现结果与工作实现的结果(具有相同的输入)进行比较。

如果你希望你的代码更快,你可以看看这篇论文http://infoscience.epfl.ch/record/34246/files/Vetterli85.pdf (前2部分)。

在您的例子中,您不能使用自定义表大小,因为它应该与图像大小匹配(可能是错误的)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14106984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档