Let Matrices = [A B C D] be a set of square matrices. I want to construct
H = [A B C D;
B A B C;
C B A B;
D C B A]
If all I was interested in was the 4 by 4 case, then this would be enough. However, I want to construct the analogous matrix when Matrices = [A B C D E F] etc. What code could I write to do this?
This can be done as follows:
Concatenate the matrices into a 3D array;
Build the basic with numbers instead of matrices using toeplitz;
Extend this structure so that using linear indexing into the 3D array produces the desired result.
N = 2; % matrix size
M = 3; % number of matrices
matrices = arrayfun(#(x) {randi(9,N)}, 1:M); % input matrices
matrices_3D = cat(3, matrices{:}); % concatenate the matrices along the third dim
ind1 = repmat(reshape(1:N^2, N, N), M, M); % linear indices within each matrix
ind2 = (repelem(toeplitz(1:M), N, N)-1)*N^2; % linear indices to select the matrices
result = matrices_3D(ind1 + ind2); % build result
Example run:
>> celldisp(matrices)
matrices{1} =
1 4
2 6
matrices{2} =
6 4
5 9
matrices{3} =
5 4
6 5
>> result
result =
1 4 6 4 5 4
2 6 5 9 6 5
6 4 1 4 6 4
5 9 2 6 5 9
5 4 6 4 1 4
6 5 5 9 2 6
I am totally new to Matlab and have a simple question (not that simple for me):
I have a matrix x:
x = 1 2 3
4 5 6
7 8 9
10 11 12
and a Vector y:
y = 1 2 3
Now I would like to multiply the numbers 1 to 4 by the first element of the Vector, the numbers 5 to 8 by the second element and 9 to 12 by the last element.
CanĀ“t find a solution. Any help is highly appreciated!
Thanks Paul
If you modify your input x to set up all "groups" as columns of a new input, let's say xx, e.g. by transposing and reshaping x accordingly, you can use (element-wise) multiplication. MATLAB's implicit expansion allows such (element-wise) matrix operations. (Before MATLAB R2016b, one would need bsxfun for that.)
That would be my solution:
% Inputs
x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
y = [1 2 3]
% Transpose and reshape x to set up all "groups" as new columns
xx = reshape(x.', 4, 3)
% (Element-wise) Multiplication using implicit expansion
z = xx .* y
Output:
x =
1 2 3
4 5 6
7 8 9
10 11 12
y =
1 2 3
xx =
1 5 9
2 6 10
3 7 11
4 8 12
z =
1 10 27
2 12 30
3 14 33
4 16 36
Hope that helps!
I am a bit new in using Matlab, and I have a question about defining a multivariable function for vector input.
If the function is a single function, say f(t), I know how to make it for vector input. The general way is to use arrayfun after defining a f(t). How about for multivariable function, say f(x,y)? What I want to do is to get two inputs, say [1 2 3] for x and [4 5 6 7] for y (dimension may be different, but both of them are either column vector or row vector) so that I can calculate to give
[f(1,4),f(1,5),f(1,6),f(1,7);
f(2,4),f(2,5),f(2,6),f(2,7);
f(3,4),f(3,5),f(3,6),f(3,7)]
The difficulty is that the vector input for x and y may not be in the same dimension.
I understand it may be difficult to illustrate if I do not have an example of f(x,y). For my use of f(x,y), it may be very complicated to display f(x,y). For simplicity, treat f(x,y) to be x^2+y, and once defined, you cannot change it to x.^2+y for vector inputs.
Here is a set of suggestions using ndgrid:
testfun = #(x,y) x^2+y; % non-vectorized form
x = 1:3;
y = 4:7;
[X,Y] = ndgrid(x,y);
% if the function can be vectorized (fastest!):
testfun_vec = #(x,y) x.^2+y; % vectorized form
A = testfun_vec(X,Y);
% or without ndgrid (also super fast):
B = bsxfun(testfun_vec,x.',y); % use the transpose to take all combinations
% if not, or if it's not bivariate operation (slowest):
C = arrayfun(testfun,X(:),Y(:));
C = reshape(C,length(x),length(y));
% and if you want a loop:
D = zeros(length(x),length(y));
for k = 1:length(X(:))
D(k) = testfun(X(k),Y(k));
end
Which will output for all cases (A,B,C and D):
5 6 7 8
8 9 10 11
13 14 15 16
As mentioned already, if you can vectorize your function - this is the best solution, and if it has only two inputs bsxfun is also a good solution. Otherwise if you have small data and want to keep your code compact use arrayfun, if you are dealing with large arrays use an un-nested for loop.
Here is the code using for loops and inline functions:
x = [1 2 3];
y = [4 5 6 7];
f = #(x,y) x^2 +y;
A = zeros(length(x), length(y));
for m = 1:length(x)
for n = 1:length(y)
A(m, n) = f(x(m), y(n));
end
end
disp(A);
Result:
A =
5 6 7 8
8 9 10 11
13 14 15 16
>> x = [1 2 3];
>> y = [4 5 6 7];
>> outValue = foo(x, y);
>> outValue
outValue =
5 6 7 8
8 9 10 11
13 14 15 16
Make this function:
function out = foo(x, y)
for i = 1 : length(x)
for j = 1 : length(y)
out(i, j) = x(i)^2 + y(j);
end
end
Iam facing problem in understanding and converting a matlab code into opencv. I want to know is there any equivalent function of sub2ind as in matlab in opencv. Or how to implement in opencv this particular function.
link for sub2ind function is
http://www.mathworks.in/help/techdoc/ref/sub2ind.html
A quick example to illustrate. Consider:
>> v = (1:4*3)
v =
1 2 3 4 5 6 7 8 9 10 11 12
>> M = reshape(v,[4 3])
M =
1 5 9
2 6 10
3 7 11
4 8 12
Now all the following are equivalent:
sz = size(M);
i = 3; j = 2;
M(i,j)
v( sub2ind(sz,i,j) )
v( sz(1)*(j-1)+i )
Just keep in mind that MATLAB uses a column-major order, while C is row-major order
This is the input matrix
7 9 6
8 7 9
7 6 7
Based on the frequency their appearance in the matrix (Note. these values are for explanation purpose. I didn't pre-calculate them in advance. That why I ask this question)
number frequency
6 2
7 4
8 1
9 2
and the output I expect is
4 2 2
1 4 2
4 2 4
Is there a simple way to do this?
Here's a three-line solution. First prepare the input:
X = [7 9 6;8 7 9;7 6 7];
Now do:
[a m n] = unique(X);
b = hist(X(:),a);
c = reshape(b(n),size(X));
Which gives this value for c:
4 2 2
1 4 2
4 2 4
If you also wanted the frequency matrix, you can get it with this code:
[a b']
Here is a code with for-loop (a is input matrix, freq - frequency matrix with 2 columns):
weight = zeros(size(a));
for k = 1:size(freq,1)
weight(a==freq(k,1)) = freq(k,2);
end
Maybe it can be solved without loops, but my code looks like:
M = [7 9 6 ;
8 7 9 ;
7 6 7 ;];
number = unique(M(:));
frequency = hist(M(:), number)';
map = containers.Map(number, frequency);
[height width] = size(M);
result = zeros(height, width); %allocate place
for i=1:height
for j=1:width
result(i,j) = map(M(i,j));
end
end