Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

llama / llama_bachelor_MPiTK_2004_VM-1

.pdf
Скачиваний:
12
Добавлен:
16.04.2013
Размер:
475.19 Кб
Скачать

- 51-

filez = dir([encode_dir, '*.tif']); for f = 1:length(filez)

encode_file = filez(f).name;

disp(sprintf('Preparing %s for quantization...',encode_file)); im_orig = double(imread([encode_dir, encode_file]));

if ~use_cached_quant

I = img_prepare([encode_dir, encode_file]); save(sprintf('img/img_%s.mat',encode_file),'I');

end

im_spectre = load(sprintf('img/img_%s.mat',encode_file)); im_spectre = im_spectre.I;

disp('Test started.') cnt = 1;

for k=1:length(lambda)

for j=1:length(clusters)

cluster_mtx = double(dlmread(sprintf('data/clusters_•d.txt',clusters(j)),' '));

disp('________________________________'); disp(sprintf('C=%d Lambda=%.1f',clusters(j),lambda(k)));

disp(sprintf('Building statistics for update frequency estimation...'));

if ~use_cached_update_stat

nu_upd = build_upd_stat(im_train, cluster_mtx, Quant_mtx(find(Quant_coef == 1),:), upd_freq_size);

save(sprintf('data/%s_update_stat.mat',train_file),'nu_upd');

end

res = load(sprintf('data/%s_update_stat.mat',train_file)); nu_upd = res.nu_upd;

res = test_algorithm(cluster_mtx,L,lambda(k),book_epsilon,Q,Quant_mtx,im_orig,im_spectre ,im_train,nu_upd,tau,use_cached_book,showpic_after_calc);

for i=1:length(L)

result{f}{cnt} = {encode_file,L(i),clusters(j),lambda(k),res{i}{1},res{i}{2},res{i}{3}};

cnt = cnt + 1;

end

disp('Saving results...'); save([result_out_dir, result_file],'result');

end

end end

disp('Plotting graphs...'); for f = 1:length(filez)

encode_file = filez(f).name;

display_graphs(result{f}, encode_file, [encode_dir,encode_file(1:end- 4),'/']);

end

disp('Saving graphs...'); [flag,fig] = figflag(''); fig = sort(fig);

for i=1:length(fig)

saveas(fig(i),sprintf([result_out_dir, '•d'],i),'emf'); saveas(fig(i),sprintf([result_out_dir, '•d'],i));

end

disp('Test finished.');

disp(sprintf('\n\nLog closed at %d.%d.%d %d:%d:%d\n',floor(clock))); diary off;

- 52-

Файл quantize.m

function [index,update,upd_mtx] = quantize(book,image,Quant_mtx,cb_param,nu_upd,tau)

M = size(image,1);

clusters = cb_param{1}; lambda = cb_param{2}; nu = book{end};

n_clust = max(max(clusters));

D = zeros(n_clust,M); index = cell(1,n_clust+2); update = cell(1,n_clust); nu_up = cell(1,n_clust); upd_mtx = cell(1,n_clust);

for k = 1:n_clust

L = size(book{k},1); Lmax(k) = 128;

nu{k} = nu{k} * M / 48 + 1;

i_clust = find(clusters == k); A = image(:,i_clust);

b = [book{k}; zeros(Lmax(k) - L,size(book{k},2))];

R = [nu{k}, ones(1,Lmax(k) - L)];

%[Jvq J] = minJ_adaptive(book{k}',A',R,lambda); nu_upd{k} = nu_upd{k} / sum(nu_upd{k}) * 64 + 1;

%nu_upd{k}(1ћ)

[Jvq,

index{k},

 

update{k},

upd_mtx{k}]

=

gtr(b',A',R,lambda,int32(L),tau,Quant_mtx(:,i_clust)',nu_upd{k});

 

update{k} = update{k}';

 

 

 

 

upd_mtx{k} = upd_mtx{k}';

=

round(update{k}

./

%update{k}

repmat(Quant_mtx(i_clust),1,size(update{k},2)))';

 

 

nu{k} = nu{k} / sum(nu{k});

 

 

 

end

 

 

 

 

 

index{end-1} = image(:,1);

 

 

 

 

param{1} =

nu;

 

 

 

 

param{2} =

book;

 

 

 

 

param{3} =

Lmax;

 

 

 

 

index{end}

= param;

 

 

 

 

disp(['

Vectors updated: ',sprintf('%d,',cellfun('length',update))]);

 

Файл test_algorithm.m

function res = test_algorithm(clusters,L,lambda,epsilon,Q,Quant_mtx,im_orig,im_spectre,im_train,n u_upd,tau,use_cached_book,showpic_after_calc)

codebook_file = sprintf('book_L•d_C•_La•.mat',max(L),max(max(clusters)),lambda*10);

res = cell(1,length(L));

disp('Building codebook...'); if ~use_cached_book

b = build_codebooks(clusters,im_train,L,lambda,epsilon); save(sprintf('book/vol/%s.mat',codebook_file),'b');

end

book = load(sprintf('book/vol/%s.mat',codebook_file));

- 53-

for k=1:length(L) disp('_____________'); disp(sprintf('L=%d',L(k))); disp('Encoding...');

[index, update, upd_mtx] = quantize(book.b{k},im_spectre,Quant_mtx,book.b{end},nu_upd,tau);

index{end-1} = encode_dc(index{end-1},Q);

disp('Decoding...');

restored = decode(index,update,upd_mtx,[size(im_orig,1) size(im_orig,2)],Q,Quant_mtx,book.b{end},tau);

psnr = 20 * log10(255 * sqrt(size(im_orig,1) * size(im_orig,2) / sum(sum((im_orig - restored).^2))));

disp(sprintf('\tPSNR=%.3f',psnr)); if showpic_after_calc

figure;

imshow(restored / 255); pause;

end

disp('Compressing data...');

all_data = zeros(length(index{1}), max(max(clusters))+1); for i=1:length(index)-2

%[y res] = Arith07(cell({index{i}'}));

%bits = [bits res(1,3)];

all_data(:,i) = index{i}';% - 1;

end

all_data(:,end) = index{end-1} + abs(min(index{end-1})); nsyms = max(all_data)+1;

[bits encoded_data] = arith_mex(int32(all_data),int32(nsyms)); bits = double(bits)';

upd = []; upd_q = [];

for i=1:length(update)

upd = [upd; reshape(update{i},size(update{i},1)*size(update{i},2),1)]; upd_q = [upd_q; upd_mtx{i}];

end

upd = upd + abs(min(upd)); nsyms = max(upd)+1;

if ~isempty(upd)

[bits_upd encoded_data] = arith_mex(int32(upd),int32(nsyms)); bits_upd = double(bits_upd)';

nsyms = max(upd_q)+1;

[bits_updmtx encoded_data] = arith_mex(int32(upd_q),int32(nsyms)); bits_updmtx = double(bits_updmtx)';

else

bits_upd = 0; bits_updmtx = 0; end

bits = [bits, bits_upd, bits_updmtx];

disp(sprintf('Bits for each cluster + DC + update + update codes:'));

disp([sprintf('\t'), sprintf('%d;

',bits)]);

 

 

bpp = sum(bits / (size(im_orig,1)

* size(im_orig,2)));

filesize=%.0f

disp(sprintf('Result:

PSNR=%.3f,

BPP=%.3f,

bytes',psnr,bpp,sum(bits)/8)); res{k} = {psnr,bits,bpp};

end

- 54-

Файл quant_mtx.m

function res = quant_mtx(q)

Q =

[ % Pennebaker mtx

24

40

51

61,

16

11

10

16

12

12

14

19

26

58

60

55,

14

13

16

24

40

57

69

56,

14

17

22

29

51

87

80

62,

18

22

37

56

68

109

103

77,

24

35

55

64

81

104

113

92,

49

64

78

87

103

121

120

101,

72

92

95

98

112

100

103

99,

];

 

 

 

 

 

 

 

Q = reshape(Q',1,64);

res = zeros(length(q),64); for i=1:length(q)

res(i,:) = q(i) * Q;

end

Файл gtr.c

#include <mex.h> #include <math.h> #include <memory.h> #include <float.h>

// Доступ к матрице по-матлабовски

 

 

 

 

#define array(a,i,j,Lrow) (a[j + i * Lrow])

 

компонент

кодируемого

#define BLKSIZE

64

//

максимальное число

вектора

256

// число различных проквантованных компонент

//#define NU_SIZE

#define MAX_SCALAR_QUANTIZERS

8

//число

различных

матриц

скалярного

квантования

/*

Алгоритм адаптивного векторного квантования GTR (Generalized Threshold Replenishment) [Fowler, 1997], с небольшими изменениями. Ищет векторы в кодовой книге book длины Lmax с наименьшим СКО от исходных К-компонентных векторов train и наименьшими битовыми затратами R (баланс задается с помошью lambda).

В соответствии с алгоритмом GTR, при выполнении условия J_вект. > J_непоср., по каналу связи передается непосредственно проквантованный (с помощью вектора Q) вектор, заносящийся в кодовую книгу. В этом случае в выходной поток индексов записывается число 0.

Изначально в кодовой книге используются только первые L векторов, затем их число может вырасти до Lmax.

Длина массива R должна быть равна Lmax, из них первые L элементов - проинициализированы.

tau - величина, близкая к 1, tau < 1 - коэффициент "устаревания" векторов кодовой книги в выходном потоке.Другими словами, c помощью tau учитывается не только частота появления вектора, но и то, насколько давно он встретился в последний раз.

Результат (индексы 1..L) в массиве Imin из M чисел.

Return Value: количество добавленных в кодовую книгу векторов. Добавленные вектора

записаны в массиве update. Если книга разрослась до Lmax векторов, то дальнейшее кодирование будет только векторным.

Jvalue - выходное суммарное значение функции J по всем векторам

*/

int min_ind(double *data,int length);

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]); __inline int best_quantizer(double *train,int itrain,int *V,double *Q,int

Qlen,int K,double *Jscalar,

- 55-

double

lambda,double *nu, int nu_len, double sum_nu);

 

int GTR(double *book,double *train,double *update,double *iquant,int L,

 

int

Lmax,int

M,int

K,double

lambda,double

*R,double

*Jvalue,double *Imin,

 

 

 

 

 

{

double tau,double *Q, int Qlen, double *nu, int nu_len)

 

i,j,k;

 

 

 

 

 

int

 

 

 

 

 

double

J, Jscalar, sumR, *Rtau, sum_nu;

 

 

double

tmp,vmin;

 

 

 

 

int

V[BLKSIZE];

 

 

 

 

int

imin, iqscalar, effL, upd_ind, upd_cnt;

 

 

lambda

/= log(2.0);

 

 

 

 

Rtau =

(double *)mxMalloc(Lmax*sizeof(double));

 

 

memcpy(Rtau,R,Lmax*sizeof(double));

 

 

 

effL =

L;

 

 

 

 

 

sumR =

0.0;

 

 

 

 

 

for (j

= 0; j < effL; j++)

 

 

 

 

sumR += R[j];

 

 

 

 

sum_nu

= 0.0;

 

 

 

 

 

for (j

= 0; j < nu_len; j++)

 

 

 

 

sum_nu += nu[j];

 

 

 

 

//printf("Sum_nu=%.3f, len=%d,center=%.3f\n",sum_nu,nu_len,nu[nu_len/2]);

upd_cnt = 0;

 

 

 

 

 

for (i

= 0; i < M; i++) {

 

 

 

 

//Оцениваем функцию J для векторного квантования и

//находим вектор кодовой книги, минимизирующий J vmin = DBL_MAX;

imin = 0;

for (j = 0; j < effL; j++) { J = 0;

for (k = 0; k < K; k++) {

tmp = array(train,i,k,K) - array(book,j,k,K); J += tmp * tmp;

}

J = sqrt(J) - lambda * log(R[j]/sumR); if (J < vmin) {

vmin = J; imin = j;

}

}

//Оцениваем функцию J для непосредственного квантования

iqscalar = best_quantizer(train,i,V,Q,Qlen,K,&Jscalar,lambda,nu,nu_len,sum_nu);

//printf("vect=%f sc=%f\n",vmin,Jscalar);

// Сравнение непосредственного и векторного квантования if (Jscalar < vmin) { // Кодируем непосредственно

if (effL < Lmax) upd_ind = effL++;

else

upd_ind = min_ind(Rtau,effL);

for (j = 0; j < K; j++) { nu[V[j] + (nu_len >> 1)]++; tmp = (double)V[j];

array(book,upd_ind,j,K) = tmp * array(Q,iqscalar,j,K); array(update,upd_cnt,j,K) = tmp;

//printf("%d ",V[j]);

}

- 56-

iquant[upd_cnt] = (double)(iqscalar + 1); //+1 for matlab

indexation

//printf("\n imin=%d Jsc=%f Jvec=%f\n",iqscalar,Jscalar,vmin);

sumR -= R[upd_ind] - 1; R[upd_ind] = 1; Rtau[upd_ind] = 1; sum_nu += K;

Jvalue[i] = Jscalar;

Imin[i] = 0; upd_cnt++;

}

else { // Кодируем векторно

Jvalue[i] = vmin; R[imin] += 1.0; Rtau[imin] += 1.0; sumR++;

Imin[i] = imin + 1;

}

for (j = 0; j < effL; j++) Rtau[j] = Rtau[j] * tau;

}

 

 

 

 

mxFree(Rtau);

 

 

 

return upd_cnt;

 

 

 

}

 

 

 

 

// call from Matlab like this:

J,

new_book]

=

//

[Jvalue,

gtr(initial_codebook',encode_seq',initial_R,lambda,int32(L),tau,Q,nu_update)

 

void mexFunction(int nlhs, mxArray *plhs[],

 

 

{

int nrhs, const mxArray *prhs[])

 

 

*book, *train, *update, *R, lambda, *final_update,

 

double

 

*iquant, *final_iquant, tau, *Q, *nu;

double *Jvalue, *Imin;

int L,Lmax,M,K,Qlen,update_len,quantizers; mxArray *upMtx, *quant_ind;

int nu_len;

book = (double *)mxGetPr(prhs[0]); train = (double *)mxGetPr(prhs[1]); R = (double *)mxGetPr(prhs[2]);

lambda = (double)mxGetScalar(prhs[3]); L = (int)mxGetScalar(prhs[4]);

tau = (double)mxGetScalar(prhs[5]); Q = (double *)mxGetPr(prhs[6]);

nu = (double *)mxGetPr(prhs[7]);

K = mxGetM(prhs[0]); //количество компонент векторов //all transposed! Qlen = mxGetN(prhs[6]);

Lmax = mxGetN(prhs[0]);

M = mxGetN(prhs[1]); //количество векторов, подлежащих кодированию quantizers = mxGetM(prhs[7]);

nu_len = mxGetN(prhs[7]);

plhs[0] = mxCreateDoubleMatrix(1, M, mxREAL); plhs[1] = mxCreateDoubleMatrix(1, M, mxREAL);

Jvalue = (double *)mxGetPr(plhs[0]);

Imin = (double *)mxGetPr(plhs[1]);

upMtx = mxCreateDoubleMatrix(K,M, mxREAL);

- 57-

update = (double *)mxGetPr(upMtx);

quant_ind = mxCreateDoubleMatrix(1,M, mxREAL); iquant = (double *)mxGetPr(quant_ind);

// Do all

update_len = GTR(book,train,update,iquant,L,Lmax,M,K,lambda,R,Jvalue,Imin,tau,Q,Qlen,nu,nu_len)

;

//printf("L=%d,tau=%.3f,lambda=%.3f,upd_len=%d\n",L,tau,lambda,update_len);

plhs[2] = mxCreateDoubleMatrix(K,update_len, mxREAL); final_update = mxGetPr(plhs[2]);

plhs[3] = mxCreateDoubleMatrix(1, update_len, mxREAL); final_iquant = mxGetPr(plhs[3]);

memcpy(final_update,update,K*update_len*sizeof(double)); memcpy(final_iquant,iquant,update_len*sizeof(double));

mxDestroyArray(upMtx); mxDestroyArray(quant_ind);

return;

}

void main(int argc, char **argv)

{

// RD_opt(book,train,2,3,4,0.3, R, Dcum,Imin);

}

__inline int min_ind(double *data,int length)

{

int i, imin = -50; double vmin = DBL_MAX;

for (i = 0; i < length; i++) { if (data[i] < vmin) {

vmin = data[i]; imin = i;

}

}

return imin;

}

__inline int best_quantizer(double *train,int itrain,int *V,double *Q,int Qlen,int K,double *Jscalar,

double lambda,double *nu, int nu_len, double sum_nu)

{

int i,j;

double tmp, vmin, Rscalar,Jtmp[MAX_SCALAR_QUANTIZERS]; int Vtmp[MAX_SCALAR_QUANTIZERS][BLKSIZE];

int imin;

vmin = DBL_MAX;

for (i = 0; i < Qlen; i++) { Jtmp[i] = 0.0;

Rscalar = 0.0;

for (j = 0; j < K; j++) {

Vtmp[i][j] = (int)(array(train,itrain,j,K) / array(Q,i,j,K) +

0.5);

tmp = array(train,itrain,j,K) - ((double)Vtmp[i][j]) *

array(Q,i,j,K);

- 58-

Jtmp[i] += tmp * tmp;

Rscalar -= log(nu[Vtmp[i][j] + (nu_len >> 1)] / sum_nu);

}

Jtmp[i] = sqrt(Jtmp[i]) + lambda * Rscalar;

}

imin = min_ind(Jtmp,Qlen); for (i = 0; i < K; i++) {

V[i] = Vtmp[imin][i];

}

*Jscalar = Jtmp[imin]; return imin;

}

Соседние файлы в папке llama