heatmap color RGB data for manaully created image

16 views (last 30 days)
I have the usage data for they key use on a qwerty keyboard. I would like to create a heat map on the image of a traditional keyboard (made at the end).
I really like how heatmap works with the color scheme. How can I get the color information from the heatmap for my keyboard? How can I can I find the RGB values for each key?
I found similiar questions to this, but they were not clear.
% Given data: the sum of Data is equal to 1
% sum(data) = 1 is True
data = [0.000185322461082283 0.0209811500582442 0.121240601503759 0.0536905644392672 0.0794967171449751 0.0211333792227047 0.0234035793709626 0.0543855236683257 0.0746584771788626 0.0124761728264323;...
0.0893254262416605 0.0582243460764588 0.0493354866038335 0.0234763846235307 0.0161164354548343 0.0785303928836175 0.0033556602774542 0.00686354971936884 0.0357407603515832 0.0146801863814466;...
0.000781001800275336 0.000344170284867097 0.0167716827279466 0.00929921635073599 0.0168974372551096 0.0614145398708038 0.0265209679127396 0.0195912316001271 0.0101066927883088 0.000972942920681987];
layout =[ "q" "w" "e" "r" "t" "y" "u" "i" "o" "p"
"a" "s" "d" "f" "g" "h" "j" "k" "l" ";"
"z" "x" "c" "v" "b" "n" "m" "," "." "/"];
% heatmap generate
figure(1)
fig = heatmap(data,'Colormap',parula)
fig =
HeatmapChart with properties: XData: {10×1 cell} YData: {3×1 cell} ColorData: [3×10 double] Show all properties
% values found for the making image, key size, key widths
key_num_width = 10.80;
key_num_hieght = 3;
key_pixel = 30;
size_multiplier = 10; % mess with this to change resolution probably something close to 10
% I forget what this does
A = 255*ones(size_multiplier*key_num_hieght*key_pixel,size_multiplier*key_num_width*key_pixel);
[B, C] = deal(A);
key_size = size_multiplier*key_pixel;
% changes the ones to 255 for image
rgbImage(:,:,1) = uint8(A);
rgbImage(:,:,2) = uint8(B);
rgbImage(:,:,3) = uint8(C);
Here, I need the data which are the three RGB matrixes each being 3x10
% HERE
% I would like to find the RGB matrix values from the heatmap
R_value = 200*ones(3,10)
R_value = 3×10
200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200
G_value = 200*ones(3,10)
G_value = 3×10
200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200
B_value = 200*ones(3,10)
B_value = 3×10
200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200
% specify key colors given R, G and B matrixes (all 3x10) that has been
% extracted from heatmap
% starts top row (left to right) and then down each row one at a time
offset = [0 0.25 0.75]; % offset for key rows
for j = 0:2
% specifies the boundries in the y directions for the keys
ywidth = (key_size*j+1):(key_size+key_size*j);
for i = 0:9
% specifies the boundries in the x directions for the keys
% note that there is a offset applied at 0, 0.25 and 0.75 of
% keywidth
xwidth = (key_size*i+1+key_size*offset(j+1)):(key_size+key_size*i+key_size*offset(j+1));
% apply found RGB values from heat map to key at a time
rgbImage(ywidth,xwidth,1) = R_value(j+1,i+1);
rgbImage(ywidth,xwidth,2) = G_value(j+1,i+1);
rgbImage(ywidth,xwidth,3) = B_value(j+1,i+1);
end
end
% enter text for each key, included in question for clarity
RGB = rgbImage;
for i = 0:9
RGB = insertText(RGB,[ key_size/2+i*key_size,key_size/2],layout(1,i+1),'FontSize',150,'AnchorPoint','Center','BoxOpacity',0);
end
for i = 0:9
RGB = insertText(RGB,[key_size/2+i*key_size+key_size*0.25,key_size/2+key_size],layout(2,i+1),'FontSize',150,'AnchorPoint','Center','BoxOpacity',0);
end
for i = 0:9
RGB = insertText(RGB,[key_size/2+i*key_size+0.75*key_size,key_size/2+key_size*2],layout(3,i+1),'FontSize',150,'AnchorPoint','Center','BoxOpacity',0);
end
% show result
figure(2)
imshow(RGB)
  3 Comments
Adam Danz
Adam Danz on 4 Aug 2022
This is the first time I see a heat map created with insertText! Ha! Creative.

Sign in to comment.

Accepted Answer

DGM
DGM on 4 Aug 2022
Edited: DGM on 4 Aug 2022
The use of heatmap() is unnecessary. This is a basic use of indexed color. Generate a color table and find the indexes into it.
data = [0.000185322461082283 0.0209811500582442 0.121240601503759 0.0536905644392672 0.0794967171449751 0.0211333792227047 0.0234035793709626 0.0543855236683257 0.0746584771788626 0.0124761728264323;...
0.0893254262416605 0.0582243460764588 0.0493354866038335 0.0234763846235307 0.0161164354548343 0.0785303928836175 0.0033556602774542 0.00686354971936884 0.0357407603515832 0.0146801863814466;...
0.000781001800275336 0.000344170284867097 0.0167716827279466 0.00929921635073599 0.0168974372551096 0.0614145398708038 0.0265209679127396 0.0195912316001271 0.0101066927883088 0.000972942920681987];
ctlength = 256; % pick a color table length
CT = parula(ctlength); % generate a color table
ctidx = round(mat2gray(data)*(ctlength-1)) % these are the corresponding row indices into CT
ctidx = 3×10
0 44 255 113 167 44 49 114 157 26 188 122 104 49 34 165 7 14 75 31 1 0 35 19 35 129 55 41 21 2
What is the color associated with data(1,3)?
CT(ctidx(1,3)+1,:)
ans = 1×3
0.9769 0.9839 0.0805
All you need to do at this point is apply that color to the image regions.
  6 Comments
DGM
DGM on 4 Aug 2022
Edited: DGM on 4 Aug 2022
FWIW, this is probably how I would have approached it with MIMT. It's definitely more costly in terms of system resources, but at least it's easier for me to think about the image manipulation this way. The row offset routine could be converted into a function to reduce repeated code.
data = [0.000185322461082283 0.0209811500582442 0.121240601503759 0.0536905644392672 0.0794967171449751 0.0211333792227047 0.0234035793709626 0.0543855236683257 0.0746584771788626 0.0124761728264323;...
0.0893254262416605 0.0582243460764588 0.0493354866038335 0.0234763846235307 0.0161164354548343 0.0785303928836175 0.0033556602774542 0.00686354971936884 0.0357407603515832 0.0146801863814466;...
0.000781001800275336 0.000344170284867097 0.0167716827279466 0.00929921635073599 0.0168974372551096 0.0614145398708038 0.0265209679127396 0.0195912316001271 0.0101066927883088 0.000972942920681987];
layout = 'qwertyuiopasdfghjkl;zxcvbnm,./';
losize = size(data); % key layout [rows cols]
keysize = [40 40]; % in pixels
rowoffset = [0 0.25 0.75]; % in keywidth units
padcolor = [1 1 1]; % the padding color where rows are offset
textcolor = [0 0 0]; % the text color obviously
ctlength = 256; % pick a color table length
CT = parula(ctlength); % pick a color table
% generate row indices into color table
ctidx = round(mat2gray(data)*(ctlength-1));
% create initial 3x10x3 RGB image from CT
keypict = ind2rgb(ctidx,CT);
% expand it based on selected key size
keypict = repelem(keypict,keysize(1),keysize(2));
% pad it as necessary for row offsets
keypict = addborder(keypict,[0 0 0 ceil(max(rowoffset)*keysize(2))],padcolor,'normalized');
% offset key rows
for r = 1:losize(1)
yrange = (r-1)*keysize(1)+1:(r-1)*keysize(1)+keysize(1);
keypict(yrange,:,:) = circshift(keypict(yrange,:,:),round(rowoffset(r)*keysize(2)),2);
end
% construct text images
keytext = cell(numel(layout),1);
for k = 1:numel(layout)
% i don't have CVT or insertText(), so i'm using crispy old bitmap fonts
keytext{k} = textim(layout(k),'cordata-ppc21');
end
% pad the text objects to the same size as the keys (implicitly centered)
keytext = imstacker(keytext,'padding',0,'size',keysize);
% tile into a flat image, pad and offset as before
keytext = imtile(keytext,losize);
keytext = addborder(keytext,[0 0 0 ceil(max(rowoffset)*keysize(2))],0);
for r = 1:losize(1)
yrange = (r-1)*keysize(1)+1:(r-1)*keysize(1)+keysize(1);
keytext(yrange,:,:) = circshift(keytext(yrange,:,:),round(rowoffset(r)*keysize(2)),2);
end
% composite the two images
outpict = replacepixels(textcolor,keypict,keytext);
imshow(outpict)
I know nobody really needs this, but I had it half-written and didn't feel like deleting it.
Adam Danz
Adam Danz on 4 Aug 2022
Edited: Adam Danz on 4 Aug 2022
@DGM, normalize(A,'range') is similar and doesn't require Image Processing TB but it currently doesn't have an option to specify both the "range" method and the dimensions.
B = rescale(A) is even better IMO.

Sign in to comment.

More Answers (1)

Adam Danz
Adam Danz on 4 Aug 2022
See the 5 lines of code under "new section". I didn't change anything else.
% Given data: the sum of Data is equal to 1
% sum(data) = 1 is True
data = [0.000185322461082283 0.0209811500582442 0.121240601503759 0.0536905644392672 0.0794967171449751 0.0211333792227047 0.0234035793709626 0.0543855236683257 0.0746584771788626 0.0124761728264323;...
0.0893254262416605 0.0582243460764588 0.0493354866038335 0.0234763846235307 0.0161164354548343 0.0785303928836175 0.0033556602774542 0.00686354971936884 0.0357407603515832 0.0146801863814466;...
0.000781001800275336 0.000344170284867097 0.0167716827279466 0.00929921635073599 0.0168974372551096 0.0614145398708038 0.0265209679127396 0.0195912316001271 0.0101066927883088 0.000972942920681987];
layout =[ "q" "w" "e" "r" "t" "y" "u" "i" "o" "p"
"a" "s" "d" "f" "g" "h" "j" "k" "l" ";"
"z" "x" "c" "v" "b" "n" "m" "," "." "/"];
% heatmap generate
figure(1)
fig = heatmap(data,'Colormap',parula)
fig =
HeatmapChart with properties: XData: {10×1 cell} YData: {3×1 cell} ColorData: [3×10 double] Show all properties
% values found for the making image, key size, key widths
key_num_width = 10.80;
key_num_hieght = 3;
key_pixel = 30;
size_multiplier = 10; % mess with this to change resolution probably something close to 10
% I forget what this does
A = 255*ones(size_multiplier*key_num_hieght*key_pixel,size_multiplier*key_num_width*key_pixel);
[B, C] = deal(A);
key_size = size_multiplier*key_pixel;
% changes the ones to 255 for image
rgbImage(:,:,1) = uint8(A);
rgbImage(:,:,2) = uint8(B);
rgbImage(:,:,3) = uint8(C);
% HERE
% % I would like to find the RGB matrix values from the heatmap
% R_value = 200*ones(3,10)
% G_value = 200*ones(3,10)
% B_value = 200*ones(3,10)
New section
cmap = uint8(parula(256) * 255);
cidx = round(normalize(data(:),'range')*(height(cmap)-1))+1;
R_value = reshape(cmap(cidx,1),size(data));
G_value = reshape(cmap(cidx,2),size(data));
B_value = reshape(cmap(cidx,3),size(data));
% specify key colors given R, G and B matrixes (all 3x10) that has been
% extracted from heatmap
% starts top row (left to right) and then down each row one at a time
offset = [0 0.25 0.75]; % offset for key rows
for j = 0:2
% specifies the boundries in the y directions for the keys
ywidth = (key_size*j+1):(key_size+key_size*j);
for i = 0:9
% specifies the boundries in the x directions for the keys
% note that there is a offset applied at 0, 0.25 and 0.75 of
% keywidth
xwidth = (key_size*i+1+key_size*offset(j+1)):(key_size+key_size*i+key_size*offset(j+1));
% apply found RGB values from heat map to key at a time
rgbImage(ywidth,xwidth,1) = R_value(j+1,i+1);
rgbImage(ywidth,xwidth,2) = G_value(j+1,i+1);
rgbImage(ywidth,xwidth,3) = B_value(j+1,i+1);
end
end
% enter text for each key, included in question for clarity
RGB = rgbImage;
for i = 0:9
RGB = insertText(RGB,[ key_size/2+i*key_size,key_size/2],layout(1,i+1),'FontSize',150,'AnchorPoint','Center','BoxOpacity',0);
end
for i = 0:9
RGB = insertText(RGB,[key_size/2+i*key_size+key_size*0.25,key_size/2+key_size],layout(2,i+1),'FontSize',150,'AnchorPoint','Center','BoxOpacity',0);
end
for i = 0:9
RGB = insertText(RGB,[key_size/2+i*key_size+0.75*key_size,key_size/2+key_size*2],layout(3,i+1),'FontSize',150,'AnchorPoint','Center','BoxOpacity',0);
end
% show result
figure(2)
imshow(RGB)
  1 Comment
Taybs
Taybs on 4 Aug 2022
Edited: Taybs on 4 Aug 2022
Thank you so much. I appreciate it. I saw the edits that you made as well.

Sign in to comment.

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!