1

I read this post and was naïvely trying to display a grayscale image containing 100 handwritten numbers taken randomly from a matrix in .mat format containing 5000 rows, each corresponding to a single handwritten number. I use the following code:

library(R.matlab)
data <- readMat('data.mat')
X = data$X
X = X[sample(nrow(X), size=100, replace=F),]

par(mar = rep(0, 4))
image(X, axes = FALSE, col = grey(seq(0, 1, length = 256)))

enter image description here

which didn't end up well because it turns out that every 400-element row vector in the matrix provides information for a 20 x 20 pixel image of a pixel; hence, the height and width of the individually displayed images of the individual numbers has to be set up a priori if we want to get them displayed side-by-side. And here is where my coding "skills" fall short.

I have saved the dataset here. To be clear, the image is in X object of the list in R str(data):

List of 2
 $ X: num [1:5000, 1:400] 0 0 0 0 0 0 0 0 0 0 ...
 $ y: num [1:5000, 1] 10 10 10 10 10 10 10 10 10 10 ...
 - attr(*, "header")=List of 3
  ..$ description: chr "MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Sat May 28 18:21:58 2016                                        "
  ..$ version    : chr "5"
  ..$ endian     : chr "little"

I come a bit closer to the objective if I limit myself to displaying just one row of the matrix X after building a 20 x 20 matrix with it:

X = data$X
X = X[sample(nrow(X), size = 1 ,replace=F),]
X = matrix(X, nrow = 20, byrow= T)

par(mar = rep(0, 4))
image(X, axes = FALSE, col = grey(seq(0, 1, length = 256)))

enter image description here

The code that unravels the matrix data into an image in matlab is:

function [h, display_array] = displayData(X, example_width)
%DISPLAYDATA Display 2D data in a nice grid
%   [h, display_array] = DISPLAYDATA(X, example_width) displays 2D data
%   stored in X in a nice grid. It returns the figure handle h and the 
%   displayed array if requested.

% Set example_width automatically if not passed in
if ~exist('example_width', 'var') || isempty(example_width) 
    example_width = round(sqrt(size(X, 2)));
end

% Gray Image
colormap(gray);

% Compute rows, cols
[m n] = size(X);
example_height = (n / example_width);

% Compute number of items to display
display_rows = floor(sqrt(m));
display_cols = ceil(m / display_rows);

% Between images padding
pad = 1;

% Setup blank display
display_array = - ones(pad + display_rows * (example_height + pad), ...
                       pad + display_cols * (example_width + pad));

% Copy each example into a patch on the display array
curr_ex = 1;
for j = 1:display_rows
    for i = 1:display_cols
        if curr_ex > m, 
            break; 
        end
        % Copy the patch

        % Get the max value of the patch
        max_val = max(abs(X(curr_ex, :)));
        display_array(pad + (j - 1) * (example_height + pad) + (1:example_height), ...
                      pad + (i - 1) * (example_width + pad) + (1:example_width)) = ...
                        reshape(X(curr_ex, :), example_height, example_width) / max_val;
        curr_ex = curr_ex + 1;
    end
    if curr_ex > m, 
        break; 
    end
end

% Display Image
h = imagesc(display_array, [-1 1]);

% Do not show axis
axis image off

drawnow;

end

which results in:

enter image description here

Community
  • 1
  • 1
Antoni Parellada
  • 4,253
  • 6
  • 49
  • 114

1 Answers1

1

this reshapes the matrix rows into blocks. Not guaranteed to be very efficient, but is plenty fast for a 100x400 matrix like in your example.

# get 100 random rows of X
X <- data$X
X <- X[sample(nrow(X), size=100, replace=FALSE),]

# allocate empty image matrix (200 by 200 pixels)
Z <- matrix(rep(0, length(X)), nrow=200)

# fill empty image matrix
for (row in 0:9) {
    rmin <- 1 + (row)*20
    for (col in 0:9) {
        cmin <- 1 + (col)*20
        Z[rmin:(rmin+19), cmin:(cmin+19)] <- X[row * 10 + col + 1,]
    }
}
# plot (after rotating matrix 90 degrees)
image(t(apply(Z, 2, rev)))

enter image description here

drammock
  • 2,373
  • 29
  • 40
  • Thank you. I get a very different image, though. Check the image on my edited OP. – Antoni Parellada May 29 '16 at 20:07
  • Looks like a lot of zeros. Maybe the digits in the training data are ordered... did you do the randomization step? – drammock May 30 '16 at 03:45
  • Yes, I changed the name of `X`, but I left critically the last `X` as is, bypassing the `sample()` procedure. There is a parenthesis missing at the end of your code. Please add it on. I'm taking the liberty of posting the resulting image - you can leave it, or erase it when you insert the last parenthesis. – Antoni Parellada May 30 '16 at 14:21