[Matlab] Hyperspectral Data To RGB

In here I will describe how you can convert your hyperspectral data containg wavelengths and reflectance values, from for example a hyperspectral cube (or hypercube), to RGB data (or XYZ, Lab, whatever).

In order to convert the hyperspectral data (wavelengths and reflectance) to RGB values, we need to get the tables that relates the visual spetrum to ‘xyz’. From ‘xyz’ we then convert to ‘XYZ’ and from there we generally go to ‘Lab’, which is device independent. I then advise you to open the file in Photoshop and convert it to a nice color profile, because Matlab only works with the inferior sRGB color profile with RGB data.

hyper2rgb.m

clc; clear all; close all
 
%Loads a directory with files in the format /<wavelength>.tif
cube_dirname = 'C:YOUR-FOLDER-WITH-FILES';
cube_dir = dir([cube_dirname '*.tif']);
 
%Load the data that relates spectral data to the x,y,z and energy primaries
%Through the strings, choose the correct data.
[lambda, xFcn, yFcn, zFcn, energy] = getSpectral('cie_1964','D65');
 
 
dummyim = imread([ cube_dirname cube_dir(end).name ]);
hypercube = uint8(zeros(size(dummyim,1), size(dummyim,2), length(cube_dirname)));
lambda_cube = zeros(length(cube_dir),1);
for i=1:length(cube_dir)
	lambdaNow = cube_dir(i).name;
	lambdaNow = lambdaNow(1:3);
	disp(lambdaNow)
	hypercube(:,:,i) = imread([cube_dirname cube_dir(i).name]);
	lambda_cube(i) = str2num(lambdaNow);
end
 
for i=1:length(lambda_cube)
	idxS = find(lambda==lambda_cube(i),1);
	if isempty(idxS)
		xFcnCor(i) = 0;
		yFcnCor(i) = 0;
		zFcnCor(i) = 0;
	else
		xFcnCor(i) = xFcn(idxS);
		yFcnCor(i) = yFcn(idxS);
		zFcnCor(i) = zFcn(idxS);
	end
 
	idxI = find(lambda==lambda_cube(i),1);
	if isempty(idxS)
		energyCor(i) = 0;
	else
		energyCor(i) = energy(idxI);
	end
end
 
%Compute the normalisation factor k
k=100./sum(yFcnCor.*energyCor);
 
%Precompute the SPD's in the eye
xI = xFcnCor.*energyCor;
yI = yFcnCor.*energyCor;
zI = zFcnCor.*energyCor;
 
%Now synthesize the data, hard to do efficiently due to memory magement..
 
X=zeros(size(dummyim));
Y=zeros(size(dummyim));
Z=zeros(size(dummyim));
 
for x=1:size(dummyim,2)
	for y=1:size(dummyim,1)
		r=double(reshape(hypercube(y,x,:),1,length(xI)))./255; %reflectance value at (x,y)
		X(y,x) = sum(xI.*r);
		Y(y,x) = sum(yI.*r);
		Z(y,x) = sum(zI.*r);
	end
end
 
XYZ(:,:,1)=X;
XYZ(:,:,2)=Y;
XYZ(:,:,3)=Z;
 
%Normalize
XYZ = k*XYZ./100;
 
C = makecform('XYZ2Lab');
Lab = applycform(XYZ,C);
Lab16 = uint16(Lab./100.*((2^16)-1));
 
C = makecform('XYZ2srgb');
sRGB = applycform(XYZ,C);
 
%Write to TIFF (in the format that Photoshop can read the L,a,b channels)
imwrite(Lab16(:,:,1),'L.tif')
imwrite(Lab16(:,:,2)./2+((2^16)/2),'a.tif')
imwrite(Lab16(:,:,3)./2+((2^16)/2),'b.tif')
 
imwrite(sRGB,'sRGB.tif')
 
imshow(sRGB)
 
 
 
%% Makes a 2D histogram style image of wavelength versus intensity of the spectral map
 
clear hypercubeSmall
 
for i=1:length(cube_dir)
	hypercubeSmall(:,:,i) = imresize(imread([cube_dirname cube_dir(i).name]),0.5);
end
%The vector 'lambda_cube' contains all the lambda elements
clear vec vech
for i=1:length(cube_dir)
	vec(i,:) = reshape(hypercubeSmall(:,:,i), 1, size(hypercubeSmall,1)*size(hypercubeSmall,2));
	h=hist(double(vec(i,:)),[0:1:255]);
	vech(1:256,i)=h;
end
 
vech=flipud(vech*(2^16-1)/max2(vech));
 
imagesc(vech)
 
%imwrite(uint16(vech),'binnedspectrum.tif')

getSpectral.m

Warning: this function is too long, as it contains some standardized spectral data. please download it from me. or below

 
function [lambda, x, y, z, energy] = getSpectral(formulary, illuminant)
%getSpectral returs lambd versus x y z primaries and illumination back
% with the colormatching function and illuminant name as input
%    [lambda, x, y, z, illum] = getSpectral(formulary, illum)
%			f.e. [lambda, x, y, z, energy] = getSpectral('cie_1964','D65')
%
% (c) Tim Zaman 2013
% Obtained from CIE spreadsheet and http://cvrl.ioo.ucl.ac.uk/
%
 
 
(...)

Download getSpectral.m

Tim Zaman

MSc Biorobotics. Specialization in computer vision and deep learning. Works at NVIDIA.

You may also like...

5 Responses

  1. Raghu says:

    Can you please explain the physics behind doing all this?/ Question’s are:
    Why can’t picking up three channels( from R, G, B ranges) from spectral data form an RGB image, or please point to some article which can help understand the physics
    Thanks very much

  2. Nicolas David says:

    Hi,

    how can I get your getSpectral.m function?

    Thank you

  3. Mohammad Karim Hashemi says:

    dear sir
    I have some hyperspectral data as below and I want to use in matlab how can I used them with matlab?.
    source:http://www.spectir.com/
    Deepwater Horizon Oil Spill Sample: June 06, 2010
    0612-1615_igm_sub.hdr
    0612-1615_rad_sub

    Thanks for your help
    Hashemizadeh
    student of M.S. communication university

  4. Mohammad Karim Hashemi says:

    dear sir
    I have some hyperspectral data as below and I want to use in matlab how can I used them with matlab?.
    source:http://www.spectir.com/
    Deepwater Horizon Oil Spill Sample: June 06, 2010
    0612-1615_igm_sub.hdr
    0612-1615_rad_sub

    Thanks for your help
    Hashemizadeh
    student of M.S. communication university