ilikecats
ilikecats

Reputation: 319

Simplifying an image in matlab

I have a picture of a handwritten letter (say the letter, "y"). Keeping only the first of the three color values (since it is a grayscale image), I get a 111x81 matrix which I call aLetter. I can see this image (please ignore the title) using:

colormap gray; image(aLetter,'CDataMapping','scaled')

Picture of handwritten letter

What I want is to remove the white space around this letter and somehow average the remaining pixels so that I have an 8x8 matrix (let's call it simpleALetter). Now if I use:

colormap gray; image(simpleALetter,'CDataMapping','scaled')

I should see a pixellated version of the letter:

pixellated version of the handwritten letter

Any advice on how to do this would be greatly appreciated!

Upvotes: 0

Views: 247

Answers (1)

Floris
Floris

Reputation: 46415

You need several steps to achieve what you want (updated in the light of @rwong's observation that I had white and black flipped…):

  1. Find the approximate 'bounding box' of the letter:
    • make sure that "text" is the highest value in the image
    • set things that are "not text" to zero - anything below a threshold
    • sum along row and column, find non-zero pixels
  2. upsample the image in the bounding box to a multiple of 8
  3. downsample to 8x8

Here is how you might do that with your situation

aLetter = max(aLetter(:)) - aLetter; % invert image: now white = close to zero
aLetter = aLetter - min(aLetter(:)); % make the smallest value zero
maxA = max(aLetter(:));
aLetter(aLetter < 0.1 * maxA) = 0; % thresholding; play with this to set "white" to zero

% find the bounding box:
rowsum = sum(aLetter, 1);
colsum = sum(aLetter, 2);
nonzeroH = find(rowsum);
nonzeroV = find(colsum);
smallerLetter = aLetter(nonzeroV(1):nonzeroV(end), nonzeroH(1):nonzeroH(end));

% now we have the box, but it's not 8x8 yet. Resampling:
sz = size(smallerLetter);

% first upsample in both X and Y by a factor 8:
bigLetter = repmat(reshape(smallerLetter, [1 sz(1) 1 sz(2)]), [8 1 8 1]);
% then reshape and sum so you end up with 8x8 in the final matrix:
letter8 = squeeze(sum(sum(reshape(bigLetter, [sz(1) 8 sz(2) 8]), 3), 1));

% finally, flip it back "the right way" black is black and white is white:
letter8 = 255 - (letter8 * 255 / max(letter8(:)));

You can do this with explicit for loops but it would be much slower.

You can also use some of the blockproc functions in Matlab but I am using Freemat tonight and it doesn't have those… Neither does it have any image processing toolbox functions, so this is "hard core".

As for picking a good threshold: if you know that > 90% of your image is "white", you could determine the correct threshold by sorting the pixels and finding the threshold dynamically - as I mentioned in my comment in the code "play with it" until you find something that works in your situation.

Upvotes: 1

Related Questions