Gaze Interest Heat Map

27 views (last 30 days)
Chris Berry
Chris Berry on 21 Apr 2011
Edited: dim-ask on 23 Jul 2022
Hello! I am attempting to take x and y coordinates from an eye tracking study and translate them into "attention heat maps." My desired heat map should look similar to:
or:
I know the location of each gaze point, the frame rate, the time that the gaze point is created, however I cannot figure out how to turn this information into a usable format. This page is close to what I need:
except that I need to amend the code so that overlapping z values are added, instead of blended together. I.E. if z1=10 and z2=15, the resulting z value will be 25. Any help that can be given would be greatly appreciated.

Accepted Answer

Jarrod Rivituso
Jarrod Rivituso on 21 Apr 2011
It sounds like you are looking for a 2-dimensional histogram. There is none in default MATLAB, as far as I know. However, several users on the file exchange have made submissions to this point:
I believe the main idea for each is that you
  1. define x,y vectors that represent the grid of bins for the histogram
  2. then you count each entry of your data adding values to the bins,
  3. and finally you use pcolor or imagesc or something like that to make the plot.
  3 Comments
Jarrod Rivituso
Jarrod Rivituso on 22 Apr 2011
So are you trying to fit a 2-D Gaussian distribution, and then specifically plot that distribution?
The histogram approach could end up looking like a Gaussian distribution, such as this:
x = randn(1000,1) + 7;
y = randn(1000,1) + 10;
[n,c] = hist3([x y],[50,50]);
imagesc(c{1},c{2},n)
Or you could replace imagesc with surf and then rotate
surf(c{1},c{2},n,'linestyle','none')
Depending on the size of the bins you choose, the data will look finer or more coarse. In the example, I've chose a 50-by-50 grid of bins
If you are trying to truly fit a Gaussian curve to the data, then I think you would need to first determine the necessary coefficients of the distribution and then plot the fitted equation, probably using something like meshgrid as shown in Matt Tearle's post (which you referenced)

Sign in to comment.

More Answers (3)

Image Analyst
Image Analyst on 24 Feb 2015
I think the accepted answer is way off base. I think that the way to go is to use scatteredInterpolant function of MATLAB, or krigging.
  1 Comment
S
S on 16 May 2016
Could you please elaborate a bit on this? Taking into account that we have as input an array of coordinates and a timestamp for each of these, how could we use scatteredInterpolant since for that we need to define an interpolant function?

Sign in to comment.


Deepa AS
Deepa AS on 24 Feb 2015
How to generate the heat map with the help of eye gaze data that consists of x and y co ordinates ?

dim-ask
dim-ask on 23 Jul 2022
Edited: dim-ask on 23 Jul 2022
There is a relatively simple solution that imo addresses best what OP was asking, and hopefully it can help other people arriving here. Eg
backimag = uint8(zeros(600,600,3)); % backimag is the background image we have; let's put black
X = randi(100, [100 1]) + 200; % some random x-coordinates
Y = randi(100, [100 1]) + 100; % some random y-coordinates
W = ones(size(X)); % we could have weights on each gaze (eg to normalise for different number of trials per subject)
heatmap = mat2cell(hot,256,[1 1 1]);% we choose a heatmap colouring, eg "hot", and convert it to "cell"
sigma = 16; % the variance parameter for the gaussian kernel
[dimY, dimX, ~] = size(backimag);
% Create "mask"
mask = zeros(dimY, dimX);
for k = 1:size(X,1)
mask(Y(k), X(k)) = mask(Y(k), X(k)) + W(k);
end
% Filter using a gaussian kernel
mask = imgaussfilt(mask, sigma);
% Normalise total mass of heatmap
% Here we equal the total mass with the one of one rectangle out of a 8x8 grid
% Decrease (increase) the constant to make the heatmap hotter (colder)
normConstant = 8;
normMask = dimX * dimY / normConstant^2 / sum(mask , [1 2]);
mask = mask * normMask;
% Colour the background image with the heatmap
newImage = backimag;
for rgbInd = 1:3
thisHeat = heatmap{rgbInd}( floor(mask*255) + 1 );
newImage(:,:,rgbInd) = (newImage(:,:,rgbInd) + uint8(thisHeat*255));
end
figure; imshow(newImage)
So, the idea is that we have a background image as an array Y x X x 3. We then create a "mask" with the gaze data ie a Y x X array where we add 1 at the positions that our gaze data gives, and we apply a gaussian filter on it (eg imgaussfilt from image processing toolbox). We then overlay this to the background, for each rgb-coordinate separately.
I used to use ksdensity to do basically the same estimation but it was much slower, while this one seems quite optimised, plus it avoids time-consuming plotting functions as it only processses arrays. The way the images are overlayed is a bit naive but works great with darker backgrounds (usually I grayscale them and make them darker before, so it looks more clear). One can do it in other ways.
Here I implemented it in a function:
https://raw.githubusercontent.com/earlychildcog/eyeVis/main/src/plotHeatmap.m
and the github repository includes scripts to create heatmap videos:
https://github.com/earlychildcog/eyeVis

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!