You are on page 1of 5

Reading and displaying images

Matlab can read PNG files and other formats without help. Here is how to read a PNG image into memory and look at the pixel values in its upper left corner. The ">>" is the Matlab prompt. Comments begin with a % sign.
>> help imread % Online help is useful... IMREAD Read image from graphics file. A = IMREAD(FILENAME,FMT) reads the image in FILENAME into A. If the file contains a grayscale intensity image, A is a two-dimensional array. If the file contains a truecolor etc... >> I = imread('test.png'); >> size(I) ans = 320 240 % Display row 1-10 and col 1-10 of I % Read image test.png into variable I % Get the number of rows and columns of I

>> I(1:10,1:10) ans = 26 26 25 25 24 20 20 20 20 21 20 24 24 21 20 19 20 20 19 17 20 19 22 21 22 22 21 21 22 21 22 22 24 24 25 22 25 24 24 25 22 22 21 22 22 24 25 26 24 21

20 19 19 20 19 21 24 25 25 22

19 21 20 21 20 21 24 25 24 24

20 24 22 22 21 24 25 25 24 25

22 24 24 24 25 22 20 20 22 22

22 22 22 20 24 24 20 20 21 21

>> colormap(gray(256)); >> image(I); >> daspect([1 1 1]);

% Use a 256-value grayscale color map % Display I as an image % Set x:y aspect ratio to be 1:1

If you like the PGM format like I do, here are matlab functions for reading and writing them:
y y

readpgm.m writepgm.m

Getting your training set into one big matrix


Matlab is really nice for linear algebra stuff and visualization, but sorta sucks when it comes to file I/O. Or rather, it's not much easier than C, although there are functions for reading and writing entire arrays to and from files. The following function, defined in load_images.m, is an

example of how to read a bunch of images, make column vectors out of each of them, and return the result.
function [Images,w,h] = load_images(filelist,downscale_f) %LOAD_IMAGES Load a set of images listed in a file. % % [IMGS,W,H] = LOAD_IMAGES(FILELIST) Treat each line of % the file named FILELIST as the filename of a PGM image, % and load each image as one column of the return array % IMGS. % % LOAD_IMAGES(FILELIST,DOWNSCALE_F) Do the same thing, % but downscale each image's width and height by a factor % of DOWNSCALE_F. Useful if the images are too big to be % loaded into memory all at once. % Matthew Dailey 2000 % Check argument consistency if nargin < 1 | nargin > 2 error('usage: load_images(filelist[,downscale_f]'); end; if nargin == 1 downscale_f = 1.0; end; Images = []; old_w = 0; old_h = 0; w=0; h=0; % Open input file numimgs = linecount(filelist); fid = fopen(filelist,'r'); if fid < 0 | numimgs < 1 error(['Cannot get list of images from file "' filelist, '"']); end; % Get the images for i = 1:numimgs imgname = fgetl(fid); if ~isstr(imgname) % EOF is not a string break; % Exit from loop on EOF end; fprintf(1,'loading PGM file %s\n',imgname); Img = readpgm(imgname); % Read this image as a 2D array if i==1 % If this is first image, figure things out old_w = size(Img,2); % - like sizes of the downscaled images old_h = size(Img,1); if downscale_f <= 1.0 w = old_w; h = old_h; else w = round(old_w/downscale_f); h = round(old_h/downscale_f); end; Images = zeros(w*h,numimgs); % - preallocate size of the return matrix end;

if downscale_f > 1.0 Img = im_resize(Img,w,h); % downscale using bicubic spline interp end; Images(1:w*h,i) = reshape(Img',w*h,1); % Make a column vector end; fclose(fid); % Close the filelist when done fprintf(1,'Read %d images.\n',numimgs); % The function returns the output arguments Images, w, and h here.

The function has a downscaling factor that lets you save memory. To use the function, just create a file listing your images then run:
>> [Imgs,w,h] = load_images('facelist',4);

The im_resize function uses Matlab's built in 2-D function interpolation (using bicubic splines) to resize the image by the desired downscaling factor. If you want to run load_images, you also need the trivial little function linecount. Here is how you would convert a column of Imgs back into an image and display it:
>> >> >> >> >> L = Imgs(:,10); L = reshape(L,w,h)'; image(L); colormap(gray(256)); daspect([1 1 1]); % Reshapes column vector into a 2D array

Getting the principal component eigenvectors of the training set


The function pc_evectors uses Turk and Pentland's trick to get the eigenvectors of A*A' from the eigenvectors of A'*A. It uses the function sortem to sort the eigenvectors and eigenvalues by eigenvalue. [Here is a faster version, sortem2, by James Javurek-Humig, which is considerably faster, if you have matlab version 7 or better.] To use pc_evectors, just do:
>> [Vecs,Vals,Psi] = pc_evectors(Imgs,30); % Get top 30 PC evectors of Imgs

And to explore the eigenvalue spectrum and how much variance the first n vectors account for, try the following:
>> >> >> >> plot(Vals); % CVals = zeros(1,length(Vals)); % CVals(1) = Vals(1); for i = 2:length(Vals) % CVals(i) = CVals(i-1) + Vals(i); end; >> CVals = CVals / sum(Vals); % >> plot(CVals); % >> ylim([0 1]); % To plot the eigenvalues Allocate a vector same length as Vals Accumulate the eigenvalue sum Normalize total sum to 1.0 Plot the cumulative sum Set Y-axis limits to be 0-1

This gives you something like the following:

It depends on the application, but most folks seem to use a number of eigenvectors that account for variance somewhere in the 65%-90% range.

Exploratory analysis of the eigenvectors


One thing that can be fun is to try to figure out what the top few eigenvectors encode. You can make a scatter plot of one component against another as follows:
>> Proj = Vecs(:,1:2)' * Imgs; evectors >> size(Proj) ans = 2 110 % To get scatterplot of PC 1 vs PC 2 % Project each image onto first 2

>> plot(Proj(1,:),Proj(2,:),'r.')

And if you wanted to add text labels to each of the points in the plot, you could do the following. First create a file containing the labels you want, in the correct order. Then read it into a Matlab string array:
>> Labels = textread('labels','%s'); >> text(Proj(1,:),Proj(2,:),Labels); point % Read labels from file 'labels' % Add text labels at each plotted

It is simple to display an eigenface as an image, using the built in imagesc function, which first scales the values in an array to the 0-255 range.
>> pc_ev_1 = Vecs(:,1); >> pc_ev_1 = reshape(pc_ev_1,w,h)'; % Get PC eigenvector 1 % Reshape into 2D array

>> imagesc(pc_ev_1);

% Display as image scaled 0-255

Finally, you might be interested in determining the reconstruction error involved in representing an image by its projection onto a few eigenvectors. Here is how you would project onto and reconstruct from eigenvectors 1-10.
>> OrigImg = Imgs(:,20); % Grab image 20 >> Projection = Vecs(:,1:10)'*(OrigImg - Psi); % Project onto ev's 1-10 >> Reconstruction = Vecs(:,1:10)*Projection+Psi; % Reconstruct from projection >> Reconstruction = reshape(Reconstruction,w,h)'; >> image(Reconstruction); >> colormap(gray(256)); >> daspect([1 1 1]);

You might also like