Related
i've been trying to do this question but no matter how i go about it i get this error.
any ideas ?
The question is
"Matrix dimensions must agree"
bb = [1,1.18,1]; %-- Filter Coefficients
nn = 1:150;
L2 = 0:9; % M - 1(10-1 = 9)
%1st at 0.3
w1 = (0.2*cos(0.44*pi*nn)) .* (exp(-1i * 0.3 * 3.14 * L2)) ;
%2nd at 0.44
w2 = 0.2*cos(0.44*pi*nn) .* exp(-1i*0.44*3.14*L2);
%3rd at 0.7
w3 = 0.2*cos(0.44*pi*nn) .* exp(-1i*0.7*3.14*L2);
wt = w1 + w2 + w3;
HTOTAL = freqz(bb, 1, wt);
H1 = freqz(bb, 1, w1); %
H2 = freqz(bb, 1, w2); %
H3 = freqz(bb, 1, w3); %
%set the value of x to see the filter
x = 1;
subplot(2,1,1); plot(wx, abs(HH))
subplot(2,1,2); plot(wx, angle(HH))
xlabel('Normalized Radian Frequency')
You're trying to element-wise multiply (0.2*cos(0.44*pi*nn)) by (exp(-1i*0.3*3.14*L2)). The issue here is that the first array contains nn = 150 elements, while the second contains L2 = 10 elements.
Looking at the original question, it looks like you're required to use a filter length (L2) of 10, but your nn array ranges from 1 to 150 instead of the required 0 to 9.
You should use (0.2*cos(0.44*pi*L2)) instead of (0.2*cos(0.44*pi*nn)) to fix your "Matrix dimensions must agree" error.
This question already has answers here:
Create a zero-filled 2D array with ones at positions indexed by a vector
(4 answers)
Closed 5 years ago.
Often you are given a vector of integer values representing your labels (aka classes), for example
[2; 1; 3; 3; 2]
and you would like to hot one encode this vector, such that each value is represented by a 1 in the column indicated by the value in each row of the labels vector, for example
[0 1 0;
1 0 0;
0 0 1;
0 0 1;
0 1 0]
For speed and memory savings, you can use bsxfun combined with eq to accomplish the same thing. While your eye solution may work, your memory usage grows quadratically with the number of unique values in X.
Y = bsxfun(#eq, X(:), 1:max(X));
Or as an anonymous function if you prefer:
hotone = #(X)bsxfun(#eq, X(:), 1:max(X));
Or if you're on Octave (or MATLAB version R2016b and later) , you can take advantage of automatic broadcasting and simply do the following as suggested by #Tasos.
Y = X == 1:max(X);
Benchmark
Here is a quick benchmark showing the performance of the various answers with varying number of elements on X and varying number of unique values in X.
function benchit()
nUnique = round(linspace(10, 1000, 10));
nElements = round(linspace(10, 1000, 12));
times1 = zeros(numel(nUnique), numel(nElements));
times2 = zeros(numel(nUnique), numel(nElements));
times3 = zeros(numel(nUnique), numel(nElements));
times4 = zeros(numel(nUnique), numel(nElements));
times5 = zeros(numel(nUnique), numel(nElements));
for m = 1:numel(nUnique)
for n = 1:numel(nElements)
X = randi(nUnique(m), nElements(n), 1);
times1(m,n) = timeit(#()bsxfunApproach(X));
X = randi(nUnique(m), nElements(n), 1);
times2(m,n) = timeit(#()eyeApproach(X));
X = randi(nUnique(m), nElements(n), 1);
times3(m,n) = timeit(#()sub2indApproach(X));
X = randi(nUnique(m), nElements(n), 1);
times4(m,n) = timeit(#()sparseApproach(X));
X = randi(nUnique(m), nElements(n), 1);
times5(m,n) = timeit(#()sparseFullApproach(X));
end
end
colors = get(0, 'defaultaxescolororder');
figure;
surf(nElements, nUnique, times1 * 1000, 'FaceColor', colors(1,:), 'FaceAlpha', 0.5);
hold on
surf(nElements, nUnique, times2 * 1000, 'FaceColor', colors(2,:), 'FaceAlpha', 0.5);
surf(nElements, nUnique, times3 * 1000, 'FaceColor', colors(3,:), 'FaceAlpha', 0.5);
surf(nElements, nUnique, times4 * 1000, 'FaceColor', colors(4,:), 'FaceAlpha', 0.5);
surf(nElements, nUnique, times5 * 1000, 'FaceColor', colors(5,:), 'FaceAlpha', 0.5);
view([46.1000 34.8000])
grid on
xlabel('Elements')
ylabel('Unique Values')
zlabel('Execution Time (ms)')
legend({'bsxfun', 'eye', 'sub2ind', 'sparse', 'full(sparse)'}, 'Location', 'Northwest')
end
function Y = bsxfunApproach(X)
Y = bsxfun(#eq, X(:), 1:max(X));
end
function Y = eyeApproach(X)
tmp = eye(max(X));
Y = tmp(X, :);
end
function Y = sub2indApproach(X)
LinearIndices = sub2ind([length(X),max(X)], [1:length(X)]', X);
Y = zeros(length(X), max(X));
Y(LinearIndices) = 1;
end
function Y = sparseApproach(X)
Y = sparse(1:numel(X), X,1);
end
function Y = sparseFullApproach(X)
Y = full(sparse(1:numel(X), X,1));
end
Results
If you need a non-sparse output bsxfun performs the best, but if you can use a sparse matrix (without conversion to a full matrix), then that is the fastest and most memory efficient option.
You can use the identity matrix and index into it using the input/labels vector, for example if the labels vector X is some random integer vector
X = randi(3,5,1)
ans =
2
1
2
3
3
then, the following will hot one encode X
eye(max(X))(X,:)
which can be conveniently defined as a function using
hotone = #(v) eye(max(v))(v,:)
EDIT:
Although the solution above works in Octave, you have you modify it for Matlab as follows
I = eye(max(X));
I(X,:)
I think this is fast specially when matrix dimension grows:
Y = sparse(1:numel(X), X,1);
or
Y = full(sparse(1:numel(X), X,1));
Just posting the sub2ind solution too to satisfy your curiosity :)
But I like your solution better :p
>> X = [2,1,2,3,3]'
>> LinearIndices = sub2ind([length(X),3], [1:length(X)]', X);
>> tmp = zeros(length(X), 3);
>> tmp(LinearIndices) = 1
tmp =
0 1 0
1 0 0
0 1 0
0 0 1
0 0 1
Just in case someone is looking for the 2D case (as I was):
X = [2 1; ...
3 3; ...
2 4]
Y = zeros(3,2,4)
for i = 1:4
Y(:,:,i) = ind2sub(X,X==i)
end
gives a one-hot encoded matrix along the 3rd dimension.
I need to evaluate a function (say)
Fxy = 2*x.^2 +3 *y.^2;
on a ternary grid x-range (0 - 1), y-range (0-1) and 1-x-y (0 - 1).
I am unable to construct the ternary grid on which I need to evaluate the above function. Also, once evaluated I need to plot the function in a ternary contour plot. Ideally, I need the axes to go counter clockwise in the sense (x -> y--> (1-x-y)).
I have tried the function
function tg = triangle_grid ( n, t )
ng = ( ( n + 1 ) * ( n + 2 ) ) / 2;
tg = zeros ( 2, ng );
p = 0;
for i = 0 : n
for j = 0 : n - i
k = n - i - j;
p = p + 1;
tg(1:2,p) = ( i * t(1:2,1) + j * t(1:2,2) + k * t(1:2,3) ) / n;
end
end
return
end
for the number of sub intervals between the triangle edge coordinates
n = 10 (say)
and for the edge coordinates of an equilateral triangle
t = tcoord = [0.0, 0.5, 1.0;
0.0, 1.0*sqrt(3)/2, 0.0];
This generated a triangular grid with the x-axis from 0-1 but the other two are not from 0-1.
I need something like this:
... with the axes range 0-1 (0-100 would also do).
In addition, I need to know the coordinate points for all intersections within the triangular grid. Once I have this I can proceed to evaluate the function in this grid.
My final aim is to get something like this. This is a better representation of what I need to achieve (as compared to the previous plot which I have now removed)
Note that the two ternary plots have iso-value contours which are different in in magnitude. In my case the difference is an order of magnitude, two very different Fxy's.
If I can plot the two ternary plots on top of each other then and evaluate the compositions at the intersection of two iso-value contours on the ternary plane. The compositions should be as read from the ternary plot and not the rectangular grid on which triangle is defined.
Currently there are issues (as highlighted in the comments section, will update this once the problem is closer to solution).
I am the author of ternplot. As you have correctly surmised, ternpcolor does not do what you want, as it is built to grid data automatically. In retrospect, this was not a particularly wise decision, I've made a note to change the design. In the mean time this code should do what you want:
EDIT: I've changed the code to find the intersection of two curves rather than just one.
N = 10;
x = linspace(0, 1, N);
y = x;
% The grid intersections on your diagram are actually rectangularly arranged,
% so meshgrid will build the intersections for us
[xx, yy] = meshgrid(x, y);
zz = 1 - (xx + yy);
% now that we've got the intersections, we can evaluate the function
f1 = #(x, y) 2*x.^2 + 3*y.^2 + 0.1;
Fxy1 = f1(xx, yy);
Fxy1(xx + yy > 1) = nan;
f2 = #(x, y) 3*x.^2 + 2*y.^2;
Fxy2 = f2(xx, yy);
Fxy2(xx + yy > 1) = nan;
f3 = #(x, y) (3*x.^2 + 2*y.^2) * 1000; % different order of magnitude
Fxy3 = f3(xx, yy);
Fxy3(xx + yy > 1) = nan;
subplot(1, 2, 1)
% This constructs the ternary axes
ternaxes(5);
% These are the coordinates of the compositions mapped to plot coordinates
[xg, yg] = terncoords(xx, yy);
% simpletri constructs the correct triangles
tri = simpletri(N);
hold on
% and now we can plot
trisurf(tri, xg, yg, Fxy1);
trisurf(tri, xg, yg, Fxy2);
hold off
view([137.5, 30]);
subplot(1, 2, 2);
ternaxes(5)
% Here we plot the line of intersection of the two functions
contour(xg, yg, Fxy1 - Fxy2, [0 0], 'r')
axis equal
EDIT 2: If you want to find the point of intersection between two contours, you are effectively solving two simultaneous equations. This bit of extra code will solve that for you (notice I've used some anonymous functions in the code above now, as well):
f1level = 1;
f3level = 1000;
intersection = fsolve(#(v) [f1(v(1), v(2)) - f1level; f3(v(1), v(2)) - f3level], [0.5, 0.4]);
% if you don't have the optimization toolbox, this command works almost as well
intersection = fminsearch(#(v) sum([f1(v(1), v(2)) - f1level; f3(v(1), v(2)) - f3level].^2), [0.5, 0.4]);
ternaxes(5)
hold on
contour(xg, yg, Fxy1, [f1level f1level]);
contour(xg, yg, Fxy3, [f3level f3level]);
ternplot(intersection(1), intersection(2), 1 - sum(intersection), 'r.');
hold off
I have played a bit with the file exchange submission https://www.mathworks.com/matlabcentral/fileexchange/2299-alchemyst-ternplot.
if you just do this:
[x,y]=meshgrid(0:0.1:1);
Fxy = 2*x.^2 +3 *y.^2;
ternpcolor(x(:),y(:),Fxy(:))
You get:
The thirds axis is created exactly as you say (1-x-y) inside the ternpcolor function. There are lots of things to "tune" here but I hope it is enough to get you started.
Here is a solution using R and my package ggtern. I have also included the points within proximity underneath, for the purpose of comparison.
library(ggtern)
Fxy = function(x,y){ 2*x^2 + 3*y^2 }
x = y = seq(0,1,length.out = 100)
df = expand.grid(x=x,y=y);
df$z = 1 - df$x - df$y
df = subset(df,z >= 0)
df$value = Fxy(df$x,df$y)
#The Intended Breaks
breaks = pretty(df$value,n=10)
#Create subset of the data, within close proximity to the breaks
df.sub = ldply(breaks,function(b,proximity = 0.02){
s = b - abs(proximity)/2; f = b + abs(proximity)/2
subset(df,value >= s & value <= f)
})
#Plot the ternary diagram
ggtern(df,aes(x,y,z)) +
theme_bw() +
geom_point(data=df.sub,alpha=0.5,color='red',shape=21) +
geom_interpolate_tern(aes(value = value,color=..level..), size = 1, n = 200,
breaks = c(breaks,max(df$value) - 0.01,min(df$value) + 0.01),
base = 'identity',
formula = value ~ poly(x,y,degree=2)) +
labs(title = "Contour Plot on Modelled Surface", x = "Left",y="Top",z="Right")
Which produces the following:
i run below code, but get X, Y, Z, and C cannot be complex error, any idea what is wrong?
k=1;
u = linspace(0,2*pi,72);
v = [-3:.2:-1,1:.2:3];
[U,V] = meshgrid(u,v);
r=sqrt((4*V.^-k)./(cos(U).^2+k*sin(U).^2));
X = r.*cos(U);
Y = r.*sin(U);
Z = V;
This is the image I want to get:
http://adasu.info/plates.png
The full code is:
function simple_math_functions_animation1
clc, close all, clear all
hf1=figure(1);hold on,grid on,axis equal, view([1 -1 1])
set(hf1,'Color','w');set(hf1,'Position',[300, 600, 500, 400]);
xlabel('x');ylabel('y'),zlabel('z');
k=1;
u = linspace(0,2*pi,72);
v = [-3:.2:-1,1:.2:3];
[U,V] = meshgrid(u,v);
r=sqrt((4*V.^-k)./(cos(U).^2+k*sin(U).^2));
X = r.*cos(U);
Y = r.*sin(U);
Z = V;
surf(X,Y,Z,'EdgeColor',[0.5 1. 0.2],'FaceColor',[1 0.2 0.8],'FaceAlpha',0.6);
XYZ=[reshape(X,1,prod(size(X)));
reshape(Y,1,prod(size(Y)));
reshape(Z,1,prod(size(Z)));
ones(1,prod(size(Z)))];
phi=[0 : pi/20 : 50*pi];
h=[]; axis([-20 20 -20 20 -20 20]);
for beta=phi % animation loop *****************
T=[cos(beta) -sin(beta) 0 0; % rotation matrix
sin(beta) cos(beta) 0 0;
0 0 1 0;
0 0 0 1];
XYZ1=T*XYZ; % coordinates changing
X1=reshape(XYZ1(1,:),size(X));Y1=reshape(XYZ1(2,:),size(Y));Z1=reshape(XYZ1(3,:),size(Z));
pause(0.1);if ~isempty(h),delete(h);end
h=surf(X1,Y1,Z1,'EdgeColor',[0.5 1. 0.2],'FaceColor',[0.2 0.2 0.8],'FaceAlpha',0.6);
end % ******************************************
end
You are getting that complex error because r is complex-valued. r is used in both X and Y and so when it's time to use surf on these inputs, you finally get that error. That makes sense because your range of V has negative values, and when you set k=1 for this expression:
r=sqrt((4*V.^-k)./(cos(U).^2+k*sin(U).^2));
You are effectively trying to take the square root of values in V and some of them are negative, and hence r is complex valued. If you look at your actual image you uploaded, you are missing a 2 in the power of V. Therefore:
r=sqrt((4*V.^2-k)./(cos(U).^2+k*sin(U).^2));
When I do this, then try running your code, I get this:
I implemented a method for removing shadows based on invariant color features found in the paper Entropy Minimization for Shadow Removal. My implementation seems to be yielding similar computational results sometimes, but they are always off, and my grayscale image is blocky, maybe as a result of incorrectly taking the geometric mean.
Here is an example plot of the information potential from the horse image in the paper as well as my invariant image. Multiply the x-axis by 3 to get theta(which goes from 0 to 180):
And here is the grayscale Image my code outputs for the correct maximum theta (mine is off by 10):
You can see the blockiness that their image doesn't have:
Here is their information potential:
When dividing by the geometric mean, I have tried using NaN and tresholding the image so the smallest possible value is .01, but it doesn't seem to change my output.
Here is my code:
I = im2double(imread(strname));
[m,n,d] = size(I);
I = max(I, .01);
chrom = zeros(m, n, 3, 'double');
for i = 1:m
for j = 1:n
% if ((I(i,j,1)*I(i,j,2)*I(i,j,3))~= 0)
chrom(i,j, 1) = I(i,j,1)/((I(i,j,1)*I(i,j,2)*I(i,j, 3))^(1/3));
chrom(i,j, 2) = I(i,j,2)/((I(i,j,1)*I(i,j,2)*I(i,j, 3))^(1/3));
chrom(i,j, 3) = I(i,j,3)/((I(i,j,1)*I(i,j,2)*I(i,j, 3))^(1/3));
% else
% chrom(i,j, 1) = 1;
% chrom(i,j, 2) = 1;
% chrom(i,j, 3) = 1;
% end
end
end
p1 = mat2gray(log(chrom(:,:,1)));
p2 = mat2gray(log(chrom(:,:,2)));
p3 = mat2gray(log(chrom(:,:,3)));
X1 = mat2gray(p1*1/(sqrt(2)) - p2*1/(sqrt(2)));
X2 = mat2gray(p1*1/(sqrt(6)) + p2*1/(sqrt(6)) - p3*2/(sqrt(6)));
maxinf = 0;
maxtheta = 0;
data2 = zeros(1, 61);
for theta = 0:3:180
M = X1*cos(theta*pi/180) - X2*sin(theta*pi/180);
s = sqrt(std2(X1)^(2)*cos(theta*pi/180) + std2(X2)^(2)*sin(theta*pi/180));
s = abs(1.06*s*((m*n)^(-1/5)));
[m, n] = size(M);
length = m*n;
sources = zeros(1, length, 'double');
count = 1;
for x=1:m
for y = 1:n
sources(1, count) = M(x , y);
count = count + 1;
end
end
weights = ones(1, length);
sigma = 2*s;
[xc , Ak] = fgt_model(sources , weights , sigma , 10, sqrt(length) , 6 );
sum1 = sum(fgt_predict(sources , xc , Ak , sigma , 10 ));
sum1 = sum1/sqrt(2*pi*2*s*s);
data2(theta/3 + 1) = sum1;
if (sum1 > maxinf)
maxinf = sum1;
maxtheta = theta;
end
end
InvariantImage2 = cos(maxtheta*pi/180)*X1 + sin(maxtheta*pi/180)*X2;
Assume the Fast Gauss Transform is correct.
I don't know whether this makes any difference as it is more than a month now, but the blockiness and different information potential plot is simply caused by compression of the used image. You can't expect to be getting same results using this image as they had, because they have used raw, high resolution uncompressed version of it. I have to say I am fairly impressed with your results, especially with implementing the information potential. That thing went over my head a little.
John.