Problema Matlab[URGENTE]

Darèios89
Sto facendo un progetto in Matlab, il testo è questo:

http://www.dmi.unict.it/~fstanco/lezioni_IEM_2007_2008/progetto_170211.pdf

Ho creato una funzione Bitplane:

function[B]=bitplane(I)

%A=rgb2gray(I);
A=I;
[m,n]=size(A);
B=zeros(m,n,8);
%figure,imshow(A);
D=[1 2 4 8 16 32 64 128];

for i=1:m
    for j=1:n 
        for h=1:8
          s=rem(round (A(i,j)/D(h)),2);%calcolo la divisione intera del colore diviso 2^n e del risultato ne calcolo il modulo diviso 2
           if(s==0)
            B(i,j,h)=1;
           end
        end
    end
end


E poi il programma vero e proprio, trascurate quello scritto tra %

clear all;
close all;


%inserimento numeri
nr=input('Digita un numero compreso tra 0 e 8: ');
ng=input('Digita un numero compreso tra 0 e 8: ');
nb=input('Digita un numero compreso tra 0 e 8: ');

%lettura immagine
I=imread('lena.jpg');
[m,n,t]=size(I);
R=I(:,:,1);      %memorizzo 3 canali
G=I(:,:,2);
B=I(:,:,3);

 
Rbit=bitplane(R);    %bitplane per ogni canale
Gbit=bitplane(G);
Bbit=bitplane(B);
    
Rnuova=zeros(m,n,8);   %creo delle matrici oer memorizzare i piani che mi servono
Gnuova=zeros(m,n,8);
Bnuova=zeros(m,n,8);

 for i=nr+1:8                     %dal piano che mi interessa fino all' ottavo
     Rnuova(:,:,i)=Rbit(:,:,i);   %memorizza
 end

 for i=nr+1:8
     Gnuova(:,:,i)=Gbit(:,:,i);
 end
 
 for i=nr+1:8
     Bnuova(:,:,i)=Bbit(:,:,i);
 end

%Rnuova=Rbit;
%Gnuova=Gbit;
%Bnuova=Bbit;

%figure,imshow(Rnuova(:,:,1));
%figure,imshow(Gnuova(:,:,1));
%figure,imshow(Bnuova(:,:,1));

%CALCOLO IL RISPARMIO IN MEMORIA

pixel=m*n;                   %primo costo
costo1=24*pixel;

bitr=8-nr;
bitg=8-ng; 
bitb=8-nb;

costo2=pixel*bitr+pixel*bitg+pixel*bitb;      %secondo costo

risparmio_bit=costo1-costo2;




II=zeros(m,n);
III=zeros(m,n);
IIII=zeros(m,n);

%for i=1:m
 %   for j=1:n
  %      A(i,j)=bi2de([Rnuova(i,j,1) Rnuova(i,j,2) Rnuova(i,j,3) Rnuova(i,j,4) Rnuova(i,j,5) Rnuova(i,j,6) Rnuova(i,j,7) Rnuova(i,j,8)]);
   %     B(i,j)=bi2de([Gnuova(i,j,1) Gnuova(i,j,2) Gnuova(i,j,3) Gnuova(i,j,4) Gnuova(i,j,5) Gnuova(i,j,6) Gnuova(i,j,7) Gnuova(i,j,8)]);
    %    C(i,j)=bi2de([Bnuova(i,j,1) Bnuova(i,j,2) Bnuova(i,j,3) Bnuova(i,j,4) Bnuova(i,j,5) Bnuova(i,j,6) Bnuova(i,j,7) Bnuova(i,j,8)]);
    %end
%end


 
 for i=1:m                        %qui prendo i valori di ogni riga in binario e li metto
     for j=1: n                    %in un vettore dopo li converto in decimali e li inserisco in un pixel
         vett=zeros(8);
         for k=1:8
             vett1(k)=Rnuova(i,j,k);
             vett2(k)=Gnuova(i,j,k);
             vett3(k)=Bnuova(i,j,k);
         end
         bi2de(vett1);
         II(i,j)=bi2de(vett1);
         III(i,j)=bi2de(vett2);
         IIII(i,j)=bi2de(vett3);
     end
 end    
 
 %II=Rnuova(:,:,1)+Rnuova(:,:,2)+Rnuova(:,:,3)+Rnuova(:,:,4)+Rnuova(:,:,5)+Rnuova(:,:,6)+Rnuova(:,:,7)+Rnuova(:,:,8);
 %III=Gnuova(:,:,1)+Gnuova(:,:,2)+Gnuova(:,:,3)+Gnuova(:,:,4)+Gnuova(:,:,5)+Gnuova(:,:,6)+Gnuova(:,:,7)+Gnuova(:,:,8);
 %IIII=Bnuova(:,:,1)+Bnuova(:,:,2)+Bnuova(:,:,3)+Bnuova(:,:,4)+Bnuova(:,:,5)+Bnuova(:,:,6)+Bnuova(:,:,7)+Bnuova(:,:,8);

 
 
 
Z(:,:,1)=II;
Z(:,:,2)=III;
Z(:,:,3)=IIII;
%figure, 
%subplot(1,4,1),imshow(uint8(II), []);
%subplot(1,4,2),imshow(uint8(III), []);
%subplot(1,4,3),imshow(uint8(IIII), []);
%subplot(1,4,4),imshow(uint8(Z), []);

imwrite(Z,'Compressa.jpg','jpg');
PSNR=psnr(double(I),Z);
figure,imshow(uint8(Z),[]);


Ho un problema perchè così facendo l' immagine Z non risulta corretta, cioè se ad esempio non elimino piani di bit dovrei ottenere la stessa immagine, invece non coincide con quella di partenza, secondo voi c' è qualche errore?
E' molto importante, grazie.

Risposte
apatriarca
for i=nr+1:8                     %dal piano che mi interessa fino all' ottavo 
     Rnuova(:,:,i)=Rbit(:,:,i);   %memorizza 
 end 

 for i=nr+1:8 
     Gnuova(:,:,i)=Gbit(:,:,i); 
 end 
  
 for i=nr+1:8 
     Bnuova(:,:,i)=Bbit(:,:,i); 
 end

Qui usi 3 volte nr, suppongo che sia un errore.

PSNR=psnr(double(I),Z);

Come mai hai passato I come matrice di double? Di che tipo erano prima di essere passati a psnr?

s = rem(round(A(i,j)/D(h)), 2);%calcolo la divisione intera del colore diviso 2^n e del risultato ne calcolo il modulo diviso 2 
if(s==0) 
    B(i,j,h)=1; 
end

Perché usi round? È il troncamento il metodo corretto per ottenere le cifre decimali di un numero. E in ogni caso è a mio parere migliore lavorare direttamente sui bit usando bitget o sporcandosi un po' più le mani con bitand e bitshift. Cioè
function [B] = bitplane(I) 

[m, n] = size(I);

B = zeros(m, n, 8);
 
D = [1 2 4 8 16 32 64 128]; 

for i = 1:m 
    for j = 1:n 
        for h=1:8 
          B(i, j, h) = bitshift(bitand(I(i, j), D(h)), 1 - h);
        end 
    end 
end

Direi che non può dirti niente per l'uso di questo genere di funzioni. Non implementano alcuna logica particolare. Il modo più semplice sarebbe
function [B] = bitplane(I) 

[m, n] = size(I);

B = zeros(m, n, 8);

for i = 1:m 
    for j = 1:n
        B(i, j, :) = bitget(I(i, j), 1:8);
    end 
end

Questo potrebbe servirti come funzione di controllo (verificare se gli altri codici funzionano correttamente) Si potrebbe anche scrivere tutto senza cicli (immagino).

Darèios89
Allora ricopio i codici, psnr, bitplane e main vero e proprio, tutte le funzione prendono le immagini in input normalmente senza effettuare conversioni, nell' usare il psnr, non so perchè ma devo convertire a double:

Ho corretto quelle sviste che mi avevi fatto notare, però continuo a non capire perchè l' immagine che qui chiamo RICOMPOSTA si vede male.

PSNR (abbiamo detto va bene)
function [PSNR,MSE] =psnr(A,Interpolata)
[m,n]=size(A);
MSE=0;

for x=1: m
    for y=1: n
        MSE=MSE+(A(x,y)-Interpolata(x,y)).^2;  
    end
end


MSE=MSE/(m*n);

 PSNR=10*log10((255^2)/MSE);
end


BITPLANE:

function[B]=bitplane(I)
 A=I;
 [m,n]=size(A);
 B=zeros(m,n,8);     
 

  for i=1:m
     for j=1:n 
         for h=1:8
             numero=A(i,j);       %memorizzo il valore
              cont=0;
             
             while(cont<h)              %continuo a dividere finchè non ottengo il bit corrispondente al piano h
                 resto=mod(numero,2);   %il resto conterrà il valore binario
                     cont=cont+1;
                        numero=numero/2;  %memorizzo il successivo numero da dividere
                     
             end
             
             if resto==1
                 B(i,j,h)=1;
             end
         end
     end
  end
  
end

             


clear all;
close all;


%inserimento numeri da tastiera
nr=input('Inserisci un numero tra 0 e 8: ');
ng=input('Inserisci un numero tra 0 e 8: ');
nb=input('Inserisci un numero tra 0 e 8: ');

%lettura immagine
I=imread('lena.jpg');
[m,n,t]=size(I);
R=I(:,:,1);      %memorizzo i 3 canali separatamente
G=I(:,:,2);
B=I(:,:,3);

 
Rbit=bitplane(R);    %bitplane per ogni canale
Gbit=bitplane(G);
Bbit=bitplane(B);
    
Rnuova=zeros(m,n,8);   %creo delle matrici per memorizzare i piani che mi servono per ogni canale
Gnuova=zeros(m,n,8);
Bnuova=zeros(m,n,8);

 for i=nr+1:8                     %da nr+1(piano che mi interessa)fino all' ottavo
     Rnuova(:,:,i)=Rbit(:,:,i);   %memorizza i piani nelle nuove matrici
 end

 for i=ng+1:8
     Gnuova(:,:,i)=Gbit(:,:,i);
 end
 
 for i=nb+1:8
     Bnuova(:,:,i)=Bbit(:,:,i);
 end



%CALCOLO IL RISPARMIO IN MEMORIA
pixel=m*n;                                     %primo costo
costo1=24*pixel;                               %avremo 3 canali cioè 8 bit ciascuno, quindi 24 moltiplicati per il numero di pixel

bitr=8-nr;    %Ho tolto dei piani, quindi ho dei bit in meno per ogni canale
bitg=8-ng; 
bitb=8-nb;

costo2=pixel*bitr+pixel*bitg+pixel*bitb;      %secondo costo

risparmio_bit=costo1-costo2;                  %ecco il risparmio



%RICOSTRUZIONE IMMAGINE
II=zeros(m,n);          
III=zeros(m,n);
IV=zeros(m,n);


 for i=1:m                        %qui prendo i valori di ogni riga in binario e li metto
    for j=1: n                    %in un vettore, dopo li converto in decimali e li inserisco nel corrispondente pixel
         for k=1:8
             vett1(k)=Rnuova(i,j,k);   %conterrà tutto il codice binario
             vett2(k)=Gnuova(i,j,k);
             vett3(k)=Bnuova(i,j,k);
         end
       II(i,j)=bi2de(vett1);       %converto ed assegno il valore decimale
       III(i,j)=bi2de(vett2);
       IV(i,j)=bi2de(vett3);
     end
 end    
 
RICOMPOSTA(:,:,1)=II;
RICOMPOSTA(:,:,2)=III;
RICOMPOSTA(:,:,3)=IV;

%STAMPE 
risparmio_bit

%SALVATAGGIO IN MEMORIA DELL' IMMAGINE COMPRESSA
imwrite(RICOMPOSTA,'Compressa.jpg','jpg');

%STAMPA
figure,imshow(RICOMPOSTA,[]),title('COMPRESSA');


%Stampa
PSNR=psnr(double(I),double(RICOMPOSTA))


apatriarca
Hai provato ad utilizzare le operazioni bitwise come ti ho consigliato? Come appare l'immagine? Hai provato a visualizzarla per cui dovresti essere in grado di dire che cosa non c'è che non va.

Darèios89
Ho già dovuto inviare il progetto......ti ringrazio comunque...:)

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.