How to plot Intensity vs wavelength of an image?

56 Ansichten (letzte 30 Tage)
Quintus
Quintus am 26 Jan. 2023
Kommentiert: DGM am 29 Jan. 2023
I want to take an image as input and detect the colors' wavelengths in that image. Then I need to determine the intensities of those wavelengths and plot intensity vs wavelength. Is it doable?

Antworten (1)

Image Analyst
Image Analyst am 26 Jan. 2023
In general, no, though attempts have been made with various assumptions about the illuminant and spectral responsivities of the camera sensor. You can have the same color with many, many different spectra, so which spectra do you pick?
  6 Kommentare
DGM
DGM am 29 Jan. 2023
Bearbeitet: DGM am 29 Jan. 2023
"Relative intensity" deserves a big asterisk here. We're talking about a color sensor with its IR mirror removed. That's why I'm assuming that some system modeling is required for intensity calibration, but frequency calibration seems fairly straightforward. That said, I imagine that intensity calibration isn't even needed for a lot of tasks. Looking at the screenshots, I'm not even sure they're doing any intensity calibration. I'd have to read more.
As to whether it could be done in MATLAB, I'm sure it could. I don't have a spectrometer, the images, or the information about the corresponding source spectra. You could make the project as a simple ad-hoc script, or you could build an entire GUI with calibration utilities or something. Depending on the goals, having Image Processing Toolbox may help make some parts of the task easier. Certainly, improfile() is part of IPT.
I grabbed an image off the website:
From that, I cropped this sample image chunk:
% get image
inpict = imread('specttrim.png');
% crop out relevant region
% this relies on the pattern being grid-aligned
inpict = imcrop(inpict,[72 68 305 20]);
% convert to grayscale somehow
%inpict = mean(im2double(inpict),3); % average?
%inpict = rgb2gray(im2double(inpict)); % BT601 luma?
inpict = imapplymatrix([0.2126 0.7152 0.0722],im2double(inpict)); % BT709 luma?
% ... or use some sort of system-specific intensity calibration information
% generate profile by averaging off-axis
% again, this relies on the pattern being grid-aligned
profile = mean(inpict,1);
% rough (linear) frequency calibration
lbref = [494 693]; % wavelengths of known peaks
idx = [77 209]; % the indices in profile corresponding to those peaks
lambda = interp1(idx,lbref,1:numel(profile),'linear','extrap');
% plot the profile
plot(lambda,profile)
xlim([min(lambda) max(lambda)])
You could underfill the curve with some pseudocolor image if you want. You could crop the image wider to get more range if you wanted. This is just a simple example.
DGM
DGM am 29 Jan. 2023
I realized that underfilling the curve was a bit more of a hassle, so here's an example.
% get image
inpict = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1277300/image.png');
% crop out relevant region
% this relies on the pattern being grid-aligned
inpict = imcrop(inpict,[72 68 305 20]);
% convert to grayscale somehow
%inpict = mean(im2double(inpict),3); % average?
%inpict = rgb2gray(im2double(inpict)); % BT601 luma?
inpict = imapplymatrix([0.2126 0.7152 0.0722],im2double(inpict)); % BT709 luma?
% ... or use some sort of system-specific intensity calibration information
% generate profile by averaging off-axis
% again, this relies on the pattern being grid-aligned
profile = mean(inpict,1);
% rough frequency calibration
lbref = [494 693]; % wavelengths of known peaks
idx = [77 209]; % the indices in profile corresponding to those peaks (manually picked)
lambda = interp1(idx,lbref,1:numel(profile),'linear','extrap');
% generate patch vertex coordinates
xx = [lambda fliplr(lambda)];
yy = [profile zeros(size(profile))];
% create color data for each vertex pair
CT = getcdata(lambda);
cc = [1:numel(lambda), numel(lambda):-1:1];
% plot the profile
patch(xx,yy,cc);
xlim([min(lambda) max(lambda)])
colormap(CT)
function CT = getcdata(vtxlambda)
% location of gradient breakpoints (in wavelength)
x0 = [312 381 403 419 440 492 512 580 646 652 779 927];
CT0 = [0 0 0; 0 0 0; 0.353 0 0.563; 0.353 0 1; 0 0 1; 0 1 1;
0 1 0; 1 1 0; 1 0 0; 1 0 0; 0 0 0; 0 0 0];
% look up colormap colors for each vertex lambda
CT = interp1(x0,CT0,vtxlambda,'linear','extrap');
end
You could generate the pseudocolor map however you choose, but I derived this from the screenshot.

Melden Sie sich an, um zu kommentieren.

Community Treasure Hunt

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

Start Hunting!

Translated by