How to create a custom colormap and then apply it to an image?

95 vues (au cours des 30 derniers jours)
Gleb Bulatovskiy
Gleb Bulatovskiy le 21 Déc 2018
Réponse apportée : DGM le 15 Jan 2023
I am trying to express an image using only 29 colors. The HEX values of colors are as follows:
C0C0C0 808080 404040 000000 FF99CC 9999FF 3333FF 000099 3399FF 0066CC 99CCFF 66B2FF 66FFFF 006633 00CC66 66FF66 00FF00 009900 FFFF99 FFFF00 CCCC00 FFB266 CC6600 994C00 FF9999 FF0000 CC0000 990000
I need colors to be exactly these; without any changes in darkness/lightness.
I found a function to create a costum colormap on file exchange: https://www.mathworks.com/matlabcentral/fileexchange/42450-custom-colormap Maybe I it will help, but I was not sure how to use it and if it will solve my problem.
Please help.
  1 commentaire
Stephan Gleis
Stephan Gleis le 18 Nov 2020
Hello,
is there a source (publication or similar) that can be quoted regarding the color map?
This colormap seems to me very suitable for some of my illustrations, and I would like to use it...

Connectez-vous pour commenter.

Réponses (4)

Image Analyst
Image Analyst le 21 Déc 2018
Try this:
hexMap = {'C0C0C0', '808080', '404040', '000000', 'FF99CC', '9999FF', '3333FF', '000099', '3399FF', '0066CC', '99CCFF', '66B2FF', '66FFFF', '006633', '00CC66', '66FF66', '00FF00', '009900', 'FFFF99', 'FFFF00', 'CCCC00', 'FFB266', 'CC6600', '994C00', 'FF9999', 'FF0000', 'CC0000', '990000'}
myColorMap = zeros(length(hexMap), 3); % Preallocate
for k = 1 : length(hexMap)
thisCell = hexMap{k}
r = hex2dec(thisCell(1:2))
g = hex2dec(thisCell(3:4))
b = hex2dec(thisCell(5:6))
myColorMap(k, :) = [r, g, b]
end
myColorMap = myColorMap / 255; % Normalize to range 0-1
imshow('moon.tif');
colormap(myColorMap);
colorbar;
0000 Screenshot.png
  7 commentaires
Image Analyst
Image Analyst le 21 Déc 2018
Modifié(e) : Image Analyst le 21 Déc 2018
You have called your m-file colormap.m, which you can't do. That is a built-in function name. Pick another name for your m-file, like colormap_test.m or something.
If you want hte moon in grayscale, just don't do anything - don't call colormap - and it will be in gray scale.
If you're working with RGB images, you cannot apply a colormap. Colormaps can only be applied to indexed images, meaning they are single values/gray scale/monochrome. If you want, you can take one of the color channels, or call rgb2gray() and then apply the colormap to that instead of the RGB image.
Walter Roberson
Walter Roberson le 21 Déc 2018
After creating the colormap, use rgb2ind() on your RGB image passing in the color map, and then use ind2rgb with the results and the colormap. The result would be a color image approximated by only the given colors.

Connectez-vous pour commenter.


Image Analyst
Image Analyst le 19 Nov 2020
For what it's worth, here is an example of how to create a custom colormap in code. This program recreates a cool colormap I once saw used by the ODYSSEA project.
% Displays an image with a cool colormap that has been used for the ODYSSEA project.
% http://www.rac-spa.org/node/1694
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
fprintf('Beginning to run %s.m ...\n', mfilename);
echo off;
%===============================================================================
% Read in the ODYSSEA color map from a .mat file, if it exists already.
% fileName = 'ODYSSEA_Color_map.mat';
% if isfile(fileName)
% s = load(fileName)
% customColorMap = s.customColorMap;
% end
%===============================================================================
% Create the custom color map from scratch.
% First, create red waveform:
r = zeros(256, 1);
r(1:57) = 1;
r(58:75) = linspace(1, 0, length(58:75));
r(150:170) = linspace(0, 1, length(150:170));
r(171:238) = 1;
r(239:256) = linspace(1, 0.5, length(239:256));
% Create green waveform:
g = zeros(256, 1);
g(1:33) = 1;
g(34:75) = linspace(1, 0, length(34:75));
g(76:93) = linspace(0, 1, length(76:93));
g(94:203) = 1;
g(204:219) = linspace(1, 0, length(204:219));
% Create blue waveform:
b = zeros(256, 1);
b(1:61) = 1;
b(62:73) = linspace(1, 0.5, length(62:73));
b(74:88) = linspace(0.5, 1, length(74:88));
b(89:130) = 1;
b(131:150) = linspace(1, 0, length(131:150));
% Now that the individual color channel mappings have been created,
% stitch the red, green, and blue vectors together to create the 256-by-3 colormap matrix.
customColorMap = [r, g, b];
%===============================================================================
% Plot the red, green, and blue components of the custom colormap so we can see what it looks like.
igs = 0 : length(r) - 1; % Input gray scale axis.
subplot(1, 2, 2);
plot(igs, r, 'r-', 'LineWidth', 3);
hold on;
plot(igs, g, 'g-', 'LineWidth', 3);
plot(igs, b, 'b-', 'LineWidth', 3);
grid on;
caption = sprintf('ODYSSEA Color Map with %d Rows', length(r));
title(caption, 'FontSize', fontSize);
xlabel('Input Gray Level', 'FontSize', fontSize);
ylabel('Output Color Channel Level', 'FontSize', fontSize);
xlim([1, 256]);
%===============================================================================
% OPTIONAL : Save the colormap to disk file 'ODYSSEA_Color_map.mat' for next time,
% in case we don't want to recreate it or want to use it elsewhere (a different m-file).
% save('ODYSSEA_Color_map.mat', 'customColorMap')
%===============================================================================
% Read in gray scale image from disk.
folder = pwd;
% baseFileName = 'cameraman.tif';
% baseFileName = 'moon.tif';
% baseFileName = 'cell.tif';
% baseFileName = 'rice.png';
baseFileName = 'AT3_1m4_01.tif';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(baseFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows, columns, numberOfColorBands] = size(grayImage);
% If it's RGB instead of grayscale, convert it to gray scale.
if numberOfColorBands > 1
grayImage = rgb2gray(grayImage);
end
%===============================================================================
% Display the original gray scale image with the custom colormap applied.
subplot(1, 2, 1);
imshow(grayImage, 'ColorMap', customColorMap);
axis on;
colorbar; % Display the colorbar to the right of the image.
caption = sprintf('Original Image with ODYSSEA Color Map Applied: "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'none');
impixelinfo;
% Enlarge figure to full screen.
g = gcf;
g.Name = 'Demo by ImageAnalyst'; % Show this in the title bar.
g.NumberTitle = 'off' % Don't show Figure 1 in title bar.
g.WindowState = 'maximized'

Image Analyst
Image Analyst le 19 Nov 2020
For what it's worth, I was wondering what your colormap would look like if it were smoother -- if it used 256 levels instead of 28. Here is that code:
% Code to create a custom 28 level colormap, then rescale it to 256 levels to be smoother.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
fprintf('Beginning to run %s.m ...\n', mfilename);
echo off;
hexMap = {'C0C0C0', '808080', '404040', '000000', 'FF99CC', '9999FF', '3333FF', '000099', '3399FF', '0066CC', '99CCFF', '66B2FF', '66FFFF', '006633', '00CC66', '66FF66', '00FF00', '009900', 'FFFF99', 'FFFF00', 'CCCC00', 'FFB266', 'CC6600', '994C00', 'FF9999', 'FF0000', 'CC0000', '990000'}
myColorMap = zeros(length(hexMap), 3); % Preallocate
numLevels = length(hexMap);
r = zeros(numLevels, 1);
g = zeros(numLevels, 1);
b = zeros(numLevels, 1);
for k = 1 : numLevels
thisCell = hexMap{k}
r(k) = hex2dec(thisCell(1:2))
g(k) = hex2dec(thisCell(3:4))
b(k) = hex2dec(thisCell(5:6))
end
% Now that the individual color channel mappings have been created,
% stitch the red, green, and blue vectors together to create the 256-by-3 colormap matrix.
myColorMap = [r, g, b]
myColorMap = myColorMap / 255; % Normalize to range 0-1
% Scale to 256 gray levels, instead of the current 28.
numLevels = 256;
myColorMap = imresize(myColorMap, [numLevels, 3]);
% Sometimes it exceeds 1 so rescale 0-1
myColorMap = rescale(myColorMap, 0, 1);
%===============================================================================
% Plot the red, green, and blue components of the custom colormap so we can see what it looks like.
r = myColorMap(:, 1);
g = myColorMap(:, 2);
b = myColorMap(:, 3);
igs = 0 : length(r) - 1; % Input gray scale axis.
subplot(1, 2, 2);
plot(igs, r, 'r-', 'LineWidth', 3);
hold on;
plot(igs, g, 'g-', 'LineWidth', 3);
plot(igs, b, 'b-', 'LineWidth', 3);
grid on;
caption = sprintf('Color Map with %d Rows', length(r));
title(caption, 'FontSize', fontSize);
xlabel('Input Gray Level', 'FontSize', fontSize);
ylabel('Output Color Channel Level', 'FontSize', fontSize);
xlim([min(igs), max(igs)]);
%===============================================================================
% Display the image on the left with the custom colormap applied.
subplot(1, 2, 1);
imshow('moon.tif', 'ColorMap', myColorMap);
colorbar;
title('moon.tif with custom colormap', 'FontSize', 18);

DGM
DGM le 15 Jan 2023
How about an answer that is complete in what it demonstrates? The main lesson here is to use rgb2ind()/ind2rgb(), so let's actually do that.
% convert the colortable to numeric
CT = 'C0C0C0 808080 404040 000000 FF99CC 9999FF 3333FF 000099 3399FF 0066CC 99CCFF 66B2FF 66FFFF 006633 00CC66 66FF66 00FF00 009900 FFFF99 FFFF00 CCCC00 FFB266 CC6600 994C00 FF9999 FF0000 CC0000 990000';
CT = hex2uint(split(CT)); % MIMT (attached)
CT = im2double(CT); % rgb2ind() expects float tables only
% read a screenshot of what looks like a JPG
inpict = imread('stopusingscreenshots.png');
% scale back to approximate original size
inpict = imresize(inpict,1/2);
% apply colormap to create an indexed image
outind = rgb2ind(inpict,CT,'dither');
imshow(outind,CT)
colorbar
% if you want RGB output, convert the result back to RGB using the same map
figure
outrgb = ind2rgb(outind,CT);
imshow(outrgb)
If you want to save the image, save the image. Saving images shouldn't involve taking a screenshot, a photo of the monitor, or the use of crayons.
imwrite(outrgb,'pixeldogrgb.png')
imwrite(outind,CT,'pixeldogind.png') % PNG supports indexed images too

Catégories

En savoir plus sur Red dans Help Center et File Exchange

Produits


Version

R2017b

Community Treasure Hunt

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

Start Hunting!

Translated by