Code covered by the BSD License  

Highlights from
Quadtree decomposition (Encoding) and Decoding of RGB Image

image thumbnail
from Quadtree decomposition (Encoding) and Decoding of RGB Image by Dr. Murtaza Khan
Quadtree decomposition (Encoding) and Decoding of RGB Image of size M-by-N-by-3.

[S,valRGB]=qt3ddecom(I,varargin)
% % This method uses three thresholds for red,green and blue blocks.
% % For any R/G/B block if the maximum value of the block elements minus the
% % minimum value of the block elements is greater than its respective threshold
% % then the RGB image is splitted into 4 blocks. 

% % Thresholds are specified as a value between 0 and 1, even if I is of class uint8 or
% % uint16. If I is uint8, the threshold value you supply is multiplied by
% % 255 to determine the actual threshold to use; if I is uint16, the
% % threshold value you supply is multiplied by 65535

% % The function also pad the image if its size is not power of 2, so that
% % image can be divided until block of size 1.

% % Input
% % image I (true color) image matrix of size M-by-N-by-3.
% % thvec: threshold values of rgb b/w 0 and 1 e.g. thvec=[0.5,0.5,0.5]
% %        (this optional argument, defualt threshold is [0 0 0] i.e.
% %        lossless encoding 

% % Output
% % S: the quadtree structure in the sparse matrix S. If S(k,m) is
% %    nonzero, then (k,m) is the upper left corner (ULC) of a block in the
% %    decomposition, and the size of the block is given by S(k,m). 
% % valRGB(n,1:3):  mean (average) of RGB compoents for nth block

% % Exmaple of usage: [S,valRGB]=qt3ddecom(I,thvec);
% %                   or [S,valRGB]=qt3ddecom(I);

function [S,valRGB]=qt3ddecom(I,varargin)

% disp('RGB Image Quadtree Decomposition');
% str=sprintf('%s', '@ Copyright M Khan'); disp(str);
% disp('Email: mak2000sw@yahoo.com');
disp('---------------------------------');
% %--------------------------------------------------------------
% % Default Values 
thvec=[0 0 0];                %lossless encoding
defaultValues = {thvec};      %threshold vector
% % % Assign Values
nonemptyIdx = ~cellfun('isempty',varargin);
defaultValues(nonemptyIdx) = varargin(nonemptyIdx);
[thvec] = deal(defaultValues{:});
% %--------------------------------------------------------------
classtr=class(I);
[ir ic id]=size(I); % size of image before padding
if(id~=3)
    error('Input Matrix (Image) must be of size M-by-N-by-3 (true color)');    
end
if(~ispowerof2(ir) || ~ispowerof2(ic))
    I=padrgbtomakepowof2(I);
    % % sizeIafterPad=size(I);
    % % disp('padding is done to make input Matrix/Image power of 2');
end
[irp,icp,id]=size(I); % size of image after padding
S=zeros(irp,icp);
% %--------------------------------------------------------------
% % Matrix S is intitially of same size as input image/matrix and holds
% % zeros in all locations.
% % stru1 holds information about those images that are to be tested
% % for splitting.
% % initially we would put coordinates of ULC of image into stru1 then
% % we will execute a loop until stru1 becomes empty. 
% % Inside loop we would take coordinates of last image block from stru1
% % and remove them from stru1, then test if for splitting.
% % If it split then we would put four new blocks into stru1. If it does
% % not split then we would (ULC) of that single block into matrix S.
% % This process would continue until stru1 becomes emtpy, that means no
% % more splitting is required and we would be outside while loop. Then
% % simple we would converte matrix S into sparse matrix.

count1=1;                    % counter to save data in S
stru1(count1).rc=[1 1];      % beginning (upper left corner) coordinates of image
stru1(count1).sz=size(I,1);  % size of image (width and height are equal)
while(size(stru1,2)>=1)    
    r1=stru1(end).rc(1);
    r2=r1+stru1(end).sz-1;
    c1=stru1(end).rc(2);
    c2=c1+stru1(end).sz-1; 
    stru1(end)=[];          % remove from stru1
    count1=count1-1;
    % % splitting (return splitting coordiantes with respect to segment
    % % (block) of image (matrix)
    [b1r,b1c,b2r,b2c,b3r,b3c,b4r,b4c,sz]=qtrgbsplit(I(r1:r2,c1:c2,1:3),thvec);
    if(sz==-1) % Not splitted
        % % disp('not splitted');
        S(r1,c1)=r2-r1+1;
    else      % splitted 
        % % disp('splitted');
        %% converting local coordinates to global coordinates
        b1r=r1+b1r-1;
        b1c=c1+b1c-1;
        b2r=r1+b2r-1;
        b2c=c1+b2c-1;
        b3r=r1+b3r-1;
        b3c=c1+b3c-1;
        b4r=r1+b4r-1;
        b4c=c1+b4c-1;        
        % % adding fourth block data in stru1
        count1=count1+1;
        stru1(count1).rc=[b4r,b4c];      
        stru1(count1).sz=sz;
        % % adding third block data in stru1
        count1=count1+1;
        stru1(count1).rc=[b3r,b3c];      
        stru1(count1).sz=sz;             
        % % adding second block data in stru1
        count1=count1+1;
        stru1(count1).rc=[b2r,b2c];      
        stru1(count1).sz=sz;             
        % % adding first block data in stru1
        count1=count1+1;
        stru1(count1).rc=[b1r,b1c];      
        stru1(count1).sz=sz;
    end    
end
% %--------------------------------------------------------------
S=sparse(S); %converting S into sparse matrix
[i,j,blkSz] = find(S);
if(length(find(thvec))==0) %lossless encoding (all entries in thvec are 0)
    for k=1:length(blkSz)        
        valRGB(k,1:3)=I(i(k),j(k),1:3); % values of corresponding indices of S of RGB
    end
else             %lossy encoding
    valR=avgofmatblks(I(:,:,1),i,j,blkSz,blkSz); % mean of Red
    valG=avgofmatblks(I(:,:,2),i,j,blkSz,blkSz); % mean of Green
    valB=avgofmatblks(I(:,:,3),i,j,blkSz,blkSz); % mean of Blue
    valRGB=[valR', valG', valB'];
end
% %--------------------------------------------------------------
% % % Now Removing those rows from S and valRGB that exceed original image size(ir,ic)
% % % ir,ic,irp,icp
if (ir<irp && ic<icp)
    [S,valRGB]=delsparsekeybyxANDy(S,i,j,valRGB,ir,ic);
end
% %--------------------------------------------------------------
% % Trim S
% S=S(1:max(i),1:max(j)); %use previously computed [i,j,v]=find(S)
S=trimsparse(S);          %computes again [i,j,v]=find(S)
% %--------------------------------------------------------------
% % next stpe is to convert to same class as that of original image.
% % if original image is of type integer this operation would also round
% % off
valRGB=converttoclass(valRGB,classtr); 
% %  sizeSAfter=size(S)
% %--------------------------------------------------------------
% % % Plotting
figure, image(I)
title('\bfOriginal Padded Image');
drawquadblocks(S);
% title('\bfQuadtree blocks on Padded Image');
% %--------------------------------------------------------------


% % % --------------------------------
% % % Author: Dr. Murtaza Khan
% % % Email : drkhanmurtaza@gmail.com
% % % --------------------------------

Contact us at files@mathworks.com