Potreboval bych pomoci s optimalizaci kody pro vypocet dct transformace (pouziva to treba jpeg), abych to mohl zkusit aplikovat na cely obrazek, ne jen na 32x32 pixelu. Klasicky jpeg to pouziva na 8x8 pole, coz je dost nuda a s dnesnim vypocetnim vykonem a pameti by mohl pouziva linearni nebo kvadratickou dct na cely soubor. Takovy je plan :)
* Treba strasnou brzdu mi tam dela pocitani absolutni hodnoty pres abs(). To uz jsem nahradil.
* Tez si nejsem jisty, co to bude delat na rychlosti, kdyz misto kosinove tabulky to budu pocitat primo.
* Mno, a potom se mi tak uplne nelibi prace s polem. Neni tam nejaky rychlejsi prvek? Ono to pole v pameti i dost zabira a pak mi tam strasi s prekrocenim limitu pameti.
<?php
ini_set('max_execution_time', 10000); //10000s
//set_time_limit(10000);
//ini_set('memory_limit', '256M');
function microtime_float() //pp 17.3.2014
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
$time = array();
$time[] = microtime_float();
// input
$file = "img/1299576.jpg";
list($width, $height, $type, $attr) = getimagesize($file);
$img = ImageCreateFromJpeg($file);
imagefilter($img, IMG_FILTER_GRAYSCALE);
// prepare tables
//$inp = array(14,17,49,122,8,56,67,121,18,219,163,88,147,88,195,121);
//$q = array(16,11,10,16,12,12,14,19,14,13,16,24,14,17,22,29);
//$max = 16;
$maxM = $maxN = 4;
$maxM = $maxN = 16;
$maxM = $maxN = 32;
//$maxM = $maxN = 64;
$maxMN = $maxM * $maxN;
$cosA = array();
$cosB = array();
$qcA = array();
$qcB = array();
//$c = array();
$c_arr = array();
$c_arr[0] = pow(1/$maxM,0.5);
$c_arr[1] = pow(2/$maxM,0.5);
$c_arr[2] = pow(1/$maxN,0.5);
$c_arr[3] = pow(2/$maxN,0.5);
$c_arr[4] = $c_arr[1] * $c_arr[3];
//$c_arr[0] *= $c_arr[4];
//$c_arr[1] *= $c_arr[4];
$cosCM = $cosCN = M_PI / (2 * $maxM);
$cosM = array();
for ($j=0,$ii=0;$j<$maxM;$j++)
{
$cosM[$j] = array();
for ($i=0;$i<$maxN;$i++,$ii++)
{
$cosM[$j][$i] = cos($cosCM * (2*$j+1)*$i);
}
}
//echo '<pre>';
//print_r($cosM);
// ---
$cosSuma = array();
for ($ii=0;$ii<$maxMN;$ii++)
{
$cosSuma[$ii] = 0;
}
for ($k=0,$kk=0;$k<$maxM;$k++)
{
for ($l=0;$l<$maxN;$l++,$kk++)
{
for ($i=0,$ii=0;$i<$maxM;$i++)
{
for ($j=0;$j<$maxN;$j++,$ii++)
{
// $cos = cos($cosCM * (2*$k+1)*$i) * cos($cosCN * (2*$l+1)*$j); //ok
$cos = $cosM[$k][$i] * $cosM[$l][$j];
// $cosSuma[$ii] += abs($cos);
$cosSuma[$ii] += $cos>0 ? $cos : -$cos;
// $cosSuma[$ii] += $cos;
}
}
}
}
for ($ii=0;$ii<$maxMN;$ii++)
{
$cosSuma[$ii] /= $maxM/4;
}
$time[] = microtime_float();
// read input
$x = 0;
$y = 0;
$x = 300;
$y = 600;
$inp = array();
for ($i=0,$ii=0;$i<$maxM;$i++)
{
for ($j=0;$j<$maxN;$j++,$ii++)
{
$inp[$ii] = imagecolorat($img, $x+$i, $y+$j) & 0xFF; //$r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF;
// $inp[$iI] = rand(0,256);
}
}
$time[] = microtime_float();
$out = array();
/*
$qcM = 1;
for ($ii=0;$ii<$maxMN;$ii++)
{
$out[$ii] = 0;
}
*/
for ($i=0,$ii=0;$i<$maxM;$i++)
{
$c1 = $i==0 ? $c_arr[0] : $c_arr[1];
for ($j=0;$j<$maxN;$j++,$ii++)
{
$c2 = $j==0 ? $c_arr[2] : $c_arr[3];;
// $qcM = ($c1 * $c2) / $q[$ii]; //ok
$qcM = ($c1 * $c2) / $cosSuma[$ii];
$out[$ii] = 0;
for ($k=0,$kk=0;$k<$maxM;$k++)
{
for ($l=0;$l<$maxN;$l++,$kk++)
{
// ok $cosM = cos($cosCM * (2*$k+1)*$i) * cos($cosCN * (2*$l+1)*$j);
$cos = $cosM[$k][$i] * $cosM[$l][$j];
$out[$ii] += $inp[$kk] * $cos;
}
}
$out[$ii] = round($out[$ii] * $qcM);
}
}
// transform 1D back
$inp2 = array();
for ($ii=0;$ii<$maxMN;$ii++)
{
$inp2[$ii] = 0;
}
for ($k=0,$kk=0;$k<$maxM;$k++)
{
for ($l=0;$l<$maxN;$l++,$kk++)
{
for ($i=0,$ii=0;$i<$maxM;$i++)
{
$c1 = $i==0 ? $c_arr[0] : $c_arr[1];
for ($j=0;$j<$maxN;$j++,$ii++)
{
$c2 = $j==0 ? $c_arr[2] : $c_arr[3];
// $qcM = ($c1 * $c2) * $q[$ii];
$qcM = ($c1 * $c2) * $cosSuma[$ii];
// ok $cos = cos($cosCM * (2*$k+1)*$i) * cos($cosCN * (2*$l+1)*$j);
$cos = $cosM[$k][$i] * $cosM[$l][$j];
$inp2[$kk] += $out[$ii] * $cos * $qcM;
}
}
}
}
$stat_diff = array();
$stat_inp=0;
$stat_out=0;
$stat_err=0;
for ($ii=0;$ii<$maxMN;$ii++)
{
$inp2[$ii] = round($inp2[$ii]);
// $inp2[$i] = $inp2[$i] <= 255 ? ($inp2[$i] >= 0 ? $inp2[$i] : 0) : 255;
$stat_inp += abs($inp[$ii]);
$stat_out += abs($out[$ii]);
$stat_err += abs($inp[$ii] - $inp2[$ii]);
// $stat_diff[$ii] = $inp[$ii] - $inp2[$ii];
// $stat_err += abs($stat_diff[$ii]);
}
// print
echo '<table><tr>';
//echo '<td>cosA';
//echo '<pre>'; print_r($cosM); echo '</pre>';
//echo '<td>cosB';
//echo '<pre>'; print_r($cosB); echo '</pre>';
//echo '<td>Q';
//echo '<pre>'; print_r($q); echo '</pre>';
//echo '<td>C';
//echo '<pre>'; print_r($c); echo '</pre>';
//echo '<td>QC-A';
//echo '<pre>'; print_r($qcA); echo '</pre>';
//echo '<td>cosSuma';
//echo '<pre>'; print_r($cosSuma); echo '</pre>';
if ($maxM<=16)
{
echo '<td>INP';
echo '<pre>'; print_r($inp); echo '</pre>';
echo '<td>OUT';
echo '<pre>'; print_r($out); echo '</pre>';
echo '<td>INP2';
echo '<pre>'; print_r($inp2); echo '</pre>';
echo '<td>stat_diff';
echo '<pre>'; print_r($stat_diff); echo '</pre>';
}
echo '</tr></table>';
echo "err = $stat_err / ".($maxMN*256)." (".($stat_err/($maxMN*256)*100)." %) ... abs(D) / (max*256)<br>";
echo "inp = $stat_inp | out = $stat_out ... suma(value)<br>";
//echo "errinp = $stat_err / $stat_inp = ".($stat_err/$stat_inp*100)." % (A / B)";
//output
//header('Content-Type: image/png');
//imagepng($img);
imagedestroy($img);
$time[] = microtime_float();
$t = array();
$t[] = round($time[count($time)-1]-$time[0],3);
for ($i=1;$i<count($time);$i++)
{
$t[] = round($time[$i]-$time[$i-1],3);
}
$t = implode(" | ",$t);
echo '<hr>Cas zpracovani '.$t.' s';
/*
pp q-256:
16 18 23 27 34 34 38 40
18 20 26 30 38 38 42 44
23 26 34 40 50 50 55 58
27 30 40 46 58 58 64 67
34 38 50 58 72 72 80 84
34 38 50 58 72 72 80 84
38 42 55 64 80 80 89 94
40 44 58 67 84 84 94 99
var tabZ=new Array(MMNN);
var x=Math.sqrt(MM/2 * NN/2);
var i,j,k;
for(j=0,k=0;j<NN;j++) {for(i=0;i<MM;i++,k++)
{tabZ[k] = x/Math.sqrt((2*i+1)*(2*j+1));}}
*/
?>