Let's assume that we have a simple matrix 3rows x 7cols.
The matrix includes only zeros (0) and (1) like:
1 0 1 1 1 0 0
0 0 1 1 0 0 0
0 0 1 0 1 1 0
Senario:
If we know the sum of non-zeros in each row,
(in first row is 4, in second row is 2, in third row is 3.) (blue line)
additional, if we know the sum of each col (1 , 0, 3, 2, 2, 1, 0) (green line)
also if we know the sum of each diagonal from the top-left to bottom-right (1,0,1,2,3,0,1,1,0)(red lines) anti-clockwise
and finally we know the sum of each diagonal from the bottom-left to top-right (0,0,2,1,3,2,1,0,0) (yellow lines)
My question is:
With these values as input (and the lenght of matrix 3x7),
4, 2, 3
1, 0, 3, 2, 2, 1, 0
1, 0, 1, 2, 3, 0, 1, 1, 0
0, 0, 2, 1, 3, 2, 1, 0, 0
How we can draw the first matrix?
After a lot of thoughts I came to the conclusion that this is a linear equation system with 3x7 unknown values and some equations.
Right?
How can I make an algorithm in C, or whatever, to solve these equations?
Should I use a method like gausian equation?
Any help would be greatly appreciated!
Start with the first column. You know the top and bottom values (from the first values of the red & yellow lists). Subtract the sum of these two from the first in the green list, and now you have the middle value as well.
Now just work to the right.
Subtract the first column's middle value from the next value in the red list, and you have the second column's top value. Subtract that same middle value from the next value in the yellow list, and you have the second column's bottom value. Subtract the sum of these two from the next value in the green list, and now you have the middle value for the second column.
et cetera
If you're going to code this up, you can see that the first two columns are a special case, and that'll make the code ugly. I'd suggest using two "ghost" columns of all zeros to the left so that you can use a single method for determining the top, bottom, and middle values for each column.
This is also easily generalizable. You'll just have to use (#rows)-1 ghost columns.
Enjoy.
You can use singular value decomposition to compute a non zero least squares solution to a system of linear homogeneous (and non homogeneous) equations in matrix form.
For a quick overview see:
http://campar.in.tum.de/twiki/pub/Chair/TeachingWs05ComputerVision/3DCV_svd_000.pdf
You should first write out your systems as a matrix equation in the form Ax = b, where x is the 21 unknowns as a column vector, and A is the 28 x 21 matrix that forms the linear system when multiplied out. You essentially need to a compute the matrix A of linear equations, compute the singular value decomposition of A and plug the results into the equation as shown in equation 9.17
There are plenty of libraries that will compute the SVD for you in C, so you only need to formulate the matrix and perform the computations in 9.17. The most difficult part is probably understanding how it all works, with a library SVD function there is relatively little code needed.
To get you started on how to form the equation of linear systems, consider a simple 3 x 3 case.
Suppose that our system is a matrix of the form
1 0 1
0 1 0
1 0 1
We would have the following inputs to the linear system:
2 1 2 (sum of rows - row)
2 1 2 (sum of colums - col)
1 0 3 0 1 (sum of first diagonal sets - t2b)
1 0 3 0 1 (sum of second diagonal sets - b2t)
so now we create a matrix for the linear system
A a1 a2 a3 b1 b2 b3 c1 c2 c3 unknowns (x) = result (b)
sum of row 1 [ 1 1 1 0 0 0 0 0 0 ] [a1] [2]
sum of row 2 [ 0 0 0 1 1 1 0 0 0 ] [a2] [1]
sum of row 3 [ 0 0 0 0 0 0 1 1 1 ] [a3] [2]
sum of col 1 [ 1 0 0 1 0 0 1 0 0 ] [b1] [2]
sum of col 2 [ 0 1 0 0 1 0 0 1 0 ] [b2] [1]
sum of col 3 [ 0 0 1 0 0 1 0 0 1 ] [b3] [2]
sum of t2b 1 [ 1 0 0 0 0 0 0 0 0 ] [c1] [1]
sum of t2b 2 [ 0 1 0 1 0 0 0 0 0 ] [c2] [0]
sum or t2b 3 [ 0 0 1 0 1 0 1 0 0 ] [c3] [3]
sum of t2b 4 [ 0 0 0 0 0 1 0 1 0 ] [0]
sum of t2b 5 [ 0 0 0 0 0 0 0 0 1 ] [1]
sum of b2t 1 [ 0 0 0 0 0 0 1 0 0 ] [1]
sum of b2t 2 [ 0 0 0 1 0 0 0 1 0 ] [0]
sum of b2t 3 [ 1 0 0 0 1 0 0 0 1 ] [3]
sum of b2t 4 [ 0 1 0 0 0 1 0 0 0 ] [0]
sum of b2t 5 [ 0 0 1 0 0 0 0 0 0 ] [1]
When you multiply out Ax, you see that you get the linear system of equations. For example if you multiply out the first row by the unkown column, you get
a1 + a2 + a3 = 2
All you have to do is put a 1 in any of the colums that appear in the equation and 0 elsewhere.
Now all you have to do is compute the SVD of A and plug the result into equation 9.17 to compute the unknowns.
I recommend SVD because it can be computed efficiently. If you would prefer, you can augment the matrix A with the result vector b (A|b) and put A in reduced row echelon form to obtain the result.
For an array of 10x15 ones and zeros, you would be trying to find 150 unknowns and have 10+15+2*(10+15-1) = 73 equations if you ignore that the values are limited to being either one or zero. Obviously you can't create a linear system on that basis which has a unique solution.
So is that constraint enough to give a unique solution?
For a 4x4 matrix with the following sums there are two solutions:
- 1 1 1 1
| 1 1 1 1
\ 0 1 1 0 1 1 0
/ 0 1 1 0 1 1 0
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
So I wouldn't expect there to be a unique solution for larger matrices - the same symmetry would exist in many places:
- 1 1 0 0 1 1
| 1 1 0 0 1 1
\ 0 1 0 0 1 0 1 0 0 1 0
/ 0 1 0 0 1 0 1 0 0 1 0
0 0 0 0 1 0
1 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
0 1 0 0 0 0
0 1 0 0 0 0
0 0 0 0 0 1
0 0 0 0 0 0
0 0 0 0 0 0
1 0 0 0 0 0
0 0 0 0 1 0
How about this as another variation
Count the amount of unknown squares each sum passes through
While there are unsolved cells
Solve all the cells which are passed through by a sum with only one unknown square
Cells are solved by simply subtracting off all the known cells from the sum
Update the amount of unknown squares each sum passes through
No boundary cases but very similar to the previous answer. This would first solve all the corners, then those adjacent to the corners, then those one step more interior from that, and so on...
Edit: Also zero out any paths that have a sum of zero, that should solve any that are solvable (I think)
Related
For example, we have a small matrix
B = [5 2,
3 4]
and the bigger one
A = [1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1]
Now I want paste B into A so that A looks like
A = [1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 5 2
0 0 0 3 4]
That means the values of A of the bottom right has been replaced. I would like to do this without using a for-loop. How is that possible?
PS:
A is always an eye(n) matrix (n is a constant).
B is a square matrix and has a variable size but is always less or equal to A
Find the relevant row and column subscripts of A and put B there.
A(end-size(B,1)+1:end, end-size(B,2)+1:end)=B
It works even if B is not a square matrix.
As in my earlier question I am trying to insert small square matrices along the diagonal of a large matrix. However, these matrices are now contained in a 3D array, and have different values. As before, overlapping values are to be added, and the small matrices are only inserted where they can fit fully inside the large matrix. The step dimension will always be equal to 1.
I have achieved an answer through the use of for-loops, but am attempting to vectorise this code for efficiency. How would I do this? The current, unvectorised code is shown below.
function M = TestDiagonal2()
N = 10;
n = 2;
maxRand = 3;
deepMiniM = randi(maxRand,n,n,N+1-n);
M = zeros(N);
for i = 1:N+1-n
M(i:i+n-1,i:i+n-1) = M(i:i+n-1,i:i+n-1) + deepMiniM(:,:,i);
end
end
The desired result is an NxN matrix with n+1 diagonals populated:
3 1 0 0 0 0 0 0 0 0
4 5 3 0 0 0 0 0 0 0
0 3 3 3 0 0 0 0 0 0
0 0 1 6 3 0 0 0 0 0
0 0 0 4 4 4 0 0 0 0
0 0 0 0 2 3 2 0 0 0
0 0 0 0 0 2 6 2 0 0
0 0 0 0 0 0 4 2 2 0
0 0 0 0 0 0 0 3 3 1
0 0 0 0 0 0 0 0 3 3
This makes use of implicit expansion, as well as sparse to add values at coincident indices, and (:) indexing to linearize a matrix in the usual column-major order.
ind1 = repmat((1:n).', n, 1) + (0:N-n); % column indices for the sum
ind2 = repelem((1:n).', n) + (0:N-n); % row indices for the sum
M = full(sparse(ind1(:), ind2(:), deepMiniM(:), N, N)); % sum over those indices
The first line of code creates some vector with "discrete labels", and the second line of code creates a sparse matrix with ones at the index that the label represents. "eye" creates an identity matrix, but then even if the vector "a" is much longer, this effect of creating a sparse matrix still works!?
Could you please help me understand what is going on?
octave:4> a = [1 3 5 7 9 2 4 6 8 10]
a =
1 3 5 7 9 2 4 6 8 10
octave:5> eye(10)(a,:)
ans =
Permutation Matrix
1 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 1
The notation eye(10)(a,:) in Octave means: build the size-10 identity matrix (eye(10)) and then pick its rows in the order given by a (note that a is used as the first index, which corresponds to rows, and : as second index, which means "take all columns"). So, for example, the 4th row of the result is row 7 of the identity matrix, because the 4th entry of a contains 7.
From this explanation it's clear that a can be as long as you want, provided that all its values are integers in the range 1...10 (these are the rows available in eye(10)).
Note that in Matlab this "chained" indexing is not allowed. You would have to first assign eye(10) to a variable, and then index into that variable:
m = eye(10);
m(a,:)
Lastly, a minor "technical" note: the obtained matrix is not of type logical (Matlab's Boolean data type), nor is it sparse. Rather, it's a full matrix of type double.
So I have this matrix A, which is made of 1 and zeros, I have about 10 to 14 white spots of many pixels, but I want only 1 white pixel/centers coordinate for every cluster of white, how do I calculate how many cluster there are and their centers.
Try to imagine the matrix A as the night sky with white starts in black sky and how to I count the stars and the stars centers, plus the star are made of cluster of white pixels.
also the clusters are not all exactly the same size.
Here is some code using bwlabel and/or regioprops, which are used to identify connected components in a matrix and a buch of other properties, respectively. I think it suits your problem quite well; however you might want to adapt my code a bit as its more of a starting point.
clear
clc
%// Create dummy matrix.
BW = logical ([ 1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 0 0 0]);
%// Identify clusters.
L = bwlabel(BW,4)
Matrix L looks like this:
L =
1 1 1 0 3 3 3 0
1 1 1 0 3 3 3 0
1 1 1 0 3 3 3 0
0 0 0 0 0 0 0 0
0 0 0 0 0 4 4 0
2 2 2 2 0 4 4 0
2 2 2 2 0 4 4 0
2 2 2 2 0 0 0 0
Here you have many ways to locate the center of the clusters. The first one uses the output of bwlabel to find each cluster and calculate the coordinates in a loop. It works and its didactic but it's a bit long and not so efficient. The 2nd method, as mentioned by #nkjt, uses regionprops which does exactly what you want using the 'Centroid' property. So here are the 2 methods:
Method 1: a bit complicated
So bwlabel identified 4 clusters, which makes sense. Now we need to identify the center of each of those clusters. My method could probably be simplified; but I'm a bit out of time so fell free to modify it as you see fit.
%// Get number of clusters
NumClusters = numel(unique(L)) -1;
Centers = zeros(NumClusters,2);
CenterLinIdices = zeros(NumClusters,1);
for k = 1:NumClusters
%// Find indices for elements forming each cluster.
[r, c] = find(L==k);
%// Sort the elements to know hot many rows and columns the cluster is spanning.
[~,y] = sort(r);
c = c(y);
r = r(y);
NumRow = numel(unique(r));
NumCol = numel(unique(c));
%// Calculate the approximate center of the cluster.
CenterCoord = [r(1)+floor(NumRow/2) c(1)+floor(NumCol/2)];
%// Actually this array is not used here but you might want to keep it for future reference.
Centers(k,:) = [CenterCoord(1) CenterCoord(2)];
%// Convert the subscripts indices to linear indices for easy reference.
CenterLinIdices(k) = sub2ind(size(BW),CenterCoord(1),CenterCoord(2));
end
%// Create output matrix full of 0s, except at the center of the clusters.
BW2 = false(size(BW));
BW2(CenterLinIdices) = 1
BW2 =
0 0 0 0 0 0 0 0
0 1 0 0 0 1 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
Method 2 Using regionprops and the 'Centroid' property.
Once you have matrix L, apply regionprops and concatenate the output to get an array containing the coordinates directly. Much simpler!
%// Create dummy matrix.
BW = logical ([ 1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 0 0 0]);
%// Identify clusters.
L = bwlabel(BW,4)
s = regionprops(L,'Centroid');
CentroidCoord = vertcat(s.Centroid)
which gives this:
CentroidCoord =
2.0000 2.0000
2.5000 7.0000
6.0000 2.0000
6.5000 6.0000
Which is much simpler and gives the same output once you use floor.
Hope that helps!
I have an array:
1 1 1 0 0
1 2 2 0 0
1 2 3 0 0
0 0 0 0 0
0 0 0 0 0
I want to make it
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
It is like rotating 1/4 piece of pie 270 degrees to fill out the remaining parts of the pie to make a full circle. Essentially mirroring the entire corner in all directions. I don't want to use any in built matlab features if possible - just some vector tricks if possible. Thanks.
EDIT:
This is embedded within an matrix of zeros of arbitrary size. I want it to work in both the above example and say this example:
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0 0 0 0 0
0 0 1 2 2 0 0 0 0 0 0 0 0 0
0 0 1 2 3 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
Ideally, I want to have a vector say [1,2,3.. N] which can be rotated circularly about the highest value in the array (N) centered about some point xc,yc in the grid. Or if this isn't possible, take an base array [1 1 1, 1 2 2, 1 2 3] and rotate it such that 3 is in the centre and you fill a circle as in the 2nd matrix above.
EDIT:
I found rot90(M,k) rotates matrix M k times but this produces:
Mrot = M + rot90(M,1) + rot90(M,2) + rot90(M,3)
Mrot =
1 1 2 1 1
1 2 4 2 1
2 4 12 4 2
1 2 4 2 1
1 1 2 1 1
This stacks it in the x,y directions which isn't correct.
Assuming the corner you want to replicate is symmetric about the diagonal (as in your example), then you can do this in one indexing step. Given a matrix M containing your sample 5-by-5 matrix, here's how to do it:
>> index = [1 2 3 2 1];
>> M = M(index, index)
M =
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1