plot gmdistribution.fit together with data - matlab

I have a histogram of data (x,y) which is a mixed of two Gaussians (simple case i.e in one dimension). To get a fit to it, i use
obj= gmdistribution.fit(data,2)
that gives me the
obj =
Gaussian mixture distribution with 2 components in 1 dimensions
Component 1:
Mixing proportion: 0.499387
Mean: -0.4789
Component 2:
Mixing proportion: 0.500613
Mean: -0.4786
Now, how can I plot this together with the original histogram? I am aware of these 2 links but they dont help me so much:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/317868
http://www.mathworks.de/de/help/stats/gmdistribution.fit.html
Any clear help is highly appreciated!

I guess this might be a bit late, but its been updated on matlabs site. Just in case
MU1 = [1 2];
SIGMA1 = [2 0; 0 .5];
MU2 = [-3 -5];
SIGMA2 = [1 0; 0 1];
X = [mvnrnd(MU1,SIGMA1,1000);mvnrnd(MU2,SIGMA2,1000)];
scatter(X(:,1),X(:,2),10,'.')
hold on
options = statset('Display','final');
obj = gmdistribution.fit(X,2,'Options',options);
10 iterations, log-likelihood = -7046.78
h = ezcontour(#(x,y)pdf(obj,[x y]),[-8 6],[-8 6]);
You could do the same for 3d using scatter3.

Related

How to plot a Diagonal Histogram in Matlab

Given scatter data, or a matrix, I would like to generate a nice plot such as the one shown below, with all 3 histograms and a colored matrix. I'm specifically interested in the diagonal histogram, which ideally, would correspond to the diagonals of a matrix:
Source figure: www.med.upenn.edu/mulab/jpst.html
The existing command scatterhist is not that powerful to generate this type of graph. Any ideas?
Thanks!
EDIT:
Following #Cris Luengo's hints, I came up with the following code which does some first work at the inclined histogram: WORK IN PROGRESS (HELP WELCOME)!!
b = [0 1 2 3 4 5 6 7 8 9 10];
h = [0.33477 0.40166 0.20134 0.053451 0.008112 0.000643 2.7e-05 0 0 0 0];
wid = 0.25; bb = sort([b-wid b-wid b+wid b+wid]);
kk = [zeros(numel(h),1) h(:) h(:) zeros(numel(h),1)];
kk = reshape(kk',[1,numel(kk)]);
pp=patch(bb,kk,'b');axis([-.5 5 0 .5])
set(gca,'CameraUpVector',[-1,.08,0]);axis square
EDIT 2: Using rotation
phi = pi/4;
R = [cos(phi),-sin(phi);sin(phi),cos(phi)];
rr = [bb' kk'] * R;
bb = rr(:,1); kk = rr(:,2);
patch(bb,kk,'b'); axis([-.5 3 -4 .5])
Here is a recipe to plot the diagonal histogram, if you can do that I’m sure you can figure out the rest too.
Compute the histogram, the bin counts are h, the bin centers are b.
Build a coordinate matrix, attaching the coordinates of a point on the x-axis at the left and right ends of the histogram:
coords = [b(:),h(:)];
coords = [coord;b(end),0;b(1),0];
Using patch you can now plot the histogram as follows:
patch(coords(1,:),coords(2,:));
To plot a rotated histogram you can simply multiply the coords matrix with a rotation matrix, before using patch:
phi = pi/4;
R = [cos(phi),-sin(phi);sin(phi),cos(phi)];
coords = R * coords;
You might need to shift the plot to place it at the right location w.r.t. the other elements.
I recommend that you place all these graphic elements in the same axes object; you can set the axes’ visibility to 'off' so that it works only as a canvas for the other elements.
It will be a bit of work to get everything placed as in the plot you show, but none of it is difficult. Use the low-level image, line,patch and text to place those types of elements, don’t try to use the higher-level plotting functions such as plot, they don’t provide any benefits over the low-level ones in this case.

Extrapolate from triangulation

Suppose we have five vertices:
X = [0 1;
2 1;
4 1;
1 0;
3 0];
a triangulation:
T = [1 4 2;
4 5 2;
5 3 2];
and function values defined on the vertices:
Fx = [1;
2;
3;
4;
-5];
then we can easily compute the function value for any point inside the triangle by using the barycentric coordinates. For point P = [1 .5], which lies in the first triangle, the barycentric coordinates are B = [.25 .5 .25], so the function evaluates to Fxi = 1/4 + 4/2 + 2/4 = 2.75.
However, I have difficulty to see how one would extrapolate this surface. We could find the closest triangle and extrapolate from that. The problem is that this results in a discontinuous function. Consider e.g. point P = [2 2]. According to triangle 1, its value would be -0.5, whereas according to triangle 3 its value would be 9.5.
Is there a "standard" or generally accepted approach to extrapolate from piecewise linear functions? Any pointers to existing material also greatly appreciated.
A possibility is Shepard's method:
https://en.wikipedia.org/wiki/Inverse_distance_weighting
The resulting function interpolates the input values defined at the vertices and is non-linear but continuous everywhere else.
The choice p=2 usually gives decent results.
Another technique to look for are "Barycentric coordinates for non-convex polygons".
The following publication shows (page 8 etc.) how the weight functions behave outside the polygons
https://www.in.tu-clausthal.de/fileadmin/homes/techreports/ifi0505hormann.pdf
However, even this solution does not behave piecewise-linear on your given triangulation.

Sliding window for matlab

The intention is to estimate in a [3 3] sliding window. 0.5*[(A(i)-A(5))^2] is computed where a(i) is the pixels around center pixel a(5).
The mean of each of these 8 half square differences is stored in the center pixel's location.
To tackle this conv2 and nlfilter were used on a training example matrix as follows.
clc;
close all;
clear all;
A = [1 2 3 4 5 6;5 4 6 3 2 1;2 3 2 1 4 5];
kernel = [-1 -1 -1; -1 8 -1; -1 -1 -1];
outputImage = conv2(A, kernel);
fun = #(x) mean(x(:));
B= nlfilter (outputImage,[3 3],fun);
The initial idea was to calculate the difference and store it in the location of the pixels instead of the center pixel. Then use a sliding window to take mean of those differences and replace the center pixel.
It was apparent that my logic was flawed.
Though i was able to calculate the difference(i first tried to see simple difference was possible for me) i had to deal with data being overwritten. moreover this method will create a matrix larger than the original which is also wrong.
the function mean and the kernel you are using are both linear and do not represent the non-linear operation you are trying to achieve.
One way of using conv and mean is by computing the 8 differences as different output channels
ker = cell(1,8);
for ii=1:8
ker{ii} = zeros(3);
ker{ii}(2,2) = 1; %// for a(5)
if ii < 5
ker{ii}(ii) = -1;
else
ker{ii}(ii+1) = -1;
end
end
interim = zeros( [size(A,1) size(A,2), numel(ker)] ); % allocate room for intermidiate results
for ii=1:numel(ker)
interim(:,:,ii) = conv2(A, ker{ii}, 'same' ); %//'same' takes care of output size for you
end
Now interim holds each of the different a(5)-a(i) we are ready for the non-linear operation
interim = interim.^2;
B = 0.5 * interim;

How can I plot filled rectangles as a backdrop for a desired target in MATLAB?

I have two datasets, one of which is a target position, and the other is the actual position. I would like to plot the target with a +/- acceptable range and then overlay with the actual. This question is only concerning the target position however.
I have unsuccessfully attempted the built in area, fill, and rectangle functions. Using code found on stackoverflow here, it is only correct in certain areas.
For example
y = [1 1 1 2 1 1 3 3 1 1 1 1 1 1 1]; % Target datum
y1 = y+1; %variation in target size
y2 = y-1;
t = 1:15;
X=[t,fliplr(t)]; %create continuous x value array for plotting
Y=[y1,fliplr(y2)]; %create y values for out and then back
fill(X,Y,'b');
The figure produced looks like this:
I would prefer it to be filled within the red boxes drawn on here:
Thank you!
If you would just plot a function y against x, then you could use a stairs plot. Luckily for us, you can use the stairs function like:
[xs,ys] = stairs(x,y);
to create the vectors xs, ys which generate a stairs-plot when using the plot function. We can now use these vectors to generate the correct X and Y vectors for the fill function. Note that stairs generates column vectors, so we have to transpose them first:
y = [1 1 1 2 1 1 3 3 1 1 1 1 1 1 1]; % Target datum
y1 = y+1; %variation in target size
y2 = y-1;
t = 1:15;
[ts,ys1] = stairs(t,y1);
[ts,ys2] = stairs(t,y2);
X=[ts.',fliplr(ts.')]; %create continuous x value array for plotting
Y=[ys1.',fliplr(ys2.')]; %create y values for out and then back
fill(X,Y,'b');
Again, thank you hbaderts. You answered my question perfectly, however when I applied it to the large data set I needed for, I obtained this image
https://dl.dropboxusercontent.com/u/37982601/stair%20fill.png
I think it is because the fill function connects vertices to fill?
In any case, for the potential solution of another individual, combined your suggested code with the stair function and used the area function.
By plotting them on top of one another and setting the color of the lower area to be white, it appears as the rectangular figures I was after.
%sample code. produces image similar to o.p.
y = [1 1 1 2 1 1 3 3 1 1 1 1 1 1 1];
y1 = y+1;
y2 = y-1;
t = 1:15;
[ts,ys1] = stairs(t,y1);
[ts,ys2] = stairs(t,y2);
area(ts,ys1,'FaceColor','b','EdgeColor','none')
hold on
area(ts,ys2,'FaceColor','w','EdgeColor','none')
https://dl.dropboxusercontent.com/u/37982601/stair%20area.png
Thanks again for your help and for pointing me in the right direction!

how to take an average of a 2x2 pixel block?

I have an image and I have to take the average of the color of 2x2 pixel.
take the average color of a 2x2 pixel block, then compute the distance between the colors in the image and the colors available for our use.
I have no idea what taking the average of 2x2 pixel block means. How to solve this?
Thank you.
You can process non-overlapping blocks of an image using blockproc
Im = imread('coins.png'); %// example image
fun = #(block_struct) mean( block_struct.data(:) ); %// anonymous function to get average of a block
B = blockproc(Im,[2 2],fun); %// process 2 by 2 blocks
imshow(B,[]); %// show resulting image
One other method I can suggest is to use combination of colfilt with the 'sliding' flag and mean as the function to operate on. The 'distinct' flag is what you actually need to use, but if you see the conversation between myself and #eigenchris, we couldn't get it to work. Still, eigenchris has shown that this is 300x faster than blockproc.
Therefore, assuming your image is stored in im, you can simply do:
out = uint8(colfilt(im, [2 2], 'sliding', #mean));
out2 = out(1:2:end,1:2:end);
The reason why you would need to subsample the results is because when we apply a sliding option, you have overlapping blocks processing the image at a time. Because you want distinct blocks, you only need 1/4 of the image because you have decomposed the image into 2 x 2 blocks. Within a 2 x 2 block, if you did the sliding option, you would have three other results that are not required, and so doing the subsampling above by a factor of two eliminates those three other blocks that give results.
Note that you'll need to cast the result as the output will be of type double.
Going with the discussion between myself and eigenchris, you can replace colfilt with the canonical imfilter to replicate the first line of the above code. I managed to get an 8x speedup on my machine when comparing the two together. Therefore:
out = imfilter(im, [0.25 0.25; 0.25 0.25], 'replicate');
out2 = out(1:2:end,1:2:end);
In terms of speedup, I wrapped each call in an anonymous function, then used timeit to time the functions:
>> f = #() uint8(colfilt(im, [2 2], 'sliding', #mean));
>> g = #() imfilter(im, [0.25 0.25; 0.25 0.25], 'replicate');
>> T = timeit(f);
>> T2 = timeit(g);
>> T/T2
ans =
7.5421
As you can see, there is roughly a 8x speedup over colfilt... most likely because it's calling im2col and col2im under the hood.
Using loops: (another method, just for knowing)
A = imread('cameraman.tif');
i = 1; j = 1;
[rows, cols] = size(A);
C(rows/2,cols/2) = 0;
for x = 1:2:rows
for y = 1:2:cols
block = [A(x,y),A(x+1,y),A(x,y+1),A(x+1,y+1)];
C(i,j) = mean(block(:));
j = j+1;
end
i = i+1;
j = 1;
end
C = uint8(C);
figure;
imshow(A); %// show original image
figure;
imshow(C); %// show resulting image