How to plot Intensity vs wavelength of an image?

56 ビュー (過去 30 日間)
Quintus
Quintus 2023 年 1 月 26 日
コメント済み: DGM 2023 年 1 月 29 日
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?

回答 (1 件)

Image Analyst
Image Analyst 2023 年 1 月 26 日
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 件のコメント
DGM
DGM 2023 年 1 月 29 日
編集済み: DGM 2023 年 1 月 29 日
"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 2023 年 1 月 29 日
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.

サインインしてコメントする。

Community Treasure Hunt

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

Start Hunting!

Translated by