MATLAB - Approximating the integral with hemisphere domain with sample data - matlab

The integral part of the rendering equation performs an integral over a hemisphere range (with respect to solid angle).
I can generate samples that carry the value of corresponding integrand with this code:
n = 10;
rho_s = 0.5;
rho_d = 0.5;
light_phi = degtorad(30);
light_theta = degtorad(60);
[lx ly lz] = sph2cart(light_phi, light_theta, 1);
refDir = cat(3, -lx, -ly, lz);
normal = cat(3, 0, 0, 1);
[sample_phi sample_theta] = meshgrid(0:12:360, 0:3:90);
[sample_x sample_y sample_z] = sph2cart(degtorad(sample_phi), degtorad(sample_theta), 1);
viewDir = cat(3, sample_x, sample_y, sample_z);
dotRL = sum(bsxfun(#times, viewDir, refDir), 3);
dotRL = max(dotRL, 0);
brdf_s = rho_s*(n+2)*(dotRL.^n)/(2*pi);
brdf_d = rho_d/pi;
brdf = brdf_s + brdf_d;
x = sample_x.*brdf; y = sample_y.*brdf; z = sample_z.*brdf;
mesh(x, y, z);
line([0 lx],[0 ly],[0 lz]);
axis equal; axis vis3d;
xlim([-1 1]); ylim([-1 1]); zlim([0 1]);
The question I face now is how to do the integral or approximation with these samples?

Related

how to draw random points inside an ellipse matlab

I want to fill this ellipse with N random points inside it
any help I'd be glad
clear ,close all;
xCenter = 15;
yCenter = 10;
xRadius = 3.5;
yRadius = 8;
theta = 0 : 0.01 : 2*pi;
N = 100; % N rand points
x = xRadius * cos(theta) + xCenter;
y = yRadius * sin(theta) + yCenter;
plot(x, y, 'LineWidth', 1);
axis square;
grid on;
I tried this code to generate 100 points inside the ellipse with specific parameters but I did not achieve my goal,
xCenter = 5;
yCenter = 3;
xRadius = 3.5;
yRadius = 8;
theta = 0 : 0.01 : 2*pi;
N = 100;
x = xRadius * cos(theta) + xCenter;
y = yRadius * sin(theta) + yCenter;
xq=(rand(N,1)*(2*yRadius) - yRadius);
yq=(rand(N,1)*(2*yRadius) - yRadius);
in = inpolygon(xq,yq,x,y);
hold on
inX = xq(in);
inY = yq(in);
outX = xq(~in);
outY = yq(~in);
plot(inX, inY , 'ro');
plot(outX, outY, 'b*');
plot(x, y, 'LineWidth', 1);
axis square;
grid on;
Sardar's answer produces points not evenly distributed within the ellipse. This code produces an even distribution of points:
xCenter = 15;
yCenter = 10;
xRadius = 3.5;
yRadius = 8;
N = 100;
% Generate points in the ellipse
t = 2*pi * rand(N,1);
d = sqrt(rand(N,1));
x = xCenter + xRadius * d .* cos(t);
y = yCenter + yRadius * d .* sin(t);
plot(x,y,'o')
The difference is the sqrt on the normalized (0 to 1) distance from the origin d. By computing this square root, you increase the density of points closer to the edge of the ellipse. This compensates for points otherwise being too dense close to the center. The uniform distribution of points along that normalized distance is what causes higher density of points near the center.
Generate random numbers for x and y axes between the specified limits, i.e. xRadius and yRadius, for the respective axes. Read Random Numbers Within a Specific Range to understand how to generate those random numbers.
hold on;
RndAngles = rand(N,1); %Same angle should be used
Xpoints = (xRadius.*rand(N,1) .*cos(2*pi*RndAngles))+ xCenter;
Ypoints = (yRadius.*rand(N,1) .*sin(2*pi*RndAngles))+ yCenter;
plot(Xpoints,Ypoints,'o'); %Plot those points
Output:

matlab image rotation code

I'm beginner in computer vision. I'm trying to do a rotate transformation using matlab. My code is
I = imread('Koala.jpg');
rows = size(I, 1);
cols = size(I, 2);
deg = 45;
deg = deg * pi / 180;
C = uint8(zeros(size(I)));
mid = ceil([rows+1 cols+1] / 2);
[x1, x2] = meshgrid(1:rows, 1:cols);
M = [cos(deg) sin(deg); -sin(deg) cos(deg)];
X = bsxfun(#minus, [x1(:) x2(:)], mid) * M;
X = round(bsxfun(#plus, X, mid));
x1 = X(:, 1);
x2 = X(:, 2);
x1(x1<1) = 1;
x2(x2<1) = 1;
x1(x1>rows) = rows;
x2(x2>cols) = cols;
X = [x1(:) x2(:)];
m = 1;
for i=1:rows
for j=1:cols
C(X(m, 1), X(m, 2), :) = I(i, j, :);
m = m + 1;
end
end
This works but in the result there are many pixeles without values. I guess, when I do "X2 = X*M", the range of the image on the transformation it's not same of the source and many values lost
If you have the Image Processing Toolbox, I would just use imrotate to do the rotation for you.
out = imrotate(I, 45);
Otherwise, I would try to vectorize your approach and use interp2. You can rotate all of the pixel centers by the specified angle and then sample at these rotated point.
% Compute the coordinates of all pixel centers
[x, y] = meshgrid(1:size(I, 2), 1:size(I, 1));
% Compute the rotation matrix
R = [ cos(deg) sin(deg);
-sin(deg) cos(deg)];
xy = [x(:), y(:)];
% Compute the middle point
mid = mean(xy, 1);
% Subtract off the middle point
xy = bsxfun(#minus, xy, mid);
% Rotate all of these coordinates by the desired angle
xyrot = xy * R;
% Reshape the coordinate matrices
xy = reshape(xy, [size(x), 2]);
xyrot = reshape(xyrot, [size(x), 2]);
% Interpolate the image data at the rotated coordinates
out = interp2(xy(:,:,1), xy(:,:,2), I, xyrot(:,:,1), xyrot(:,:,2));

Graphically represent density of iterations

Kind all,
I am working in MATLAB and I'm using Monte Carlo techniques to fit a model. Basically, if we assume that my model is a simple function such as
y=m*x^2+c
And that both my parameters m and c vary between 0.5 and 10, I may randomly draw from such a parameter space and obtain each time a new y. If I plot all my realizations of y I obtain something similar to the following figure:
Is there a way to represent the DENSITY of the realizations? I mean, is there a way (instead of plotting all the realizations) to obtain some kind of contour plot that lies between the minimum of my iterations and the maximum for which its color represents the amount of realizations that fall within a certain interval?
Thanks all!
This isn't very pretty, but you could vary the parameters and play with the scatter/plotting, to make it a bit more visually appealing.
Also I assumed a gaussian distribution instead of your random one (totally random coloring will give you a uniform density). Also this code could be optimized for speed.
n = 1000;
l = 100;
x = linspace(1, 10, l);
y = repmat(x.^2, n, 1);
c = repmat(normrnd(1, 1, n, 1), 1, l);
m = repmat(normrnd(1, 1, n, 1), 1, l);
y = y.*m + c;
p = plot(y', '.');
figure; hold on;
for i = 1:l
[N,edges,bin] = histcounts(y(:, i));
density = N./sum(N);
c = zeros(n, 3);
for j = 1:n
c(j, :) = [1-density(bin(j))/max(density), 1-density(bin(j))/max(density), 1-density(bin(j))/max(density)];
end
scatter(ones(n, 1)*x(i),y(:, i),[],c,'filled');
end
Gives
This creates a histogram of y values for every position in x, then calculates the probability density for each y-value and colors in the points. Here, the y-values for every position x are normalized individually, to color the points according to the overall density of the plot you need to renormalize.
You can calculate y for discrete points of x, while setting random values for c and m. Then using hist function you can find a "not-normalized density" of function values for a given x. You can then normalize it to get a real density of the values, so that the overall area under the distribution curve sums up to 1.
In order to visualize it, you construct a mesh grid [X, Y] along the values of x and y and put the density values as Z. Now you can either plot the surf or its contour plot.
Here is the code:
clear;
n = 1000000; %number of simulation steps
%parameter ranges
m_min = 0.5; m_max = 10;
c_min = 0.5; c_max = 10;
%x points
x_min = 1; x_max = 4; x_count = 100;
x = linspace(x_min, x_max, x_count);
x2 = x.^2;
y_min = 0; y_max = m_max*x_max*x_max + c_max; y_step = 1;
m = rand(n, 1)*(m_max - m_min) + m_min;
c = rand(n, 1)*(c_max - c_min) + c_min;
c = repmat(c, 1, x_count);
y = m*x2 + c;
x_step = (x_max- x_min)/(x_count-1);
[X, Y] = meshgrid(x_min:x_step:x_max, y_min-y_step:y_step:y_max+y_step);
Z = zeros(size(X));
bins = y_min:y_step:y_max;
for i=1:x_count
[n_hist,y_hist] = hist(y(:, i), bins);
%add zeros on both sides to close the profile
n_hist = [0 n_hist 0];
y_hist = [y_min-y_step y_hist y_max+y_step];
%normalization
S = trapz(y_hist,n_hist); %area under the bow
n_hist = n_hist/S; %scaling of the bow
Z(:, i) = n_hist';
end
surf(X, Y, Z, 'EdgeColor','none');
colormap jet;
xlim([x_min x_max]);
ylim([y_min y_max]);
xlabel('X');
ylabel('Y');
figure
contour(X,Y,Z, 20);
colormap jet;
colorbar;
grid on;
title('Density as function of X');
xlabel('X');
ylabel('Y');
Another interesting view is a plot of each section depending on the x value:
Here is the code for this plot:
clear;
n = 1000000; %number of simulation steps
%parameter ranges
m_min = 0.5; m_max = 10;
c_min = 0.5; c_max = 10;
%x points
x_min = 1; x_max = 4; x_count = 12;
x = linspace(x_min, x_max, x_count);
x2 = x.^2;
m = rand(n, 1)*(m_max - m_min) + m_min;
c = rand(n, 1)*(c_max - c_min) + c_min;
c = repmat(c, 1, x_count);
y = m*x2 + c;
%colors for the plot
colors = ...
[ 0 0 1; 0 1 0; 1 0 0; 0 1 1; 1 0 1; 0 0.75 0.75; 0 0.5 0; 0.75 0.75 0; ...
1 0.50 0.25; 0.75 0 0.75; 0.7 0.7 0.7; 0.8 0.7 0.6; 0.6 0.5 0.4; 1 1 0; 0 0 0 ];
%container for legend entries
legend_list = cell(1, x_count);
for i=1:x_count
bin_number = 30; %number of histogramm bins
[n_hist,y_hist] = hist(y(:, i), bin_number);
n_hist(1) = 0; n_hist(end) = 0; %set first and last values to zero
%normalization
S = trapz(y_hist,n_hist); %area under the bow
n_hist = n_hist/S; %scaling of the bow
plot(y_hist,n_hist, 'Color', colors(i, :), 'LineWidth', 2);
hold on;
legend_list{i} = sprintf('Plot of x = %2.2f', x(i));
end
xlabel('y');
ylabel('pdf(y)');
legend(legend_list);
title('Density depending on x');
grid on;
hold off;

Matlab scatter and histogram plot

I have 20 numerical data points with x and y coordinates. I would like to plot them in a 2D plot. They will be concentrated around an x and y coordinate. To better visualise this behaviour, I would like to add histogram bars on top of the 2D scatter plot for the x axis, and histogram bars on the right of the 2D plot for the y axis this way, they do not interfere with the axis labels. Now, my 20 numerical points are in fact two sets of 10 and I would like to have both sets plotted in different colours. Something like this:
python plot
How can I do this?
Update:
FWHM11Avg = [3.88,3.43,3.16,3.22,3.73,2.43,2.88,3.01,3.59,2.17];
FWHM11Med = [4.4,3.1,3,3.15,3.9,2,3.00,2.85,3.85,2.2];
FWHM12Avg = [3.50,2.30,2.97,2.97,2.98,2.28,2.94,2.36,3.51,1.7];
FWHM12Med = [3.3,2.1,2.9,2.8,2.9,2.1,2.8,2.30,3.5,1.7];
minx = min([FWHM11Avg; FWHM11Med]);
maxx = max([FWHM11Avg; FWHM11Med]);
miny = min([FWHM12Avg; FWHM12Med]);
maxy = max([FWHM12Avg; FWHM12Med]);
% make figure
figure(1)
clf
% first subplot -- y-data histc
ah1 = subplot(2, 2, 1);
y_bins = 1.5:.25:4.5;
n = hist(FWHM12Avg, y_bins);
bar(y_bins, n, 'vertical', 'on')
hold on
hist(FWHM12Med, y_bins)
bar(y_bins, n, 'vertical', 'on')
% x-data histc
ah2 = subplot(2, 2, 4);
x_bins = 1.5:.25:4.5;
n = hist(FWHM11Avg, x_bins);
bar(x_bins, n, 'horizontal', 'on')
hold on
n = hist(FWHM11Med, x_bins);
bar(x_bins, n, 'horizontal', 'on')
% scatterplot
ah3 = subplot(2, 2, 2);
hold on
scatter(FWHM11Avg, FWHM11Med)
scatter(FWHM12Avg, FWHM12Med)
% link axes, adjust histc orientation
linkaxes([ah1, ah3], 'y')
linkaxes([ah3, ah2], 'x')
set(ah3,'XLim',[minx, maxx]);
set(ah3,'YLim',[miny, maxy]);
ah1.Box = 'off';
ah1.View = [180, -90];
ah1.Visible = 'off';
ah2.Visible = 'off';
ah2.Box = 'off';
ah2.View = [0, -90];
Also there seems not to be an option available for adding numerical axes to the histograms to see how many points there are in a bar - at least in the documentation I did not see any option. Is that so?
Second Update with applied suggestions to the above syntax:
FWHM11Avg = [3.88,3.43,3.16,3.22,3.73,2.43,2.88,3.01,3.59,2.17];
FWHM11Med = [4.4,3.1,3,3.15,3.9,2,3.00,2.85,3.85,2.2];
FWHM12Avg = [3.50,2.30,2.97,2.97,2.98,2.28,2.94,2.36,3.51,1.7];
FWHM12Med = [3.3,2.1,2.9,2.8,2.9,2.1,2.8,2.30,3.5,1.7];
minx = min([FWHM11Avg; FWHM11Med]);
maxx = max([FWHM11Avg; FWHM11Med]);
miny = min([FWHM12Avg; FWHM12Med]);
maxy = max([FWHM12Avg; FWHM12Med]);
% make figure
figure(1)
clf
% first subplot -- y-data histc
ah1 = subplot(2, 2, 1);
y_bins = 1.5:.25:4.5;
n = hist(FWHM12Avg, y_bins);
bar(y_bins, n, 'vertical', 'on')
hold on
hist(FWHM12Med, y_bins)
bar(y_bins, n, 'vertical', 'on')
% x-data histc
ah2 = subplot(2, 2, 4);
x_bins = 1.5:.25:4.5;
n = hist(FWHM11Avg, x_bins);
bar(x_bins, n, 'horizontal', 'on')
hold on
n = hist(FWHM11Med, x_bins);
bar(x_bins, n, 'horizontal', 'on')
% scatterplot
ah3 = subplot(2, 2, 2);
hold on
scatter(FWHM11Avg, FWHM11Med)
scatter(FWHM12Avg, FWHM12Med)
% link axes, adjust histc orientation
linkaxes([ah1, ah3], 'y')
linkaxes([ah3, ah2], 'x')
set(ah3,'XLim',[minx, maxx]);
set(ah3,'YLim',[miny, maxy]);
set(ah1,'Box','off');
set(ah1,'View',[180, -90]);
set(ah1,'Visible','off');
set(ah2,'Visible','off');
set(ah2,'Box','off');
set(ah2,'View',[0, -90]);
Please research before asking. There is a function in Matlab scatterhist which does this
x0 = 6.1;
y0 = 3.2;
n = 50;
r = rand(n ,1 );
theta = 2*pi*rand(n, 1);
x = x0 + r.*cos(theta);
y = y0 + r.*sin(theta);
scatterhist(x,y, 'Direction','out', 'Location', 'NorthEast')
Edit: Using the data you provided. Is this what you want?
FWHM11Avg = [3.88,3.43,3.16,3.22,3.73,2.43,2.88,3.01,3.59,2.17];
FWHM11Med = [4.4,3.1,3,3.15,3.9,2,3.00,2.85,3.85,2.2];
FWHM12Avg = [3.50,2.30,2.97,2.97,2.98,2.28,2.94,2.36,3.51,1.7];
FWHM12Med = [3.3,2.1,2.9,2.8,2.9,2.1,2.8,2.30,3.5,1.7];
% make figure
figure(1)
clf
FWHM11Avg = FWHM11Avg(:);
FWHM11Med = FWHM11Med(:);
FWHM12Avg = FWHM12Avg(:);
FWHM12Med = FWHM12Med(:);
minX = min([FWHM11Avg; FWHM12Avg]);
maxX = max([FWHM11Avg; FWHM12Avg]);
minY = min([FWHM11Med; FWHM12Med]);
maxY = max([FWHM11Med; FWHM12Med]);
resX = 0.25;
resY = 0.25;
nBinsX = ceil((maxX - minX) / resX);
nBinsY = ceil((maxY - minY) / resY);
label = vertcat( ...
num2cell(repmat('FWHM11', size(FWHM11Avg)),2), ...
num2cell(repmat('FWHM12', size(FWHM11Avg)),2));
Avg = vertcat(FWHM11Avg, FWHM12Avg);
Med = vertcat(FWHM11Med, FWHM12Med);
% scatterplot
scatterhist(Avg, Med, 'Group', label, 'Direction','out', ...
'Location', 'NorthEast', 'NBins', [nBinsX, nBinsY])
This is something I've been using lately:
% generate some random data
mu = [1 2];
sigma = [1 0.5; 0.5 2];
R = chol(sigma);
my_data1 = repmat(mu,100,1) + randn(100,2)*R;
mu = [2 1];
sigma = [3 -0.5; -0.5 2];
R = chol(sigma);
my_data2 = repmat(mu,100,1) + randn(100,2)*R;
% find limits
minx = min([my_data1(:, 1); my_data2(:, 1)]);
maxx = max([my_data1(:, 1); my_data2(:, 1)]);
miny = min([my_data1(:, 2); my_data2(:, 2)]);
maxy = max([my_data1(:, 2); my_data2(:, 2)]);
% make figure
figure(1)
clf
% first subplot -- y-data histogram
ah1 = subplot(2, 2, 1);
histogram(my_data1(:, 2), 'Orientation','horizontal', 'Normalization', 'probability', 'BinWidth', 0.5)
hold on
histogram(my_data2(:, 2), 'Orientation','horizontal', 'Normalization', 'probability', 'BinWidth', 0.5)
% x-data histogram
ah2 = subplot(2, 2, 4);
histogram(my_data1(:, 1), 'Normalization', 'probability', 'BinWidth', 0.5)
hold on
histogram(my_data2(:, 1), 'Normalization', 'probability', 'BinWidth', 0.5)
% scatterplot
ah3 = subplot(2, 2, 2);
hold on
scatter(my_data1(:, 1), my_data1(:, 2))
scatter(my_data2(:, 1), my_data2(:, 2))
% link axes, adjust histogram orientation
linkaxes([ah1, ah3], 'y')
linkaxes([ah3, ah2], 'x')
ah3.XLim = [minx, maxx];
ah3.YLim = [miny, maxy];
ah1.Box = 'off';
ah1.View = [180, -90];
ah1.Visible = 'off';
ah2.Visible = 'off';
ah2.Box = 'off';
ah2.View = [0, -90];
producing this plot
This code assumes a recent version of MATLAB (I use 2014b), but can be easily adapted using the old histogram functions (hist, histc) and the set(..) syntax for graphical objects.

How to plot a hyper plane in 3D for the SVM results?

I just wondering how to plot a hyperplane of the SVM results.
For example, here we are using two features, we can plot the decision boundary in 2D. But if how can we plot a hyperplane in 3D if we use 3 features?
load fisheriris;
features = meas(1:100,:);
featureSelcted = features(1:100,1:2); % For example, featureSelcted = features(1:100,1:3) can not be plotted
groundTruthGroup = species(1:100);
svmStruct = svmtrain(featureSelcted, groundTruthGroup, ...
'Kernel_Function', 'rbf', 'boxconstraint', Inf, 'showplot', true, 'Method', 'QP');
svmClassified = svmclassify(svmStruct,featureSelcted,'showplot',true);
A similar solution in R can be found at svm-fit-hyperplane, but a Matlab implementation would be handy.
Here is a function to plot 3D SVM results in MATLAB.
function [] = svm_3d_matlab_vis(svmStruct,Xdata,group)
sv = svmStruct.SupportVectors;
alphaHat = svmStruct.Alpha;
bias = svmStruct.Bias;
kfun = svmStruct.KernelFunction;
kfunargs = svmStruct.KernelFunctionArgs;
sh = svmStruct.ScaleData.shift; % shift vector
scalef = svmStruct.ScaleData.scaleFactor; % scale vector
group = group(~any(isnan(Xdata),2));
Xdata =Xdata(~any(isnan(Xdata),2),:); % remove rows with NaN
% scale and shift data
Xdata1 = repmat(scalef,size(Xdata,1),1).*(Xdata+repmat(sh,size(Xdata,1),1));
k = 50;
cubeXMin = min(Xdata1(:,1));
cubeYMin = min(Xdata1(:,2));
cubeZMin = min(Xdata1(:,3));
cubeXMax = max(Xdata1(:,1));
cubeYMax = max(Xdata1(:,2));
cubeZMax = max(Xdata1(:,3));
stepx = (cubeXMax-cubeXMin)/(k-1);
stepy = (cubeYMax-cubeYMin)/(k-1);
stepz = (cubeZMax-cubeZMin)/(k-1);
[x, y, z] = meshgrid(cubeXMin:stepx:cubeXMax,cubeYMin:stepy:cubeYMax,cubeZMin:stepz:cubeZMax);
mm = size(x);
x = x(:);
y = y(:);
z = z(:);
f = (feval(kfun,sv,[x y z],kfunargs{:})'*alphaHat(:)) + bias;
t = strcmp(group, group{1});
% unscale and unshift data
Xdata1 =(Xdata1./repmat(scalef,size(Xdata,1),1)) - repmat(sh,size(Xdata,1),1);
x =(x./repmat(scalef(1),size(x,1),1)) - repmat(sh(1),size(x,1),1);
y =(y./repmat(scalef(2),size(y,1),1)) - repmat(sh(2),size(y,1),1);
z =(z./repmat(scalef(3),size(z,1),1)) - repmat(sh(3),size(z,1),1);
figure
plot3(Xdata1(t, 1), Xdata1(t, 2), Xdata1(t, 3), 'b.');
hold on
plot3(Xdata1(~t, 1), Xdata1(~t, 2), Xdata1(~t, 3), 'r.');
hold on
% load unscaled support vectors for plotting
sv = svmStruct.SupportVectorIndices;
sv = [Xdata1(sv, :)];
plot3(sv(:, 1), sv(:, 2), sv(:, 3), 'go');
legend(group{1},group{end},'support vectors')
x0 = reshape(x, mm);
y0 = reshape(y, mm);
z0 = reshape(z, mm);
v0 = reshape(f, mm);
[faces,verts,colors] = isosurface(x0, y0, z0, v0, 0, x0);
patch('Vertices', verts, 'Faces', faces, 'FaceColor','k','edgecolor', 'none', 'FaceAlpha', 0.5);
grid on
box on
view(3)
hold off
end
Example plot:
% load data
load fisheriris;
% train svm using three features for two species
svmStruct = svmtrain(meas(1:100,1:3),species(1:100),'showplot','false','kernel_function','rbf',...
'boxconstraint',1,'kktviolationlevel',0.05,'tolkkt',5e-3);
% run function described above
svm_3d_matlab_vis(svmStruct,meas(1:100,1:3),species(1:100))