0

I'm using the function DrawFormattedText to present text in Psychtoolbox. I'm wondering how I could count the number of pixels produced by the text from this function.

A minimal example looks like this (you should be able to copy/paste this):

[w, wRect]=Screen('OpenWindow', 0, [0 128 128],[],[],[],[],128);
Screen('TextFont',w, 'Arial'); %Set font
Screen('TextSize',w, 16); %Set text size
[nx, ny, bbox] = DrawFormattedText(w, 'HowManyPixelsDoIHave?', 'center', 'center', 60);
Screen('Flip',w);
KbWait; %Wait for response before closing
Screen('CloseAll');

In this example I want to find out how many pixels are used to write the text "HowManyPixelsDoIHave?" I need a metric to compare various printed text strings.

I don't seem to have a grasp on how to access the content produced by the DrawFormattedText function.

A matrix of the entire screen and its pixel values would be sufficient. If anyone would know how to narrow it down to specific regions of the screen, this would be greatly appreciated.

Thanks for any help you might be able to provide!

KerrBer
  • 129
  • 11

2 Answers2

0

Extracting the pixels is actually relay easy.I'm not sure if you want the information ho many space is needed for the text do display, or you want the information for example how many black pixels does the letter B contain.

Version 1 - how much space do I need

All the information is stored in the bbox variable. bbox contains the the points which define the rectangle in which the Text is printed.

You can get those values by typing bbox in your command line. The output should look like this:

>> bbox
bbox =

   1592    517   1770    533

The individual values you can get by:

bbox(1) % x left
bbox(2) % y top
bbox(3) % x right
bbox(4) % y botom

so here's the code for your problem

 [w, wRect]=Screen('OpenWindow', 0, [0 128 128],[],[],[],[],128);
Screen('TextFont',w, 'Arial'); %Set font
Screen('TextSize',w, 16); %Set text size
[nx, ny, bbox] = DrawFormattedText(w, 'HowManyPixelsDoIHave?', 'center', 'center', 60);
Screen('Flip',w);
KbWait; %Wait for response before closing
Screen('CloseAll');

pixelWidth  =  bbox(3) - bbox(1) %x
pixelHeight = bbox(4) - bbox(2) %y

pixelWidth contains the number of pixels needed to print the whole text (including white space) for your x-axis. pixelHeight does the same for your y-axis.

I think you should have a look at some matlab/octave basics, the accessing a specific element of a vector is easy to learn and super important.

Version 2 - how many black pixels are needed for letter B

There is a function called Screen('GetImage', that saves your current screen to a variable. For this propose we create a window that is 100 * 100 px big. so if we save our window we get a 100*100*3 image as a variable. *3 tell us that there are three layers of that image that are the R the G and the B value of a RGB color space. RGB has values from 0 to 255.

What we do is we open a window with black [0 0 0] background and write on that screen with a slightly brighter black [1 1 1]. When we save the window now with Screen('GetImage', you get something like this for the first layer image(:,:,1):

  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  1  1  1  1  1  1  1  0  0  0  0
  0  0  0  1  0  0  0  0  0  0  1  0  0  0
  0  0  0  1  0  0  0  0  0  0  0  1  0  0
  0  0  0  1  0  0  0  0  0  0  0  1  0  0
  0  0  0  1  0  0  0  0  0  0  1  0  0  0
  0  0  0  1  1  1  1  1  1  1  1  0  0  0
  0  0  0  1  0  0  0  0  0  0  1  0  0  0
  0  0  0  1  0  0  0  0  0  0  0  1  0  0
  0  0  0  1  0  0  0  0  0  0  0  1  0  0
  0  0  0  1  0  0  0  0  0  0  0  1  0  0
  0  0  0  1  0  0  0  0  0  0  1  0  0  0
  0  0  0  1  1  1  1  1  1  1  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0

Just sum that up 2 times and you know how many pixels are contained.

WINDOWSIZE = [100 100 200 200]
[w, wRect]=Screen('OpenWindow', 0, [0 0 0] ,WINDOWSIZE );

Screen('TextFont', w, 'Arial'); %Set font
Screen('TextSize',  w, 16); %Set text size
Screen('TextColor', w  ,[1 1 1]); % rgb for the textfont displays 1

[nx, ny, bbox] = DrawFormattedText(w, 'Ban', 'center', 'center' );
Screen('Flip',w);
ban = Screen('GetImage', w);
KbWait; %Wait for response before closing
[nx, ny, bbox] = DrawFormattedText(w, 'San', 'center', 'center' );
Screen('Flip',w);
san = Screen('GetImage', w);
KbWait; %Wait for response before closing
Screen('CloseAll');

pixelsum_san= sum(sum(san(:,:,1)))
pixelsum_ban =sum(sum(ban(:,:,1)))

Here's the result:

pixelsum_san =  79
pixelsum_ban =  90
wuschLOR
  • 155
  • 1
  • 6
  • Thank you for taking the time to answer! Unless I haven't understood correctly, bbox can provide me with the rectangular bounding box of the text. So in your example above, pixelWidth*pixelHeight would return the number of pixels in this box. This results in the same bbox size for the words "Ban" and "San". What I'm trying to do is to **count the number of pixels used in the text itself**. That is, how many pixels are used to write the characters in "Ban" as opposed to "San". Or have I misunderstood what bbox is capable of? Thanks again for your help. – KerrBer Aug 07 '15 at 09:06
0

Extrapolating from @wuschLOR 's answer:

To get the 3D array of the screen contents I use:

IM = Screen('GetImage',w);

I then subtract (absolute) the background value for each dimension from the matrix of each dimension:

bgcolour = [0, 128, 128];
for l = 1:size(IM,3)

    nobgval(l) = sum(sum(abs(double(IM(:,:,l))-bgcolour(l))));

end

Which I then sum to get a 'metric' of how different the screen contents were from the background:

pixelmetric = sum(nobgval)

I'm not sure how reliable this would be in all cases, but for comparing different words presented in the same font size, etc, I'm assuming it should work. I'd love to hear if anyone has specific criticisms of this method (or even better, better solutions!) :)

Many thanks!

KerrBer
  • 129
  • 11