Wind rose diagram plot in matlab - matlab

I am currently trying to plot in matlab a wind rose diagram with data wind velocities and directions for a given period.
The main program is such that after plotting several plots on the Weibull distribution, it calls another matlab program to produce a wind rose.
The wind rose program is essentially here: https://www.mathworks.com/matlabcentral/fileexchange/47248-wind-rose
and the main program is mainly based on https://www.mathworks.com/matlabcentral/fileexchange/41996-computing-weibull-distribution-parameters-from-a-wind-speed-time-series?focused=3786165&tab=function
I've been working yesterday on a very old matlab edition and I had serious problems with making the code run.
Today with Octave in a Ubuntu machine and after some efforts I managed to get a result with a minor problem: the wind rose did not had all the information it should have.
I run the program in a new version of matlab and then I got the following message:
Error using WindRose (line 244)
is not a valid property for WindRose function.
Error in octavetestoforiginalprogram (line 184)
[figure_handle,count,speeds,directions,Table] = WindRose(dir,vel,Options);
How can the program run in Octave and now produces such an error, I don't understand.
Does anyone have an idea of what this error means?
Note: I am posting the entire code below if anyone wants to read it:
%% EXTRACT AND PLOT RAW DATA
% Extract wind speed data from a file
v = xlsread('1981-1985_timeseries.xlsx');
% Plot the measured wind speed
plot(v)
title('Wind speed time series');
xlabel('Measurement #');
ylabel('Wind speed [m/s]');
%% PROCESS DATA
% Remove nil speed data (to avoid infeasible solutions in the following)
v(find(v==0)) = [];
% Extract the unique values occuring in the series
uniqueVals = unique(v);
uniqueVals(isnan(uniqueVals))=[];
% Get the number of unique values
nbUniqueVals = length(uniqueVals);
% Find the number of occurences of each unique wind speed value
for i=1:nbUniqueVals
nbOcc = v(find(v==uniqueVals(i)));
N(i) = length(nbOcc);
end
% Get the total number of measurements
nbMeas = sum(N);
% To take into account the measurement resolution
% (i.e., a measured wind speed of 2.0 m/s may actually correspond to a
% real wind speed of 2.05 or 1.98 m/s), compute the delta vector which
% contains the difference between two consecutive unique values
delta(1) = uniqueVals(1);
for i=2:nbUniqueVals
delta(i) = uniqueVals(i) - uniqueVals(i-1);
end
% Get the frequency of occurence of each unique value
for i=1:nbUniqueVals
prob(i) = N(i)/(nbMeas*delta(i));
end
% Get the cumulated frequency
freq = 0;
for i=1:nbUniqueVals
freq = prob(i)*delta(i) + freq;
cumFreq(i) = freq;
end
%% PLOT THE RESULTING DISTRIBUTION
% Plot the distribution
figure
subplot(2,1,1);
pp=plot(uniqueVals,prob)
title('Distribution extracted from the time series');
xlabel('Wind speed [m/s]');
ylabel('Probability');
% Plot the cumulative distribution
subplot(2,1,2);
plot(uniqueVals,cumFreq)
title('Cumulative distribution extracted from the time series');
xlabel('Wind speed [m/s]');
ylabel('Cumulative probability');
%% EXTRACT THE PARAMETERS USING A GRAPHICAL METHOD
% See the following references for more explanations:
% - Akdag, S.A. and Dinler, A., A new method to estimate Weibull parameters
% for wind energy applications, Energy Conversion and Management,
% 50 :7 1761�1766, 2009
% - Seguro, J.V. and Lambert, T.W., Modern estimation of the parameters of
% the Weibull wind speed distribution for wind energy analysis, Journal of
% Wind Engineering and Industrial Aerodynamics, 85 :1 75�84, 2000
% Linearize distributions (see papers)
ln = log(uniqueVals);
lnln = log(-log(1-cumFreq));
% Check wether the vectors contain inifinite values, if so, remove them
test = isinf(lnln);
for i=1:nbUniqueVals
if (test(i)==1)
ln(i)= [];
lnln(i)= [];
end
end
% Extract the line parameters (y=ax+b) using the polyfit function
params = polyfit(ln,lnln',1);
a = params(1);
b = params(2);
y=a*ln+b;
% Compare the linealized curve and its fitted line
figure
plot(ln,y,'b',ln,lnln,'r')
title('Linearized curve and fitted line comparison');
xlabel('x = ln(v)');
ylabel('y = ln(-ln(1-cumFreq(v)))');
% Extract the Weibull parameters c and k
k = a
c = exp(-b/a)
%% CHECK RESULTS
% Define the cumulative Weibull probability density function
% F(V) = 1-exp(-((v/c)^k)) = 1-exp(-a2), with a1 = v/c, a2 = (v/c)^k
a1 = uniqueVals/c;
a2 = a1.^k;
cumDensityFunc = 1-exp(-a2);
% Define the Weibull probability density function
%f(v)=k/c*(v/c)^(k-1)*exp(-((v/c)^k))=k2*a3.*exp(-a2),
% with k2 = k/c, a3 = (v/c)^(k-1)
k1 = k-1;
a3 = a1.^k1;
k2 = k/c;
densityFunc = k2*a3.*exp(-a2);
% Plot and compare the obtained Weibull distribution with the frequency plot
figure
subplot(2,2,1);
pp=plot(uniqueVals,prob,'.',uniqueVals,densityFunc, 'r')
title('Weibull probability density function');
xlabel('v');
ylabel('f(v)');
subplot(2,2,3)
h=hist(v);
title('Wind speed time series');
xlabel('Measurement #');
ylabel('Wind speed [m/s]');
h=h/(sum(h)*10);
bar(h)
% Same for the cumulative distribution
subplot(2,2,2);
plot(uniqueVals,cumFreq,'.',uniqueVals,cumDensityFunc, 'r')
title('Cumulative Weibull probability density function');
xlabel('v');
ylabel('F(V)');
%inner
figure
hold on
pp=plot(uniqueVals,prob,'.',uniqueVals,densityFunc, 'r')
title('Weibull probability density function');
xlabel('v');
ylabel('f(v)');
bar(h)
hold off
%inner
%rose
w=xlsread('rose.xlsx');
dir=w(:,2)*10;
vel=w(:,1);
Options = {'anglenorth','FreqLabelAngle',0,'angleeast','FreqLabelAngle',90,'labels',{'N (0)','S (180)','E (90)','W (270)'},'freqlabelangle',45,'nDirections',20,'nFreq',25,'LegendType',1};
[figure_handle,count,speeds,directions,Table] = WindRose(dir,vel,Options);
close all; clear Options;

After a quick read of the script documentation, here is what I found concerning the creation of the windrose plot:
% With options in a cell array:
Options = {'anglenorth',0,'angleeast',90,'labels',{'N (0°)','S (180°)','E (90°)','W (270°)'},'freqlabelangle',45};
[figure_handle,count,speeds,directions,Table] = WindRose(dir,spd,Options);
% With options in a structure:
Options.AngleNorth = 0;
Options.AngleEast = 90;
Options.Labels = {'N (0°)','S (180°)','E (90°)','W (270°)'};
Options.FreqLabelAngle = 45;
[figure_handle,count,speeds,directions,Table] = WindRose(dir,spd,Options);
close all;
% Usual calling:
[figure_handle,count,speeds,directions,Table] = WindRose(dir,spd,'anglenorth',0,'angleeast',90,'labels',{'N (0°)','S (180°)','E (90°)','W (270°)'},'freqlabelangle',45);
Your error is:
Error using WindRose (line 244)
is not a valid property for WindRose function.
Error in octavetestoforiginalprogram (line 184)
[figure_handle,count,speeds,directions,Table] = WindRose(dir,vel,Options);
And it is being produced within the routine that undertakes option arguments sanitization. Since options must be provided in the form of name-value pairs... it seems that the script is detecting a mismatching number of elements and one or more names with a missing value. And here they are:
Options =
{'anglenorth','FreqLabelAngle',0,'angleeast','FreqLabelAngle',90,'labels',{'N
(0)','S (180)','E (90)','W
(270)'},'freqlabelangle',45,'nDirections',20,'nFreq',25,'LegendType',1};
The two properties marked with a bold font have no value associated to them (unlike the examples in the tutorial) and this probably messes up the whole parametrization process. Probably, the first option being extracted is anglenorth = FreqLabelAngle, which is not correct.

Related

Trying to discretize a continuous signal but I'm trying to plot the regular signal given roots

I need to plot out a function based on roots that I can use poly() to get the polynomial for. However, whenever I run the function, it gives me an error. I want to be able to fix the error so I can continue onto my further goals.
I need to plot the function with respect to the domain of time I provide, plot the function with respect to the sampling index nVec multiplied by the sampling rate deltaT, then plot the discrete signal. I am at a stop right now because I cannot plot the continuous signal (the first plot). It consistently gives me an error. I have tried changing the roots (rootsVec) from negative inclusion to purely positive so I can obtain the equation from poly() as well as put the sampling rate for the increment in time but to no avail.
function [tVec,nVec,xVec] =
fxNthOrderPolyDTSignal(domainVec,noOfSamples,rootsVec)
DSIntervals = noOfSamples - 1;
deltaT = (max(domainVec) - min(domainVec))/DSIntervals;
%time = input("Please input a specific time within the domain: ");
nVec = min(domainVec)/deltaT;
tVec = min(domainVec) + (nVec * deltaT);
Eqtn = poly(rootsVec);
x = linspace(domainVec(1),0.5,max(domainVec));
figure(1)
plot(Eqtn(x),x)
figure(2)
plot(Eqtn,(nVec*deltaT))
end
The expected result is simply a plot of the the signal with the following input arguments:
domainVec = [-10, 10] (this is the time where the signal exists);
noOfSamples = 30;
rootsVec = [-3, 8] (aka a second order polynomial);
The actual result is the following error: Array indices must be positive integers or logical values.
Check this code, with a proper naming of variables, more Signal Processing style...
With n=10 you will start to see the discretization.
function [t,x,dt] = f(tlim,n,p)
%% Function (Press 'Run Section' from here)
% Parameters (Delete these for function to work)
tlim=[-10 10];
n=30;
p=[-3 8];
% Polinomial Coefficients from Roots
a=poly(p);
% Sampling Time
dt=(tlim(2)-tlim(1))/n;
% Evaluate
t=linspace(tlim(1),tlim(2),n)';
x=a(1)*t.^0+a(2)*t.^1+a(3)*t.^2;
% Plot
plot(t,x)
I figured it out. This was the correct answer to my problem. Thank you for your help!
function [tVec,nVec,xVec] =
fxNthOrderPolyDTSignal(domainVec,noOfSamples,rootsVec)
deltaT = (max(domainVec) - domainVec(1))/noOfSamples;
nVec = [0 : noOfSamples];
tVec = [];
for i = nVec
tVec(end + 1) = min(domainVec) + (i*deltaT);
end
nomial = poly(rootsVec);
xVec = polyval(nomial,tVec);
subplot(3,1,1)
plot(tVec,xVec)
title('x(t)')
subplot(3,1,2)
stem(tVec,xVec)
title('x[n]')
subplot(3,1,3)
stem(tVec,tVec*0)
title('x(nDeltaT)')
end

Linear regression -- Stuck in model comparison in Matlab after estimation?

I want to determine how well the estimated model fits to the future new data. To do this, prediction error plot is often used. Basically, I want to compare the measured output and the model output. I am using the Least Mean Square algorithm as the equalization technique. Can somebody please help what is the proper way to plot the comparison between the model and the measured data? If the estimates are close to true, then the curves should be very close to each other. Below is the code. u is the input to the equalizer, x is the noisy received signal, y is the output of the equalizer, w is the equalizer weights. Should the graph be plotted using x and y*w? But x is noisy. I am confused since the measured output x is noisy and the model output y*w is noise-free.
%% Channel and noise level
h = [0.9 0.3 -0.1]; % Channel
SNRr = 10; % Noise Level
%% Input/Output data
N = 1000; % Number of samples
Bits = 2; % Number of bits for modulation (2-bit for Binary modulation)
data = randi([0 1],1,N); % Random signal
d = real(pskmod(data,Bits)); % BPSK Modulated signal (desired/output)
r = filter(h,1,d); % Signal after passing through channel
x = awgn(r, SNRr); % Noisy Signal after channel (given/input)
%% LMS parameters
epoch = 10; % Number of epochs (training repetation)
eta = 1e-3; % Learning rate / step size
order=10; % Order of the equalizer
U = zeros(1,order); % Input frame
W = zeros(1,order); % Initial Weigths
%% Algorithm
for k = 1 : epoch
for n = 1 : N
U(1,2:end) = U(1,1:end-1); % Sliding window
U(1,1) = x(n); % Present Input
y = (W)*U'; % Calculating output of LMS
e = d(n) - y; % Instantaneous error
W = W + eta * e * U ; % Weight update rule of LMS
J(k,n) = e * e'; % Instantaneous square error
end
end
Lets start step by step:
First of all when using some fitting method it is a good practice to use RMS error . To get this we have to find error between input and output. As I understood x is an input for our model and y is an output. Furthermore you already calculated error between them. But you used it in loop without saving. Lets modify your code:
%% Algorithm
for k = 1 : epoch
for n = 1 : N
U(1,2:end) = U(1,1:end-1); % Sliding window
U(1,1) = x(n); % Present Input
y(n) = (W)*U'; % Calculating output of LMS
e(n) = x(n) - y(n); % Instantaneous error
W = W + eta * e(n) * U ; % Weight update rule of LMS
J(k,n) = e(n) * (e(n))'; % Instantaneous square error
end
end
Now e consists of errors at the last epoch. So we can use something like this:
rms(e)
Also I'd like to compare results using mean error and standard deviation:
mean(e)
std(e)
And some visualization:
histogram(e)
Second moment: we can't use compare function just for vectors! You can use it for dynamic system models. For it you have to made some workaround about using this method as dynamic model. But we can use some functions as goodnessOfFit for example. If you want something like error at each step that consider all previous points of data then make some math workaround - calculate it at each point using [1:currentNumber].
About using LMS method. There are built-in function calculating LMS. Lets try to use it for your data sets:
alg = lms(0.001);
eqobj = lineareq(10,alg);
y1 = equalize(eqobj,x);
And lets see at the result:
plot(x)
hold on
plot(y1)
There are a lot of examples of such implementation of this function: look here for example.
I hope this was helpful for you!
Comparison of the model output vs observed data is known as residual.
The difference between the observed value of the dependent variable
(y) and the predicted value (ŷ) is called the residual (e). Each data
point has one residual.
Residual = Observed value - Predicted value
e = y - ŷ
Both the sum and the mean of the residuals are equal to zero. That is,
Σ e = 0 and e = 0.
A residual plot is a graph that shows the residuals on the vertical
axis and the independent variable on the horizontal axis. If the
points in a residual plot are randomly dispersed around the horizontal
axis, a linear regression model is appropriate for the data;
otherwise, a non-linear model is more appropriate.
Here is an example of residual plots from a model of mine. On the vertical axis is the difference between the output of the model and the measured value. On the horizontal axis is one of the independent variables used in the model.
We can see that most of the residuals are within 0.2 units which happens to be my tolerance for this model. I can therefore make a conclusion as to the worth of the model.
See here for a similar question.
Regarding you question about the lack of noise in your models output. We are creating a linear model. There's the clue.

Measuring peaks and the distance between them in my plot

I will keep the explanation, how my codes works, very short. I advise you to try this code yourself, so perhaps you understand it better that way. I have an audio-file and read it in my code. Now i switch from the time domain to the frequency domain by using the function FFT. But the only difference is, that i am performing an STFT on my audio signal. I do it every 30ms, until to the length of my signal. I am aware, that there are many different function in matlab, which also can perform this easily, but there are not giving me the results i need. Now, i am plotting many different frequency spectrums every 30ms. But i split up my signal in three frequency bands. They are called LOW, MEDIUM and HIGH. Basically, this means I have 3 different spectrums plotting every 30ms. The next step I do, is summing all the magnitudes from ONE frequency spectrum together, this means I have ONE VALUE per frequency spectrum, which are being squared.
Now, i have the power from every spectrum ! And all of these values are being plotted in my code. I am only plotting the power values, otherwise my code performance time would be extremely slow.
Btw, the code looks long, but there are two for loop. In the first, i read the low spectrum and when it is finished, the second starts with the medium and high spectrum. Basically they are the same. I am aware, i can probably do that with findpeaks or something similar. But how can i write/pull that of? Or what the necessary steps to do that. At the end, i included a file, Hopefully you can see that.
I want to measure the peaks and get the distance between them from the red plot.
EDIT:
Ok, i got the peaks, but not in the way i imagined. I want to show the peaks, which are above 5000-line. Sorry for not being clear at the beginning. See my plot, what i mean. I want to say my code, that only the peaks should be measured, which are above the 5000-line.
[pks, locs] = findpeaks(ValuesOfYc);
p=plot(x,ValuesOfYc,'r-' ,x(locs), pks,'ob');
This is, what I did above, in my first loop. How should i go on from there?
clear;
clc;
%% MATLAB
%% read file
%_________________________________________
[y,fs]=audioread('Undertale - Megalovania.wav');
% audioread = read wav -file
% y = contains the audio signal
% fs = 44100
% 'UnchainMyHeart' = name of the wav-file
%_________________________________________
%% PARAMETER FOR STFT
%_________________________________________
t_seg=0.03; % length of segment in ms
fftlen = 4096; %FFT-Points
% Defining size of frequency bands
f_low= 1:200; %lower frequencies
f_medium= 201:600; %medium frequencies
f_high= 601:1000; %higher frequencies
%__________________________________________
%% CODE
segl =floor(t_seg*fs);
windowshift=segl/2;
% defining the size of the window shift
window=hann(segl);
% apply hann function on segment length (30 ms)
window=window.';
% transpose vector
si=1;
% defining start index
ei=segl;
% defining end index
N=floor( length(y)/windowshift - 1);
% Calculates the number, how often the window has to shift
% until to length of the audio signal
f1=figure;
% Generating new window
f=0:1:fftlen-1;
f=f/fftlen*fs;
% defining frequency vector
Ya=zeros(1,fftlen);
ValuesOfYc = NaN(1,N);
ValuesOfYd = NaN(1,N);
ValuesOfYe = NaN(1,N);
x =(1:N)*windowshift/fs;
% defining x-axis
for m= 1:1:N
y_a = y(si:ei);
% a segment is taken out from audio signal length(30ms)
y_a= y_a.*window;
% multiplying segment with window (hanning)
Ya=fft(y_a, fftlen);
% Applying fft on segment
Yb=abs(Ya(1:end/2)).^2;
% Squaring the magnitudes from one-sided spectrum
drawnow; % Updating the graphical values
figure(f1);
% Showing the power values
%% frequency bands
y_low = Yb(f_low); % LOW frequency spectrum
Yc=sum(y_low);
% Summing all the power values from one frequency spectrum together
% so you get one power value from one spectrum
ValuesOfYc(m) = Yc;
%Output values are being saved here, which are generated from the for
%loop
% m = start variable from for loop
[pks, locs] = findpeaks(ValuesOfYc);
subplot(2,1,1)
p=plot(x,ValuesOfYc,'r-', x(locs(pks>=5000)), pks(pks>=5000),'ob');
p(1).LineWidth =0.5;
xlabel('time (Audio length)')
ylabel('Power')
grid on
si=si+windowshift;
% Updating start index
ei=ei+windowshift;
% Updating end index
end
for o= 1:1:N
y_a = y(si:ei);
% a segment is taken out from audio signal length(30ms)
y_a= y_a.*window;
% multiplying segment with window (hanning)
Ya=fft(y_a, fftlen);
% Applying fft on segment
Yb=abs(Ya(1:end/2)).^2;
% Squaring the magnitudes from one-sided spectrum
drawnow; % Updating the graphical values
figure(f1);
% Showing the power values
[![enter image description here][1]][1]
%% frequency bands
y_medium = Yb(f_medium); % MEDIUM frequency spectrum
y_high = Yb(f_high); % HIGH frequency spectrum
Yd=sum(y_medium);
Ye=sum(y_high);
% Summing all the power values from one frequency spectrum together
% so you get one power value from one spectrum
ValuesOfYd(o) = Yd;
ValuesOfYe(o) = Ye;
%Output values are being saved here, which are generated from the for
%loop
% m = start variable from for loop
subplot(2,1,2)
p=plot(x, ValuesOfYd,'g-', x, ValuesOfYe,'b-' );
p(1).LineWidth =0.5;
xlabel('time (Audio length)')
ylabel('Power')
grid on
si=si+windowshift;
% Updating start index
ei=ei+windowshift;
% Updating end index
end

How to do a frequency band?

Here in this code i am doing a stft on my wav-file. There is no problem with that. At the beginning, i am defining my parameter, afterwards using my wav file and then applying the stft. Basically what i am doing is a real-time spectral analysis. Anyway my question is, how do i a frequency band? I want my signal to be separated in LOW/MEDIUM/HIGH. I want my vector to be saved, from 0-250 Hz in the LOW-Band, 250-5000 Hz in the MEDIUM-Band, 5-22.05k Hz in the HIGH-Band. I advise you, to try my code in Matlab, if you don't understand it. Just take any wav-file. Btw my signal is plotted in the variable "Yres". Any solution is appreciated!
NFA=2; % Number is used for plotting every 2nd picture
t_seg=0.05; % Length of segment in ms
fftlen = 4096;
% Lenght of "fft",because our segment contains 2205 points
[y,fs]=audioread('UnchainMyHeart.wav');
% audioread = functions reads WAV-file
% y = A vector which contains my audio signal
% fs = sample frequency (44100)
% 'UnchainMyHeart' = WAV-file
t=linspace(0,length(y)/fs,length(y));
% linspace = Creating time vector
% 0 = Start time
% length(y)/fs = End time
% length(y) = Number of samples in y
plot(t,y)
% plotting signal in the time domain
segl =floor(t_seg*fs);
% Applying fft function on the variable "segl"
windowshift=segl/2;
% Defining the size of the window, which goes to the next "segl"
window=hann(segl);
% hann function
window=window.';
si=1;
%Start index
ei=segl;
%End index
AOS= length(y)/windowshift - 1;
% AOS is the number of "segl" we use (About 433)
f1=figure;
% Opening new window
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
% Defining frequency vector
Ya=zeros(1,fftlen);
plot(f,Ya),axis([0 fs -90 50])
grid on
n=0;
%start variable
for m= 1:1:AOS
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
n=n+1;
if n==1
Yres=abs(Ya);
else
Yres=Yres+abs(Ya);
end
if n==NFA
Yres=Yres/NFA;
n=0;
drawnow;
%Tut die Grafikobjekte immer auf den neuesten Stand updaten
figure(f1);
plot(f(1:end/2), 20*log10(abs(Yres(1:end/2))));
ylim([-90 50]);
title('Spektrum eines Audiosignal');
xlabel('f(Hz)');
ylabel('dB');
grid on;
end
si=si+windowshift;
% Updating start index
ei=ei+windowshift;
% Updating end index
end
This may not be the best answer! But this may help you get started on something. You can use spectrogram() function from MATLAB's Signal Processing Toolbox.
Let's suppose you have an audio file named ''UnchainMyHeart.wav'(in your case) with one channel. The code goes as follows:
% Reading the audio file
[y1,fs] = audioread('UnchainMyHeart.wav');
% Parameters for STFT (or spectrogram)
windowDuration = 30e-3; overlapDuration = 15e-3;
windowLength = round(windowDuration*fs); % window length
overlapLength = round(overlapDuration*fs); % overlapping of windows
nfft = 1024;
% Executing STFT for the signal
[S1,F1,T1,P1] = spectrogram(x1,hanning(windowLength), ...
overlapLength, nfft, fs, 'yaxis');
S1 and P1 contain STFT and Power Spectrum Density(PSD) of the signal for a time interval of each section with a time interval whose estimations are contained in T1.
For your question, you are looking for F1 which is a vector of cyclical frequencies expressed in terms of sampling frequency, fs. For example: if you have a sampling frequency of 48 kHz (fs) and nfft of 1024, then you will have 513 [(1024/2) +1)] frequency values spaced by (fs/nfft). i.e. 46.875. So your frequency components will be 0, 46.875, 46.875*2, ..., 46.875*512. The maximum you will have is 24 kHz due to Nyquist criterion.
Now, you can easily write a simple routine specifying the ranges as you said. The same technique can be used in your code which is an implementation of stft. I would suggest using MATLAB's built-in function unless your problem requires an implementation. Hope this helps!
If needed, I can answer why the parameters for STFT are chosen as included in the code.

How to compute the Cumulative Distribution Function of an image in MATLAB

I need to compute the Cumulative Distribution Function of an image. I normalized the values using the following code:
im = imread('cameraman.tif');
im_hist = imhist(im);
tf = cumsum(im_hist); %transformation function
tf_norm = tf / max(tf);
plot(tf_norm), axis tight
Also, when the CDF function is plotted, does the plot have to be somewhat a straight line which ideally should be a straight line to represent equal representation for pixel intensities?
You can obtain a CDF very easily by:
A = imread('cameraman.tif');
[histIM, bins] = imhist(A);
cdf = cumsum(counts) / sum(counts);
plot(cdf); % If you want to be more precise on the X axis plot it against bins
For the famous cameraman.tif it results in:
As for your second question. When the histogram is perfectly equalized (i.e. when at each intensity correspond roughly the same number of pixels) your CDF will look like a straight 45° line.
EDIT: Strictly speaking cumsum alone is not a proper CDF as a CDF describe a probability, hence it must obey probability axioms. In particular the first axiom of probability tell us that a probability value should lie in the range [0 ... 1] and cumsum alone does not guarantee that.
function icdf = imgcdf(img)
% Author: Javier Montoya (jmontoyaz#gmail.com).
% http://www.lis.ic.unicamp.br/~jmontoya
%
% IMGCDF calculates the Cumulative Distribution Function of image I.
% Input parameters:
% img: image I (passed as a bidimensional matrix).
% Ouput parameters:
% icdf: cumulative distribution function.
%
% See also: IMGHIST
%
% Usage:
% I = imread('tire.tif');
% icdf = imgcdf(I);
% figure; stem(icdf); title('Cumulative Distribution Function (CDF)');
if exist('img', 'var') == 0
error('Error: Specify an input image.');
end
icdf = [];
ihist = imghist(img);
maxgval = 255;
icdf = zeros(1,maxgval);
icdf(1)= ihist(1);
for i=2:1:maxgval+1
icdf(i) = ihist(i) + icdf(i-1);
end
end
Its not my code but it works for me! Also check the cdf function in the statistics toolbox