Projection matrix sign confusion (edited title) - matlab

Down I have edited my question.
I am projecting Wxyz to image(u,v) and getting some wrong result. I can't figure out where is mistake. Please help some one to figure out.
Given:
Wxyzz =
386.06 197.02 -1821.8 1
407.32 -108 -1859.1 1
4.9764 290.92 -1531.2 1
103.39 -233.07 -1643.2 1
189.7 320.19 -1667.9 1
76.279 147.9 -1597.2 1
47.798 -319.51 -1605.8 1
164.74 -223.1 -1688.6 1
482.06 -251.66 -1921.2 1
226.42 -213.27 -1733.6 1
Wxyz=Wxyz' %';
%# intrinsic
fu = 2640; fv =2640; uo= 1514; vo = 994;
A= [ fu 0 uo 0
0 fv vo 0
0 0 1 0
0 0 0 1];
Exterior=[-6.6861,12.6118,-8.0660,[-0.4467,-0.3168,0.2380]*pi/180];%# deg 2 rad
%#data
X0=Exterior(1);
Y0=Exterior(2);
Z0=Exterior(3);
ax=Exterior(4);
by=Exterior(5);
cz=Exterior(6);
%#Rotation in X
Rx = [1 0 0
0 cos(ax) -sin(ax)
0 sin(ax) cos(ax)];
%#Rotation in Y
Ry = [cos(by) 0 sin(by)
0 1 0
-sin(by) 0 cos(by)];
%#Rotation in Z
Rz = [cos(cz) -sin(cz) 0
sin(cz) cos(cz) 0
0 0 1];
R=Rx*Ry*Rz;
T=[X0;Y0;Z0];
Extrinsic= R';
Extrinsic(:,4) = -(R')* (T);
Extrinsic(4,:) = [0 0 0 1]
PImage = A* Extrinsic* Wxyz;
%#Obtain the X's
PImage(1 ,:) = PImage(1 ,:) ./ PImage(3 ,:);
%#Obtain the Y's
PImage(2 ,:) = PImage(2 ,:) ./ PImage(3 ,:);
I am getting
PImage =
955.93 707.43 -1814.4 1
939.75 1147.6 -1854.2 1
1506.3 490.36 -1521 1
1352.7 1370.2 -1637.6 1
1213.9 485.04 -1658.4 1
1389.7 749.08 -1588.5 1
1440.9 1521.6 -1600.6 1
1261.2 1344.2 -1683.2 1
857.22 1340 -1917.8 1
1173.9 1319.9 -1728.5 1
I supposed to get( real 2 D points)
img =
2072.8 706.69
2088.9 1146.9
1522.6 489.6
1676.1 1369.5
1814.9 484.3
1639.2 748.35
1587.9 1520.9
1767.6 1343.5
2171.4 1339.3
1854.9 1319.2
If I use
A= [ -fu 0 uo 0
0 fv vo 0
0 0 1 0
0 0 0 1];
I get corect answer.
I can't figure out where is mistake in rotation or translation; Why Pimage(:,1) is not identical with img(:,1).
Any help will be grateful.

You've done the rotation, and you've done the transformation.
What you need to do is the projection! Now I don't know what exactly you're trying to accomplish, but I don't see a projection matrix anywhere. So that's the first thing you need to fix.
Remember that doing a projection is a R4 -> R4 operation. If you're trying to get an R2 vector, you're trying to do something else (more).
see more at wikipedia.
if you really want to learn the details, you can watch and learn courtesy of YouTube

Related

Generating in Matlab a "modified" diagonal matrix

I want to construct a matrix A in Matlab of dimension w x (m*w) where
each row is full of zeros except m consecutive ones that shift towards the right hand side as we move down to the rows.
Few examples can clarify
w=3,m=4
A=[1 1 1 1 0 0 0 0 0 0 0 0;
0 0 0 0 1 1 1 1 0 0 0 0;
0 0 0 0 0 0 0 0 1 1 1 1]
or
w=3, m=3
A=[1 1 1 0 0 0 0 0 0;
0 0 0 1 1 1 0 0 0;
0 0 0 0 0 0 1 1 1]
or
w=2, m=3
A=[1 1 1 0 0 0;
0 0 0 1 1 1]
I can't see how to proceed and any hint would be extremely helpful.
Step 1. Simplify the problem
If you write the "modified diagonal matrix" you are asking about as a row vector it will always look like the following
% 1 ... 1 0 ... ... 0 ... ... ... ... ... ... ... ... 1 ... 1
% m ones m*w zeros w-1 times the same as before m ones
Step 2. Think how to solve the simplified problem
The fundamental unit you need is a vector of m ones followed by m*w zeros;
Once you have built such vector, you need it to be repeated w times, MATLAB already knows how to do that;
The only thing you miss are the trailing ones: append them;
Now that the vector you were looking for is completed, you need to turn it into a matrix. MATLAB already knows how to do this too.
Final code
Once you understood the above steps, the final behaviour can be achieved even with a one-liner
>> m = 4; w = 3;
>> vec2mat([repmat([ones(1, m) zeros(1, m*w)], 1, w-1) ones(1, m)], w*m)
ans =
1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1
About speed
It's true, for loops aren't so slow anymore. I timed my one-liner solution, the trivial for loop and Luis Mendo's solution with eye() and repelem().
Click on images to zoom
Tested on the same machine, with MATLAB R2018a.
As you can see, as long as m and w are quite small, even if you could point out some differences in speed, them won't be noticeable to humans.
Anyway if you are going to work with bigger matrices, it becomes quite obvious which solution is the best.
Here are some approaches:
Using eye and repelem:
A = repelem(eye(w), 1, m);
Using eye and indexing:
A = eye(w);
A = A(1:w, ceil(1/m:1/m:w));
Using eye and kron:
A = kron(eye(w), ones(1,m));
Using singleton expansion:
A = bsxfun(#eq, (1:m).', ceil(1/m:1/m:w)); % Or A = (1:m).'==ceil(1/m:1/m:w);

Perform "outer product" of 2-D matrix and return a 3-D array in MATLAB

I would like to do an operation on a 2-D matrix which somehow looks like the outer product of a vector. I already have written some codes for this task, but it is pretty slow, so I would like to know if there is anything I can do to accelerate it.
I would like to show the code I wrote first, followed by an example to illustrate the task I wanted to do.
My code, version row-by-row
function B = outer2D(A)
B = zeros(size(A,1),size(A,2),size(A,2)); %Pre-allocate the output array
for J = 1 : size(A,1)
B(J,:,:) = transpose(A(J,:))*A(J,:); %Perform outer product on each row of A and assign to the J-th layer of B
end
end
Using the matrix A = randn(30000,20) as the input for testing, it spends 0.317 sec.
My code, version page-by-page
function B = outer2D(A)
B = zeros(size(A,1),size(A,2),size(A,2)); %Pre-allocate the output array
for J = 1 : size(A,2)
B(:,:,J) = repmat(A(:,J),1,size(A,2)).*A; %Evaluate B page-by-page
end
end
Using the matrix A = randn(30000,20) as the input for testing, it spends 0.146 sec.
Example 1
A = [3 0; 1 1; 1 0; -1 1; 0 -2]; %A is the input matrix.
B = outer2D(A);
disp(B)
Then I would expect
(:,:,1) =
9 0
1 1
1 0
1 -1
0 0
(:,:,2) =
0 0
1 1
0 0
-1 1
0 4
The first row of B, [9 0; 0 0], is the outer product of [3 0],
i.e. [3; 0]*[3 0] = [9 0; 0 0].
The second row of B, [1 1; 1 1], is the outer product of [1 1],
i.e. [1; 1]*[1 1] = [1 1; 1 1].
The third row of B, [1 0; 0 0], is the outer product of [1 0],
i.e. [1; 0]*[1 0] = [1 0; 0 0].
And the same for the remaining rows.
Example 2
A =
0 -1 -2
0 1 0
-3 0 2
0 0 0
1 0 0
B = outer2D(A)
disp(B)
Then, similar to the example 1, the expected output is
(:,:,1) =
0 0 0
0 0 0
9 0 -6
0 0 0
1 0 0
(:,:,2) =
0 1 2
0 1 0
0 0 0
0 0 0
0 0 0
(:,:,3) =
0 2 4
0 0 0
-6 0 4
0 0 0
0 0 0
Because the real input in my project is like in the size of 30000 × 2000 and this task is to be performed for many times. So the acceleration of this task is quite essential for me.
I am thinking of eliminating the for-loop in the function. May I have some opinions on this problem?
With auto expansion:
function B = outer2D(A)
B=permute(permute(A,[3 1 2]).*A',[2 3 1]);
end
Without auto expansion:
function B = outer2Dold(A)
B=permute(bsxfun(#times,permute(A,[3 1 2]),A'),[2 3 1]);
end
Outer products are not possible in the matlab language.

Gauss-Jordan elimination over GF(2)

I need to transform a parity-check matrix H (that only consists of ones and zeros) from a non-standard to a standard form, this is, express it as:
Hsys = [A | I]
H and Hsys share the same dimension: (n-k,n). I above corresponds to an identity matrix of dimension (n-k).
Gauss-Jordan elimination comes in handy to solve this problem. Matlab has an specific command, rref, for this purpose, however it is no longer valid while working over GF(2) as in our case. Glancing through the Internet I found in Github a potentially suitable solution to overcome this drawback. However it does not always work out.
I also tried doing HH = mod(rref(H),2), which did not work at all, as many of the output elements weren't binary.
Here below you may find three samples of non-standard parity check matrices in which Gauss-Jordan elimination (over GF(2)) can be applied. As there should always be a way to arrange any matrix to be systematic, I would need a method that works out with matrices of any dimension.
These first sample is taken from sid's post in Stackoverflow, not responded yet:
H=[1 0 1 1 0;
0 0 1 0 1;
1 0 0 1 0;
1 0 1 1 1];
H=[1 1 0 1 1 0 0 1 0 0;
0 1 1 0 1 1 1 0 0 0;
0 0 0 1 0 0 0 1 1 1;
1 1 0 0 0 1 1 0 1 0;
0 0 1 0 0 1 0 1 0 1];
The last one is a matrix of dimension (50x100) and can be found in this link to my Dropbox.
Edit on 21/06/2017
The solution proposed by #Jonas worked out in some cases, but not in most of them, as H matrix seems to be singular. Any other similar way to do this?
Thank you in advance, and best regards.
Here is how I'd do it (using Gauss-Jordan elimination):
H=[1 1 0 1 1 0 0 1 0 0;
0 1 1 0 1 1 1 0 0 0;
0 0 0 1 0 0 0 1 1 1;
1 1 0 0 0 1 1 0 1 0;
0 0 1 0 0 1 0 1 0 1];
rows = size(H, 1);
cols = size(H, 2);
r = 1;
for c = cols - rows + 1:cols
if H(r,c) == 0
% Swap needed
for r2 = r + 1:rows
if H(r2,c) ~= 0
tmp = H(r, :);
H(r, :) = H(r2, :);
H(r2, :) = tmp;
end
end
% Ups...
if H(r,c) == 0
error('H is singular');
end
end
% Forward substitute
for r2 = r + 1:rows
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Back Substitution
for r2 = 1:r - 1
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Next row
r = r + 1;
end
Let me know if this doesn't solve your issue.
I went through the same issue and #jonas code also produced mostly singular matrix error. you can try the following code which I found to be helpful when searching for the systematic form of H. Its also include the calculation of G.
% Gauss-Jordan elimination
swaps=zeros(m,2);
swaps_count=1;
n=size(H, 2);
m=size(H, 1);
j=1;
index=1;
while index<=m
i=index;
while (HH(i,j)==0)&(i<m)
i=i+1;
end
if HH(i,j)==1
temp=HH(i,:);
HH(i,:)=HH(index,:);
HH(index,:)=temp;
for i=1:m
if (index~=i)&(HH(i,j)==1)
HH(i,:)=mod(HH(i,:)+HH(index,:),2);
end
end
swaps(swaps_count,:)=[index j];
swaps_count=swaps_count+1;
index=index+1;
j=index;
else
j=j+1;
end
end
for i=1:swaps_count-1
temp=HH(:,swaps(i,1));
HH(:,swaps(i,1))=HH(:,swaps(i,2));
HH(:,swaps(i,2))=temp;
end
G=[(HH(:,m+1:n))' eye(n-m)];
for i=swaps_count-1:-1:1
temp=G(:,swaps(i,1));
G(:,swaps(i,1))=G(:,swaps(i,2));
G(:,swaps(i,2))=temp;
end
disp(sum(sum((mod(H*G',2)))));

Conditionally replace neighbouring cells

Lets say I have a matrix A:
A =
0 1 0 0
0 0 0 0
0 0 0 1
0 0 0 0
And I want to create a new matrix B of the same dimension where all ones and accompanying neighbours are replaced by the following matrix:
X =
1 1 1
1 2 1
1 1 1
The 2 in matrix X should be placed 'on top' of the 1 values as to get:
B =
1 2 1 0
1 1 2 1
0 0 1 2
0 0 1 1
Values should be added up where elements overlap and matrix X should be 'cut off' in places where it extends the dimensions of matrix A/B The idea is to eventually replace X by a 2d gaussian distribution and matrix A will be large containing many more ones. So it's essential that the code is efficient and fast. This is the code i came up with:
A = [0 1 0 0;0 0 0 0;0 0 0 1;0 0 0 0]
X = [1 1 1;1 2 1;1 1 1]
B = zeros(4,4);
t=1;
indA = find(A==1);
indX = find(X==2);
all = find(X>0);
[iall jall] = ind2sub(size(X),all);
[ia ja] = ind2sub(size(A),indA)
[ix jx] = ind2sub(size(X),indX)
iv = ia-ix
jv = ja-jx
for t=1:numel(iv),
ib = iall+iv(t);
jb = jall+jv(t);
ibjb = [ib(:), jb(:)]
c1 = (ibjb(:,1)>4)|(ibjb(:,1)<1); c2 = (ibjb(:,2)>4)|(ibjb(:,1)<1);
ibjb((c1|c2),:)=[]
isel = ibjb(:,1)-iv(t)
jsel = ibjb(:,2)-jv(t)
B(ibjb(:,1), ibjb(:,2)) = B(ibjb(:,1), ibjb(:,2))+ X(isel, jsel)
t=t+1;
end
Is there a more efficient/faster way (minimizing the loops) to code this function?
What you want is a (2D) convolution. So use conv2:
B = conv2(A, X, 'same');

Plot the density of a matrix

Good day,
In Matlab I have got a matrix which is very sparse. Now I would like to plot the 'density' of the matrix. Let's say I have a matrix A:
A = [3 0 0
0 2 0
0 0 1];
Now the plot should look something like:
x
x
x
So there should be a dot (or something else) at each location (row, column) in which matrix A has got a nonzero value.
Any ideas?
spy is what you need:
% taken from MatLab documentation
B = bucky;
spy(B)
Consider something like this:
subs = zeros(0,2);
for ind = [find(A)']
[r,c] = ind2sub(size(A), ind);
subs = [subs; [r,c]];
end
scatter(subs(:,2), subs(:,1));
set(gca,'YDir','Reverse')
xlim([1 size(A,2)])
ylim([1 size(A,1)])
Which, for the matrix A:
0 1 0 1 1
0 0 0 0 0
0 1 0 0 0
0 1 0 1 1
0 0 1 1 0
Gives you the following scatter plot:
What about this :
A=[3 0 0; 0 2 0; 0 0 1];
imagesc(A)