I am trying to read an image, DCT transform it, quantize it, and then save the quantized coefficients to a file that will be read into a fractal encoding program.
When I decode the file (with the quantized coefficients), all I get is some grey screen. Is this due to the contents of the file or am I missing out on something else?
%% LOSSY COMPRESSION-DECOMPRESSION USNIG DISCRETE COSINE TRANSFORM TECHNIQUE.
function[]=dct11(filename,n,m)
% "filename" is the string of characters including Image name and its
% extension.
% "n" denotes the number of bits per pixel.
% "m" denotes the number of most significant bits (MSB) of DCT Coefficients.
% Matrix Intializations.
N=8; % Block size for which DCT is Computed.
M=8;
I=imread('Lenna.bmp'); % Reading the input image file and storing intensity values in 2-D matrix I.
I_dim=size(I); % Finding the dimensions of the image file.
I_Trsfrm.block=zeros(N,M); % Initialising the DCT Coefficients Structure Matrix "I_Trsfrm" with the required dimensions.
Norm_Mat=[16 11 10 16 24 40 51 61 % Normalization matrix (8 X 8) used to Normalize the DCT Matrix.
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];
save('LenaInitial.dat','I');
%% PART-1: COMPRESSION TECHNIQUE.
% Computing the Quantized & Normalized Discrete Cosine Transform.
% Y(k,l)=(2/root(NM))*c(k)*c(l)*sigma(i=0:N-1)sigma(j=0:M-1)y(i,j)cos(pi(2i+1)k/(2N))cos(pi(2j+1)l/(2M))
% where c(u)=1/root(2) if u=0
% = 1 if u>0
for a=1:I_dim(1)/N
for b=1:I_dim(2)/M
for k=1:N
for l=1:M
prod=0;
for i=1:N
for j=1:M
prod=prod+double(I(N*(a-1)+i,M*(b-1)+j))*cos(pi*(k-1)*(2*i-1)/(2*N))*cos(pi*(l-1)*(2*j-1)/(2*M));
end
end
if k==1
prod=prod*sqrt(1/N);
else
prod=prod*sqrt(2/N);
end
if l==1
prod=prod*sqrt(1/M);
else
prod=prod*sqrt(2/M);
end
I_Trsfrm(a,b).block(k,l)=prod;
end
end
% Normalizing the DCT Matrix and Quantizing the resulting values.
I_Trsfrm(a,b).block=round(I_Trsfrm(a,b).block./Norm_Mat);
% save ('LenaCompressed1.txt');
end
end
%Andrew added this
% save ('LenaCompressed.txt');
% zig-zag coding of the each 8 X 8 Block.
for a=1:I_dim(1)/N
for b=1:I_dim(2)/M
I_zigzag(a,b).block=zeros(1,0);
freq_sum=2:(N+M);
counter=1;
for i=1:length(freq_sum)
if i<=((length(freq_sum)+1)/2)
if rem(i,2)~=0
x_indices=counter:freq_sum(i)-counter;
else
x_indices=freq_sum(i)-counter:-1:counter;
end
index_len=length(x_indices);
y_indices=x_indices(index_len:-1:1); % Creating reverse of the array as "y_indices".
for p=1:index_len
if I_Trsfrm(a,b).block(x_indices(p),y_indices(p))<0
bin_eq=dec2bin(bitxor(2^n-1,abs(I_Trsfrm(a,b).block(x_indices(p),y_indices(p)))),n);
else
bin_eq=dec2bin(I_Trsfrm(a,b).block(x_indices(p),y_indices(p)),n);
end
I_zigzag(a,b).block=[I_zigzag(a,b).block,bin_eq(1:m)];
end
else
counter=counter+1;
if rem(i,2)~=0
x_indices=counter:freq_sum(i)-counter;
else
x_indices=freq_sum(i)-counter:-1:counter;
end
index_len=length(x_indices);
y_indices=x_indices(index_len:-1:1); % Creating reverse of the array as "y_indices".
for p=1:index_len
if I_Trsfrm(a,b).block(x_indices(p),y_indices(p))<0
bin_eq=dec2bin(bitxor(2^n-1,abs(I_Trsfrm(a,b).block(x_indices(p),y_indices(p)))),n);
else
bin_eq=dec2bin(I_Trsfrm(a,b).block(x_indices(p),y_indices(p)),n);
end
I_zigzag(a,b).block=[I_zigzag(a,b).block,bin_eq(1:m)];
end
end
end
end
end
% Clearing unused variables from Memory space
clear I_Trsfrm prod;
clear x_indices y_indices counter;
% Run-Length Encoding the resulting code.
for a=1:I_dim(1)/N
for b=1:I_dim(2)/M
% Computing the Count values for the corresponding symbols and
% savin them in "I_run" structure.
count=0;
run=zeros(1,0);
sym=I_zigzag(a,b).block(1);
j=1;
block_len=length(I_zigzag(a,b).block);
for i=1:block_len
if I_zigzag(a,b).block(i)==sym
count=count+1;
else
run.count(j)=count;
run.sym(j)=sym;
j=j+1;
sym=I_zigzag(a,b).block(i);
count=1;
end
if i==block_len
run.count(j)=count;
run.sym(j)=sym;
end
end
% Computing the codelength needed for the count values.
dim=length(run.count); % calculates number of symbols being encoded.
maxvalue=max(run.count); % finds the maximum count value in the count array of run structure.
codelength=log2(maxvalue)+1;
codelength=floor(codelength);
% Encoding the count values along with their symbols.
I_runcode(a,b).code=zeros(1,0);
for i=1:dim
I_runcode(a,b).code=[I_runcode(a,b).code,dec2bin(run.count(i),codelength),run.sym(i)];
end
end
end
% Saving the Compressed Code to Disk.
save ('LenaCompressed.txt','I_runcode');
% Clearing unused variables from Memory Space.
clear I_zigzag run;
Andrew, you use MATLAB's save statement to save the coefficients into a file ending with .txt. What does the "fractal encoding program" assume about the file format?
Your file will not be a text file. Check out the documentation of save. Perhaps you can use the '-ascii' flag.
Otherwise, you may have to write that file of coefficients yourself. To get you started, I'd say fprintf is worth a look.
I want to plot a heart shape wireframe as shown in the following image
(source):
I have tried to make it by using this MATLAB program:
n=100;
x=linspace(-3,3,n);
y=linspace(-3,3,n);
z=linspace(-3,3,n);
[X,Y,Z]=ndgrid(x,y,z);
F=((-(X.^2) .* (Z.^3) -(9/80).*(Y.^2).*(Z.^3)) + ((X.^2) + (9/4).* (Y.^2) + (Z.^2)-1).^3);
isosurface(F,0)
lighting phong
caxis
axis equal
colormap('flag');
view([55 34]);
But I didn't get the desired shape of framework as shown in the figure.
I have identified the problem: to create a wireframe we usually use the command mesh(). But this plotting facility only allow us to plot a function of two variables such as z=f(x,y). But my program makes use of three variables: F(x,y,z).
How can I solve the problem?
Here's my best attempt at reproducing the entire figure:
Generating the contoured heart mesh:
I used the contourc function to generate a series of contours in the x-y, x-z, and y-z planes. Notice that in the image you want to reproduce, the mesh lines on the back-facing side of the heart are not rendered. The quickest and easiest way I could think of to reproduce that aspect of the plot was to use isosurface to render a white surface just beneath the inside surface of the mesh, blocking the view of the back side.
Here's the code for the function heart:
function heart
% Initialize the volume data, figure, and axes:
[X,Y,Z] = meshgrid(linspace(-3,3,101));
F = -X.^2.*Z.^3-(9/80).*Y.^2.*Z.^3+(X.^2+(9/4).*Y.^2+Z.^2-1).^3;
hFigure = figure('Position',[200 200 400 400],'Color','w');
hAxes = axes('Parent',hFigure,'Units','pixels',...
'Position',[1 1 400 400],'NextPlot','add',...
'DataAspectRatio',[1 1 1],'Visible','off',...
'CameraViewAngle',10,...
'XLim',[32 70],'YLim',[39 63],'ZLim',[34 73]);
view([-39 30]);
% Create and plot contours in the y-z plane:
for iX = [35 38 41 45 48 51 54 57 61 64 67]
plane = reshape(F(:,iX,:),101,101);
cData = contourc(plane,[0 0]);
xData = iX.*ones(1,cData(2,1));
plot3(hAxes,xData,cData(2,2:end),cData(1,2:end),'k');
end
% Create and plot contours in the x-z plane:
for iY = [41 44 47 51 55 58 61]
plane = reshape(F(iY,:,:),101,101);
cData = contourc(plane,[0 0]);
yData = iY.*ones(1,cData(2,1));
plot3(hAxes,cData(2,2:end),yData,cData(1,2:end),'k');
end
% Create and plot contours in the x-y plane:
for iZ = [36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 69 71]
plane = F(:,:,iZ);
cData = contourc(plane,[0 0]);
startIndex = 1;
if size(cData,2) > (cData(2,1)+1)
startIndex = cData(2,1)+2;
zData = iZ.*ones(1,cData(2,1));
plot3(hAxes,cData(1,2:(startIndex-1)),...
cData(2,2:(startIndex-1)),zData,'k');
end
zData = iZ.*ones(1,cData(2,startIndex));
plot3(hAxes,cData(1,(startIndex+1):end),...
cData(2,(startIndex+1):end),zData,'k');
end
% Fill the inside of the mesh with an isosurface to
% block rendering of the back side of the heart:
p = patch(isosurface(F,-0.001));
set(p,'FaceColor','w','EdgeColor','none');
end
Putting the figure together:
To reproduce the entire figure I first generated the heart mesh using the heart function above, then added the other elements around it. I also used a few submissions from The MathWorks File Exchange:
arrow.m from Erik Johnson (to generate the arrows)
myaa.m from Anders Brun (to create a nice anti-aliased final image)
Here's the code for the function I_Heart_Math (which generates the above figure):
function I_Heart_Math
% Initialize heart plot and adjust figure and axes settings:
heart;
set(gcf,'Position',[200 200 700 300],'Name','Original image');
offset = get(gca,'CameraPosition')-get(gca,'CameraTarget');
offset = 35.*offset./norm(offset);
set(gca,'Position',[65 -9 300 300],'CameraViewAngle',6,...
'XLim',[21+offset(1) 70],'YLim',[16+offset(2) 63],...
'ZLim',[32 81+offset(3)]);
% Create the axes and labels, offsetting them in front of the
% heart to give the appearance they are passing through it:
arrowStarts = [81 51 51; 51 86 51; 51 51 32]+repmat(offset,3,1);
arrowEnds = [21 51 51; 51 16 51; 51 51 81]+repmat(offset,3,1);
arrow(arrowStarts,arrowEnds,5,40,40);
text('Position',[22 52 48]+offset,'String','x','FontSize',12);
text('Position',[50 17 49]+offset,'String','y','FontSize',12);
text('Position',[46.5 51 81.5]+offset,'String','z','FontSize',12);
% Create the equation text:
text('Position',[51 47 28],'FontName','Bookman','FontSize',8,...
'HorizontalAlignment','center',...
'String',{'(x^2+^9/_4y^2+z^2-1)^3-x^2z^3-^9/_{80}y^2z^3=0'; ...
'-3 \leq x,y,z \leq 3'});
% Create the large-type text:
hI = text('Position',[4 52 69.5],'String','I',...
'FontAngle','italic','FontName','Trebuchet MS',...
'FontSize',116,'FontWeight','bold');
hM = text('Position',[80.5 50 42.5],'String','Math',...
'FontAngle','italic','FontName','Trebuchet MS',...
'FontSize',116,'FontWeight','bold');
% Create an anti-aliased version of the figure too (the larger
% fonts need some adjustment to do this... not sure why):
set(hI,'Position',[4 52 68],'FontSize',86);
set(hM,'Position',[80.5 50 41],'FontSize',86);
myaa;
set(hI,'Position',[4 52 69.5],'FontSize',116);
set(hM,'Position',[80.5 50 42.5],'FontSize',116);
set(gcf,'Name','Anti-aliased image');
end
A very elegant solution is given by #gnovice. I though I extend it by adding the other elements to replicate the figure pointed by the OP. I also added some cool animations!
% volume data
[X,Y,Z] = meshgrid(linspace(-3,3,101));
F = -X.^2.*Z.^3 - (9/80).*Y.^2.*Z.^3 + (X.^2 + (9/4).*Y.^2 + Z.^2 - 1).^3;
% initialize figure
hFig = figure('Menubar','none', 'Color','w');
pos = get(hFig, 'Position');
set(hFig, 'Position', [pos(1)-0.15*pos(3) pos(2) 1.3*pos(3) pos(4)]);
% initialize axes
hAxes = axes('Parent',hFig, 'DataAspectRatio',[1 1 1], ...
'XLim',[30 120], 'YLim',[35 65], 'ZLim',[30 75]);
view(-39,30);
axis off
% Fill the inside of the mesh with an isosurface to
% block rendering of the back side of the heart
patch(isosurface(F,-1e-3), 'FaceColor','w', 'EdgeColor','none')
hidden on % hidden surface removal
% contours in the y-z plane
for iX = [35 38 41 45 48 51 54 57 61 64 67]
plane = reshape(F(:,iX,:), [101 101]);
cData = contourc(plane, [0 0]);
xData = iX.*ones(1,cData(2,1));
line(xData, cData(2,2:end), cData(1,2:end), ...
'Color','r', 'Parent',hAxes)
pause(.1)
end
% contours in the x-z plane
for iY = [41 44 47 51 55 58 61]
plane = reshape(F(iY,:,:), [101 101]);
cData = contourc(plane, [0 0]);
yData = iY.*ones(1,cData(2,1));
line(cData(2,2:end), yData, cData(1,2:end), ...
'Color','r', 'Parent',hAxes)
pause(.1)
end
% contours in the x-y plane
for iZ = [36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 69 71]
plane = F(:,:,iZ);
cData = contourc(plane, [0 0]);
startIndex = 1;
if size(cData,2) > (cData(2,1)+1)
startIndex = cData(2,1)+2;
zData = iZ.*ones(1,cData(2,1));
line(cData(1,2:(startIndex-1)), cData(2,2:(startIndex-1)), zData, ...
'Color','r', 'Parent',hAxes)
end
zData = iZ.*ones(1,cData(2,startIndex));
line(cData(1,(startIndex+1):end), cData(2,(startIndex+1):end), zData, ...
'Color','r', 'Parent',hAxes)
pause(.1)
end
% text
props = {'FontWeight','bold', 'FontAngle','italic', 'FontSize',100};
pause(.2)
text(7,50,70, 'I', props{:})
pause(.5)
text(80,50,43, 'Math', props{:})
pause(.2)
% xyz axes
line([20 80], [50 50], [52.5 52.5], 'Color','k')
line([50 50], [20 80], [52.5 52.5], 'Color','k')
line([50 50], [50 50], [30 80], 'Color','k')
text(20,50,50, 'x')
text(48,20,50, 'y')
text(45,50,80, 'z')
drawnow
% equation
props = {'FontSize',10, 'Interpreter','latex'};
text(20,65,30, '$(x^2+9/4y^2+z^2-1)^3 - x^2z^3-9/80y^2z^3=0$', props{:});
text(30,45,30, '$-3 \leq x,y,z \leq 3$', props{:});
drawnow
(The above GIF file was created using GETFRAME and IMWRITE).
This code plots the shaded surface:
% volume data
step = 0.05;
[X,Y,Z] = meshgrid(-3:step:3, -3:step:3, -3:step:3);
F = (-(X.^2).*(Z.^3)-(9/80).*(Y.^2).*(Z.^3))+((X.^2)+(9/4).*(Y.^2)+(Z.^2)-1).^3;
% shaded surface
isosurface(X,Y,Z,F,0)
lighting phong
axis equal
view(-39,30)
set(gcf, 'Color','w')
colormap flag
We could instead plot the wireframe only:
% volume data
step = 0.05;
[X,Y,Z] = meshgrid(-3:step:3, -3:step:3, -3:step:3);
F = (-(X.^2).*(Z.^3)-(9/80).*(Y.^2).*(Z.^3))+((X.^2)+(9/4).*(Y.^2)+(Z.^2)-1).^3;
% wireframe
patch(isosurface(X,Y,Z,F,0), 'FaceColor','w', 'EdgeColor','b')
daspect([1 1 1])
view(3)
axis tight equal
set(gcf, 'Color','w')