A matlab code I don't understand - matlab

I don't understand what does mean (1:65536 < wthresh) in the command below :
cw = reshape(b(:)' .* (1:65536 < threshold), 256, 256);
b is an image of size 256x256 and 65536=256x256. I only know commands like this one:
cw = reshape(b(:)' .* (b < threshold), 256, 256);
meaning we keep only pixels of b that are smaller than 'threshold'.

Just find out with easy examples:
>> (1:10<3)
ans =
1 1 0 0 0 0 0 0 0 0
This produces a vector where the first 2 elements are set to 1 while the rest are 0.
>> b=1:10
b =
1 2 3 4 5 6 7 8 9 10
>> b.*(1:10<3)
ans =
1 2 0 0 0 0 0 0 0 0
This does an element-wise multiplication with vector b. So basically the first threshold-1 elements are kept, while the rest are set to 0. reshape will rearrange the vector to a 256 x 256 matrix again. Since I don't know the expected output, I cannot judge if this is the desired behavior, or if it is a bug in your code.

Related

Up-/Downsampling of a logical vector (not with zeros)

I hope you can help with a little problem I am having.
I want to upsample and downsample a vector with zeros and ones. We have the functions upsample and downsample for that, however, the upsample function in Matlab only adds zeros to the vector. I would like to repeat the value, instead of just putting in zeros.
Unfortunately the upsample function does not do that. Thus, I tried to use repmat (in the third dimension) and then reshape to get back to the old format. I know it must be possible with these functions, but if I simply use them, the vector just gets duplicated and added to the end.
An example:
The input vector is: [1 0 0 1 0 1 0 1 1 1 0 0] (these should be random).
Now I want to upsample (say) by a factor of 2. Then I want to get:
[1 1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 1 0 0 0 0].
Thanks in advance for any help!
You can use repelem:
>> repelem([1 0 1],2)
ans =
1 1 0 0 1 1
Or using repmat and reshape when input is a column vector:
>> input = [1 0 1];
>> reshape(repmat(input, 2, 1), 1, [])
ans =
1 1 0 0 1 1

Python equivalent for Matlab vector slice

I have the following code in Matlab (I do not have Matlab), that apparently constructs integers by sampling sequences of binary values:
velocity_LUT_10bit = zeros(2^10,1);
for n = 1:length(velocity_LUT_10bit),
imagAC = bin2dec(num2str(bitget(n-1,9:-1:6))) - bitget(n-1,10)*2^4; % Imaginary part of autocorrelation: signed 5-bit integer
realAC = bin2dec(num2str(bitget(n-1,4:-1:1))) - bitget(n-1, 5)*2^4; % Real part of autocorrelation: signed 5-bit integer
velocity_LUT_10bit(n) = velNyq_CF*angle((realAC+0.5)/16 + 1i*(imagAC+0.5)/16)/pi;
end;
I am having trouble understanding the bitget() function. From the docs, the first arg is the sampled sequence, while the second arg specifies the range of the sample, but I am confused about what the slicing x:-y:z means. I understand it from the docs as "sample from index x to z, going right to left by strides of y". Is that correct?
What would be the numpy equivalent of bin2dec(num2str(bitget(n-1,9:-1:6)))? I understood I should be using numpy.packbits(), but I am a bit stuck.
In an Octave session:
>> for n=0:3:15,
bitget(n,1:1:5)
end
ans =
0 0 0 0 0
ans =
1 1 0 0 0
ans =
0 1 1 0 0
ans =
1 0 0 1 0
ans =
0 0 1 1 0
ans =
1 1 1 1 0
This is just the binary representation of the number, with a sliced selection of the bits. Octave/Matlab is using the 'start:step:stop' syntax.
The rest converts the numbers to a string and from binary to decimal:
>> num2str(bitget(13,5:-1:1))
ans = 0 1 1 0 1
>> bin2dec(num2str(bitget(13,5:-1:1)))
ans = 13
bitget(n-1,9:-1:6) must be fetching the 9th to 6th bits (powers of 2) in reverse order. So for a number up to 2^10-1, it's pulling out 'bits' 1-4, 5, 6-9, and 10.
I'm not familiar with Python/numpy binary representations, but here's a start:
>> num2str(bitget(100,10:-1:1))
ans = 0 0 0 1 1 0 0 1 0 0
In [434]: np.binary_repr(100,10)
Out[434]: '0001100100'

More efficient way of symmetrizing a square matrix in MATLAB?

I have an "almost symmetric" matrix, which I wish to symmetrize in MATLAB. For example, I wish to symmetrize
>> A = [0 0 1; 2 0 3; 0 3 0]
A =
0 0 1
2 0 3
0 3 0
into
>> B
B =
0 2 1
2 0 3
1 3 0
Safe assumptions are that diagonal entries of A are all zero and that "the bits to change" are always 0. E.g., I changed A(1, 2) and A(3, 1) in the above example, and original values at both locations were 0.
My best attempt based on #Photon's comment (Thanks Photon!) is
>> C = -0.5*(A.'.*A~=0)+1;
>> B = (A+A.').*C
B =
0 2 1
2 0 3
1 3 0
Is there a better (more efficient or faster) way of achieving this?
What about
B = max( A, A.' );
Assuming all entries of A are non-negative.

Select first n of 1 values from a binary vector (0,1) in MATLAB

I have a binary vector, e.g:
x = [1 1 1 0 0 1 0 1 0 0 0 1]
I want to keep the first 4 elements that are '1' (substituting the rest with '0's). In my example the resulting vector should be:
z = [ 1 1 1 0 0 1 0 0 0 0 0 0]
Any help would be much appreciated.
First construct a vector of zeroes, then use find:
z = false(size(x));
z(find(x, 4)) = true;
No need for find for a binary vector. Use cumsum instead!
>> z = x;
>> z(cumsum( z, 2 ) > 4) = 0;
This solution (unlike find-based answers) can process a stack of such binary vectors at once (all you need is to verify that cumsum works on the proper dimension).
Try following:
z=x;
A=find(z);
z(A(5:end))=0;
Idea here is to make all, but first n, 1's to 0's

Computing linear indices and counting non-zero entries of large sparse matrices in row-first order

Say I have a sparse non-rectangular matrix A:
>> A = round(rand(4,5))
A =
0 1 0 1 1
0 1 0 0 1
0 0 0 0 1
0 1 1 0 0
I would like to obtain the matrix B where the non-zero entries of A are replaced by their linear index in row-first order:
B =
0 2 0 4 5
0 7 0 0 10
0 0 0 0 15
0 17 18 0 0
and the matrix C that where the non-zero entries of A are replaced by the order in which they are found in a row-first search:
C =
0 1 0 2 3
0 4 0 0 5
0 0 0 0 6
0 7 8 0 0
I am looking for vectorized solutions for this problem that scale to large sparse matrices.
If I understand what you are asking, a couple of tranpositions should do the trick. The key is that find(A.') will do "row-first" indexing on A, where .' is the short hand for the transpose of a 2D matrix. So:
>> A = round(rand(4,5))
A =
0 1 0 1 1
0 1 0 0 1
0 0 0 0 1
0 1 1 0 0
then
B=A.';
B(find(B)) = find(B);
B=B.';
gives
B =
0 2 0 4 5
0 7 0 0 10
0 0 0 0 15
0 17 18 0 0
Here's a solution that doesn't require any transposing back and forth:
>> B = A; %# Initialize B
>> C = A; %# Initialize C
>> mask = logical(A); %# Create a logical mask using A
>> [r,c] = find(A); %# Find the row and column indices of non-zero values
>> index = c + (r - 1).*size(A,2); %# Compute the row-first linear index
>> [~,order] = sort(index); %# Compute the row-first order with
>> [~,order] = sort(order); %# two sorts
>> B(mask) = index %# Fill non-zero elements of B
B =
0 2 0 4 5
0 7 0 0 10
0 0 0 0 15
0 17 18 0 0
>> C(mask) = order %# Fill non-zero elements of C
C =
0 1 0 2 3
0 4 0 0 5
0 0 0 0 6
0 7 8 0 0
An outline (Matlab isn't on this machine, so verification is delayed):
You can use find() to get the coordinate list. Let T = A'; [r,c] = find(T)
From the coordinate list, you can create both B and C. Let valB = sub2ind([r,c],T) and valC = 1:length(r)
Use the sparse command to create B and C, e.g. B = sparse(r,c,valB), and then transpose, e.g. B = B' (or could do sparse(c,r,valB)).
Or, as #IanHincks suggests, let B = A'; B(find(B)) = find(B). (I'm not sure why .' is recommended, but, again, I don't have Matlab in front of to check.) For C, simply use C(find(C)) = 1:nnz(A). And transpose back, as he suggests.
Personally, I work with coordinate lists all the time, having migrated away from the sparse matrix representation, just to cut out the costs of index lookups.