I have a matrix:
>> A = rand(5,2)
ans =
0.843985 0.911387
0.330442 0.589956
0.828405 0.220234
0.049927 0.632131
0.975574 0.254384
I want to output a new matrix of the same size (or replace the items in the matrix above) where each item is computed as follows:
if the item (x,y) is greater than (max value of the owning column * 0.50) then use the item value
otherwise item = 0
So in the example above,
max(A) = [0.975574 0.911387]
max(A) * 0.50 = [0.488779 0.45569]
the output should be
0.843985 0.911387
0 0.589956
0.828405 0
0 0.632131
0.975574 0
How to apply this function without explicitly looping through each column?
>> A = rand(5,2)
A =
0.8147 0.0975
0.9058 0.2785
0.1270 0.5469
0.9134 0.9575
0.6324 0.9649
>> B = A.*(A>0.5*max(A))
B =
0.8147 0
0.9058 0
0 0.5469
0.9134 0.9575
0.6324 0.9649
Related
I want to calculate the euclidean distance between every element of an n-channeled matrix to every other and then apply the function exp(-dist) to it. My matrix is MxN so the output must be (MxN)x(MxN).
This is my code so far:
MAX=M*N;
A = zeros([MAX,MAX]);
dist= zeros([MAX,MAX]);
for x1=1:MAX
for x2=1:MAX
for i=1:M
for j=1:N
for s=1:M
for z=1:N
%every pixel is a vector rgb
dist(x1,x2) = norm((imIn(i,j)-imIn(s,z)),3);
A(x1,x2) = exp(-dist);
end
end
end
end
end
end
It's really slow and doesn't work - it gives just ones.
I would use bsxfun:
*Note that since the distance is applied to scalar values, I just use abs(a-b). There is no point in call norm(), it's just dead time.
m = 3;
n = 4;
ImIn = rand(m,n)
% first transform to vector
vector = ImIn(:)
% edit: better solution for older versions, see comments
Distances = abs(bsxfun(#minus, vector', vector))
% for latest matlab versions
Distances = abs(vector'- vector)
Ouput:
ImIn =
0.5833 0.9747 0.6369 0.6378
0.4217 0.2235 0.6486 0.4072
0.6525 0.1869 0.2085 0.5017
vector =
0.5833
0.4217
0.6525
0.9747
0.2235
0.1869
0.6369
0.6486
0.2085
0.6378
0.4072
0.5017
Distances =
0 0.1616 0.0693 0.3915 0.3597 0.3964 0.0536 0.0654 0.3747 0.0546 0.1761 0.0816
0.1616 0 0.2308 0.5530 0.1982 0.2348 0.2152 0.2269 0.2132 0.2161 0.0145 0.0800
0.0693 0.2308 0 0.3222 0.4290 0.4656 0.0156 0.0039 0.4440 0.0147 0.2453 0.1508
0.3915 0.5530 0.3222 0 0.7512 0.7879 0.3379 0.3261 0.7662 0.3369 0.5675 0.4731
0.3597 0.1982 0.4290 0.7512 0 0.0366 0.4134 0.4251 0.0150 0.4143 0.1837 0.2782
0.3964 0.2348 0.4656 0.7879 0.0366 0 0.4500 0.4618 0.0217 0.4509 0.2203 0.3148
0.0536 0.2152 0.0156 0.3379 0.4134 0.4500 0 0.0117 0.4284 0.0009 0.2297 0.1352
0.0654 0.2269 0.0039 0.3261 0.4251 0.4618 0.0117 0 0.4401 0.0108 0.2414 0.1469
0.3747 0.2132 0.4440 0.7662 0.0150 0.0217 0.4284 0.4401 0 0.4293 0.1987 0.2932
0.0546 0.2161 0.0147 0.3369 0.4143 0.4509 0.0009 0.0108 0.4293 0 0.2306 0.1361
0.1761 0.0145 0.2453 0.5675 0.1837 0.2203 0.2297 0.2414 0.1987 0.2306 0 0.0945
0.0816 0.0800 0.1508 0.4731 0.2782 0.3148 0.1352 0.1469 0.2932 0.1361 0.0945 0
Check:
>> size(ImIn)
ans =
3 4
>> size(Distances)
ans =
12 12
I'm trying to implement a zero padding zoom using fourier.
I'm using octave and I can't add zeros around my matrix.
The result (after inverse fourier transformation) is very dark.
My goal:
My code:
I=double(imread('montagne.jpeg'));
I = I/255;
%%scaling factor
facteur = 4;
[m,n,r] = size(I);
H=fft2(I);
H = fftshift(H);
%%the new image
B = zeros(facteur*m,facteur*n,3);
%%try to add zeros around my matrix
%% r : rgb channels
for r=1:3
for i=1:m
for j=1:n
B(i+((facteur*m)/4),j+((facteur*n)/4),r) = H(i,j,r);
end
end
end
%% show the image
B= ifftshift(B);
final = ifft2(B);
figure;
imshow(final);
Any suggestions ?
Don't use for-loops to copy matrices. I would try something like:
I = im2double (imread ('IMG_2793.JPG'));
facteur = 4; %%scaling factor
[m, n, r] = size (I);
H = fftshift (fft2 (I));
B = zeros(facteur*m, facteur*n, 3);
ms = round (m * (facteur/2 - 0.5));
ns = round (n * (facteur/2 - 0.5));
B(ms:(m+ms-1), ns:(n+ns-1), :) = H;
final = abs (ifft2 (ifftshift (B)));
figure;
imshow(final * facteur^2);
EDIT:
Btw, there is also the function padarray which does what you want:
octave:1> padarray (magic(3), [1, 1])
ans =
0 0 0 0 0
0 8 1 6 0
0 3 5 7 0
0 4 9 2 0
0 0 0 0 0
On Octave I'm trying to unpack a vector in the format:
y = [ 1
2
4
1
3 ]
I want to return a matrix of dimension ( rows(y) x max value(y) ), where for each row I have a 1 in the column of the original digits value, and a zero everywhere else, i.e. for the example above
y01 = [ 1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0 ]
so far I have
y01 = zeros( m, num_labels );
for i = 1:m
for j = 1:num_labels
y01(i,j) = (y(i) == j);
end
end
which works, but is going get slow for bigger matrices, and seems inefficient because it is cycling through every single value even though the majority aren't changing.
I found this for R on another thread:
f3 <- function(vec) {
U <- sort(unique(vec))
M <- matrix(0, nrow = length(vec),
ncol = length(U),
dimnames = list(NULL, U))
M[cbind(seq_len(length(vec)), match(vec, U))] <- 1L
M
}
but I don't know R and I'm not sure if/how the solution ports to octave.
Thanks for any suggestions!
Use a sparse matrix (which also saves a lot of memory) which can be used in further calculations as usual:
y = [1; 2; 4; 1; 3]
y01 = sparse (1:rows (y), y, 1)
if you really want a full matrix then use "full":
full (y01)
ans =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
Sparse is a more efficient way to do this when the matrix is big.
If your dimension of the result is not very high, you can try this:
y = [1; 2; 4; 1; 3]
I = eye(max(y));
y01 = I(y,:)
The result is same as full(sparse(...)).
y01 =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
% Vector y to Matrix Y
Y = zeros(m, num_labels);
% Loop through each row
for i = 1:m
% Use the value of y as an index; set the value matching index to 1
Y(i,y(i)) = 1;
end
Another possibility is:
y = [1; 2; 4; 1; 3]
classes = unique(y)(:)
num_labels = length(classes)
y01=[1:num_labels] == y
With the following detailed printout:
y =
1
2
4
1
3
classes =
1
2
3
4
num_labels = 4
y01 =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
I've a two matrices
A = [0 0 0; 0 0 0; 0 0 0]
and
B = [2 3 4;]
How will I get
A = [0 0 0; 2 3 4; 0 0 0]
In Octave you could set/update any part of the original matrix.
For example, here is how to add vector B to the second row of a matrix A:
A(2,:) = A(2,:) + B;
Assume the following matrix:
myMatrix = [
1 0 1
1 0 0
1 1 1
1 1 1
0 1 1
0 0 0
0 0 0
0 1 0
1 0 0
0 0 0
0 0 0
0 0 1
0 0 1
0 0 1
];
Given the above (and treating each column independently), I'm trying to create a matrix that will contain the number of rows since the last value of 1 has "shown up". For example, in the first column, the first four values would become 0 since there are 0 rows between each of those rows and the previous value of 1.
Row 5 would become 1, row 6 = 2, row 7 = 3, row 8 = 4. Since row 9 contains a 1, it would become 0 and the count starts again with row 10. The final matrix should look like this:
FinalMatrix = [
0 1 0
0 2 1
0 0 0
0 0 0
1 0 0
2 1 1
3 2 2
4 0 3
0 1 4
1 2 5
2 3 6
3 4 0
4 5 0
5 6 0
];
What is a good way of accomplishing something like this?
EDIT: I'm currently using the following code:
[numRow,numCol] = size(myMatrix);
oneColumn = 1:numRow;
FinalMatrix = repmat(oneColumn',1,numCol);
toSubtract = zeros(numRow,numCol);
for m=1:numCol
rowsWithOnes = find(myMatrix(:,m));
for mm=1:length(rowsWithOnes);
toSubtract(rowsWithOnes(mm):end,m) = rowsWithOnes(mm);
end
end
FinalMatrix = FinalMatrix - toSubtract;
which runs about 5 times faster than the bsxfun solution posted over many trials and data sets (which are about 1500 x 2500 in size). Can the code above be optimized?
For a single column you could do this:
col = 1; %// desired column
vals = bsxfun(#minus, 1:size(myMatrix,1), find(myMatrix(:,col)));
vals(vals<0) = inf;
result = min(vals, [], 1).';
Result for first column:
result =
0
0
0
0
1
2
3
4
0
1
2
3
4
5
find + diff + cumsum based approach -
offset_array = zeros(size(myMatrix));
for k1 = 1:size(myMatrix,2)
a = myMatrix(:,k1);
widths = diff(find(diff([1 ; a])~=0));
idx = find(diff(a)==1)+1;
offset_array(idx(idx<=numel(a)),k1) = widths(1:2:end);
end
FinalMatrix1 = cumsum(double(myMatrix==0) - offset_array);
Benchmarking
The benchmarking code for comparing the above mentioned approach against the one in the question is listed here -
clear all
myMatrix = round(rand(1500,2500)); %// create random input array
for k = 1:50000
tic(); elapsed = toc(); %// Warm up tic/toc
end
disp('------------- With FIND+DIFF+CUMSUM based approach') %//'#
tic
offset_array = zeros(size(myMatrix));
for k1 = 1:size(myMatrix,2)
a = myMatrix(:,k1);
widths = diff(find(diff([1 ; a])~=0));
idx = find(diff(a)==1)+1;
offset_array(idx(idx<=numel(a)),k1) = widths(1:2:end);
end
FinalMatrix1 = cumsum(double(myMatrix==0) - offset_array);
toc
clear FinalMatrix1 offset_array idx widths a
disp('------------- With original approach') %//'#
tic
[numRow,numCol] = size(myMatrix);
oneColumn = 1:numRow;
FinalMatrix = repmat(oneColumn',1,numCol); %//'#
toSubtract = zeros(numRow,numCol);
for m=1:numCol
rowsWithOnes = find(myMatrix(:,m));
for mm=1:length(rowsWithOnes);
toSubtract(rowsWithOnes(mm):end,m) = rowsWithOnes(mm);
end
end
FinalMatrix = FinalMatrix - toSubtract;
toc
The results I got were -
------------- With FIND+DIFF+CUMSUM based approach
Elapsed time is 0.311115 seconds.
------------- With original approach
Elapsed time is 7.587798 seconds.