# Is there a way I can convert image (pixel) values to Raman shift using MATLAB?

13 views (last 30 days)

Show older comments

### Answers (3)

Star Strider
on 19 Dec 2021

They appear to me to be different data.

However, filtering out the high-frequency noise is likely as close as it is possible to get to correcting the ‘Pixel’ data —

T1 = readtable('https://www.mathworks.com/matlabcentral/answers/uploaded_files/833340/Calcite%20Pixel.txt', 'VariableNamingRule','preserve')

T2 = readtable('https://www.mathworks.com/matlabcentral/answers/uploaded_files/833345/Calcite%20Raman%20Shift.txt', 'VariableNamingRule','preserve')

Pixx = T1.Pixel;

PixDS = T1.('Dark Subtracted');

RSx = T2.('Raman Shift');

RSDS = T2.('Dark Subtracted');

figure

plot(Pixx, PixDS)

grid

title('Pixel')

figure

plot(RSx, RSDS)

grid

title('Raman Shift')

PixDScb = correctBaseline(Pixx, PixDS, 5, 50, 3);

figure

plot(Pixx, PixDScb)

grid

title('Pixel — Corrected Baseline')

RSDScb = correctBaseline(RSx, RSDS, .01, 5);

figure

plot(RSx, RSDScb)

grid

title('Raman Shift — Corrected Baseline')

Pixx_stats = [mean(diff(Pixx)); std(diff(Pixx))];

Fs = 1;

Fn = Fs/2;

L = numel(Pixx);

NFFT = 2^nextpow2(L);

FTPixDS = fft(PixDScb,NFFT)/L;

Fv = linspace(0, 1, NFFT/2+1)*Fn;

Iv = 1:numel(Fv);

figure

plot(Fv, abs(FTPixDS(Iv))*2)

grid

xlim([0 0.1])

Passband = 0.03; % Hz (Or Cycles/(Whatever The x-Axis Units Are))

PixDScb_f = lowpass(PixDScb, 0.03, Fs);

figure

subplot(2,1,1)

plot(Pixx, PixDScb)

grid

title('Pixel — Corrected Baseline')

subplot(2,1,2)

plot(Pixx, PixDScb_f)

grid

title('Pixel — Corrected Baseline — Filtered')

function correctedSignal = correctBaseline(varargin)

% % % ARGUMENT LIST (IN ORDER) —

% % % x: X-Vector

% % % y: Y=Vector

% % % prom: Peak Minimum Prominence

% % % sep: Miinimum Peak Separation

% % % pd: Polynomial Degree

% % %

% % % CALLING CONVENTION —

% % % correctedSignal = correctedBaseline(x, y, prom, sep, pd_

% vn = numel(varargin)

x = varargin{1};

y = varargin{2};

prom = varargin{3};

sep = varargin{4};

pd = 4;

if numel(varargin) > 4

pd = varargin{5};

end

TF = islocalmin(y, 'MinProminence',prom, 'MinSeparation',sep);

p = polyfit(x(TF), y(TF),4);

BL = polyval(p, x);

correctedSignal = y-BL;

end

.

##### 12 Comments

Image Analyst
on 25 Dec 2021

OK, so for one signal (which one), it starts at 280 cm-1, and ends at 1085 cm-1, and I ignore the 711.

And for the other signal, it starts at what and ends at what?

I don't need the pixel values because you said those are in the first column of the text file, so we know those. Calcite's x (pixel value) goes from 86 to 2005, and Calcite Raman Shift's x (pixel value) goes from 162 to 2790 -- these are just values from the first column of the text files and I presume these are the pixel coordinates.

OK, let's try a different approach. Are you saying that one signal is a scaled and shifted version of the other and that we need to rescale and shift one signal such that certain spikes align with the corresponding peaks on the other signal? Like maybe you want to do normalized cross correlation? Or just find the two tallest peaks in each signal and align those?

Image Analyst
on 20 Dec 2021

Assuming that both signals were acquired with the same wavenumber range, you can simply rescale the x axis for each to go linearly from the starting wavenumber to the ending wavenumber. However since each signal for some reason has a different number of samples, you'll have to interpolat. See my code below. I'm assuming that the first element of each signal should be relocated to wavenumber1 and the last element of each signal should be relocated to wavenumber2. If we assume that they look reasonably well aligned now, and we have a new x axis that is the wavenumbers. Adapt my code below to use the actual wavenumbers for the signals.

% Read in first signal.

data1 = readmatrix('Calcite Pixel.txt');

x1 = data1(:, 1); % Get pixels.

signal1 = data1(:, 2); % Get intensity.

% Read in other signal

data2 = readmatrix('Calcite Raman Shift.txt');

x2 = data2(:, 1); % Get pixels.

signal2 = data2(:, 2);

subplot(2, 1, 1);

plot(x1, signal1, 'r-', 'LineWidth', 2);

hold on;

plot(x2, signal2, 'b-', 'LineWidth', 2);

grid on;

ylabel('Signal')

xlabel('Pixels')

wavenumber1 = 1700; % Whatever

wavenumber2 = 4000; % Whatever

% Find the max number of wavenumber samples

numSamples = max([length(signal1), length(signal2)])

% Get wavenumbers going from wavenumber1 to wavenumber2 with numSamples

wavenumbers = linspace(wavenumber1, wavenumber2, 2*numSamples);

% Interpolate both signals to be on a common x axis.

xi1 = linspace(wavenumber1, wavenumber2, length(signal1));

signal1 = interp1(xi1, signal1, wavenumbers);

xi2 = linspace(wavenumber1, wavenumber2, length(signal2));

signal2 = interp1(xi2, signal2, wavenumbers);

subplot(2, 1, 2);

plot(wavenumbers, signal1, 'r-', 'LineWidth', 2);

hold on;

plot(wavenumbers, signal2, 'b-', 'LineWidth', 2);

grid on;

ylabel('Signal')

xlabel('Wavenumber')

The top is the original, pixel-based signals, and the bottom is the new signals shfted, interpolated, and rescaled so that the x axis now represents wavenumbers.

##### 4 Comments

Image Analyst
on 24 Dec 2021

Now I'm confused even more. You talk like "Pixel" is some specific program. Why are you capitalizing Pixel? Is it a software package? Because just a "pixel" from an image would not be capitalized. I assumed that somehow you'd gotten coordinates by scanning some image of a plot/graph and the coordinates were in pixels.

I still don't know what you mean by that third number.

Can you attach the original .spc files (zipped up). Why don't we just use those instead of messing with some text file with other, incorrect coordinates?

David Goodmanson
on 24 Dec 2021

Edited: David Goodmanson
on 24 Dec 2021

Now that the peaks in both pixels and cm^(-1) are provided, you can do a linear fit, which is very close.

p = [155.56834, 396.54987 624.69582,]

r = [280.05051 711.46459 1085.32579]

a = polyfit(p,r,1)

figure(1)

plot(p,r,'o-',p,polyval(a,p),'o-')

grid on

xlabel('pixels')

ylabel('inverse cm')

a = 1.7172 18.6607

i.e.

cm^(-1) = 1.7172*pixel + 18.66

so one cm^(-1) is worth 1.717 pixels.

It seems unikely in this case but suppose you knew for a fact that, because of the way the instrumentation is built and data is taken, cm^(-1) has to be strictly proportional to pixels, i.e. no offset like the 18.66 above. Then you could find the proportionality constant

c = r/p

p = [0 p];

r = [0 r];

figure(2)

plot(p,r,'o-',p,c*p,'o-')

grid on

xlabel('pixels')

ylabel('inverse cm')

c = 1.7556

##### 2 Comments

David Goodmanson
on 25 Dec 2021

Hi ortizgd,

I guess I could, but your access to the files is much more convenient than mine. Defining

pixel file

p = pixels (col 1)

Ip = intensity (col 2)

inverse cm file

icm = inv cm (col 1)

Iicm = intensity (col 2)

then with

figure(1)

plot(1.7172*p+18.66,Ip,icm,Iicm)

grid on

either the peaks willl match up or they won't.

### See Also

### Community Treasure Hunt

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

Start Hunting!