Calculate distance between every point of matrix with each other - image

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

Related

Apply a function to each cell in Octave

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

How to generate a matrix with a function pattern?

Background info (Optional reading):
I'm running simulations of reflections of sound waves in against boundaries. The medium conditions for the points in space are set using a matrix. Let's say the dimensions of the space is an N by N grid, and there are two speeds of sound I care about, c0 and c1.
Right now I'm using code like the following to generate barrier patterns
medium.sound_speed = c0*ones(N,N); % set the speed of sound to be c0 everywhere
medium.sound_speed(:, N/2:N) = c1; % set the right half of the grid to a different speed
medium.sound_speed(50:70, 50:70) = c1; % set a box to have a different speed
Or
% set all speeds to c0 except set the diagonal to c1
medium.sound_speed = c0*ones(N,N)-(c0*eye(N,N))+c1*eye(N,N);
However, I can't generate more complex boundaries with different curvatures.
Question
I want to programmatically create matrices with patterns reflecting functions. For instance, I want to enter f(x)=2 and for that to create a matrix that looked something like this, assuming N=6.
[ 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1 1 1 1 1 1
0 0 0 0 0 0
0 0 0 0 0 0 ]
Or f(x)=0.5*x+1
[ 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 1 1
0 0 1 1 0 0
1 1 0 0 0 0
0 0 0 0 0 0]
I would also be able to generate curved patterns like f(x)=1/x, which seems to require some form of the Midpoint circle algorithm, used for drawing curvatures with pixels.
[ 1 0 0 0 0 0
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 1 0 0
0 0 0 0 1 1
0 0 0 0 0 0 ]
In reality, N is at least 128, so manually creating these matrices for shapes with some level of complexity is impractical, and I thought this was an interesting problem.
Does anyone know of some way to do this, or suggestions for alternative approaches?
Thank you in advance.
Edit:
I modified this implementation of Bresenham's algorithm to provide a matrix with the desired line given an origin and an ending point.
function M=bresenham_line(point)
if (abs(point(4)-point(2)) > abs(point(3)-point(1))) % If the line is steep
x0 = point(2);y0 = point(1); x1 = point(4);y1=point(3);% then it would be converted to
token =1; % non steep by changing coordinate
else
x0 = point(1);y0 = point(2); x1 = point(3);y1=point(4);
token = 0;
end
if(x0 >x1)
temp1 = x0; x0 = x1; x1 = temp1;
temp2 = y0; y0 = y1; y1 = temp2;
end
dx = abs(x1 - x0) ; % Distance to travel in x-direction
dy = abs(y1 - y0); % Distance to travel in y-direction
sx = sign(x1 - x0); % sx indicates direction of travel in X-dir
sy = sign(y1 - y0); % Ensures positive slope line
x = x0; y = y0; % Initialization of line
param = 2*dy - dx ; % Initialization of error parameter
for i = 0:dx-1 % FOR loop to travel along X
x_coord(i+1) = x; % Saving in matrix form for plot
y_coord(i+1) = y;
param = param + 2*dy; % parameter value is modified
if (param >0) % if parameter value is exceeded
y = y +1*sy; % then y coordinate is increased
param = param - 2*(dx ); % and parameter value is decreased
end
x = x + 1*sx; % X-coordinate is increased for next point
end
M = zeros(size(x_coord,2), size(y_coord,2));
for i=1:1:size(x_coord,2)
x = x_coord(i);
y = y_coord(i);
M(x,y) = 1;
end
M
Implemented like so:
c1 = 0;
M = bresenham_line([1 1 Nx/2+1 Ny+1]);
medium.sound_speed = c0*ones(Nx,Ny) - (c0*M) + c1*M;
No progress on curved function shapes yet.
A way to get some similar results:
f = #(x)0.5*x; %create the function (x should be written even if the function doesn't depend on x: #(x) 0*x + 2)
N = 6; %choose the size of the atrix
M = zeros(N,N); %create an empty matrix
x = (1:N);
y = round(f(x-1)); %discretization
x(y>N-1|y<0) = [];
y(y>N-1|y<0) = [];
M(sub2ind(size(M),y+1,x)) = 1;
M = flipud(M)
So you can choose your function, then the result in your matrix will look like a discretization of a normal plot.
This is a slightly 'dirty' way of getting something like this, although I you best bet might Bresenham's algorithm.
N = 128;
[X,Y] = meshgrid(1:N,1:N);
bound1 = Y<2*X;
bound2 = Y<2*X+1;
M = xor(bound1,bound2);
bound1 you can define any function y=f(x), and mark the area under it. with bound2 you select and area that is slightly higher (shifted up). Once you take and xor of the two area you get just the desired y=f(x) marked. I think that in order to get reasonable results the shift might be different for more complicated function.
For illustration I used imagesc (the flipud is just for make the (0,0) in the bottom left, instead of the top left):
imagesc(flipud(M));
Edit
Indeed for some function this might not be the best. For example for y=x^2, you have to increase the shift and still does not look great.
bound1 = Y<X.^2;
bound2 = Y<X.^2+15;
M = xor(bound1,bound2);

zero padding zoom fourier

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

Efficiently unpack a vector into binary matrix Octave

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

How to write a function to generate random number 0/1 use another random function?

If I have a function named rand1() which generates number 0(30% probability) or 1(70% probability), how to write a function rand2() which generates number 0 or 1 equiprobability use rand1() ?
Update:
Finally, I found this is a problem on book Introduction to Algorithms (2nd) (I have bought the Chinese edition of this book ), Excercise 5.1-3, the original problem is :
5.1-3
Suppose that you want to output 0 with probability 1/2 and 1 with probability 1/2.
At your disposal is a procedure BIASED-RANDOM, that outputs either 0 or 1. It
outputs 1 with some probability p and 0 with probability 1− p, where 0 < p < 1,
but you do not know what p is. Give an algorithm that uses BIASED-RANDOM
as a subroutine, and returns an unbiased answer, returning 0 with probability 1/2
and 1 with probability 1/2. What is the expected running time of your algorithm
as a function of p?
the solution is :
(see: http://www.cnblogs.com/meteorgan/archive/2012/05/04/2482317.html)
To get an unbiased random bit, given only calls to BIASED-RANDOM, call
BIASED-RANDOM twice. Repeatedly do so until the two calls return different
values, and when this occurs, return the Þrst of the two bits:
UNBIASED-RANDOM
while TRUE
do
x ← BIASED-RANDOM
y ← BIASED-RANDOM
if x != y
then return x
To see that UNBIASED-RANDOM returns 0 and 1 each with probability 1/2, observe
that the probability that a given iteration returns 0 is
Pr {x = 0 and y = 1} = (1 − p)p ,
and the probability that a given iteration returns 1 is
Pr {x = 1 and y = 0} = p(1 − p) .
(We rely on the bits returned by BIASED-RANDOM being independent.) Thus, the
probability that a given iteration returns 0 equals the probability that it returns 1.
Since there is no other way for UNBIASED-RANDOM to return a value, it returns 0
and 1 each with probability 1/2.
Generate two numbers, a and b.
If a is 0 and b is 1 (21% chance), generate a 0.
If a is 1 and b is 0 (21% chance), generate a 1.
For all other cases (58% chance), just generate a new a and b and try again.
If you call rand1 twice, there is an equal chance of getting [1 0] and [0 1], so if you return the first of each non-matching pair (and discard matching pairs) you will get, on average, 0.5(1 - p2 - (1-p)2) output bits per input bit (where p is the probability of rand1 returning 1; 0.7 in your example) and independently of p, each output bit will be 1 with probability 0.5.
However, we can do better.
Rather than throw away the matching pairs, we can remember them in the hope that they are followed by opposite matching pairs - The sequences [0 0 1 1] and [1 1 0 0] are also equally likely, and again we can return the first bit whenever we see such a sequence (still with output probability 0.5.) We can keep combining them indefinitely, looking for sequences like [0 0 0 0 1 1 1 1] etc.
And we can go even further - consider the input sequences [0 0 0 1] and [0 1 0 0] produce the same output ([0]) as it stands, but these two sequences were also equally likely, so we can extract an extra bit of output from this, returning [0 0] for the first case and [0 1]
for the second. This is where it gets more complicated though, as you would need to start buffering output bits.
Both techniques can be applied recursively, and taken to the limit it becomes lossless (i.e. if rand1 has a probability of 0.5, you get an average of one output bit per input bit.)
Full description (with math) here: http://www.eecs.harvard.edu/~michaelm/coinflipext.pdf
You will need to figure out how close you want to get to 50% 0 50% 1.
If you add results from repeated calls to rand1. if the results is 0 or 2 then the value returned is 0 if it is 1 then return 1. (in code you can use modulo 2)
int val = rand1(); // prob 30% 0, and 70% 1
val=(val+rand1())%2; // prob 58% 0, and 42% 1 (#1 see math bellow)
val=(val+rand1())%2; // prob 46.8% 0, and 53.2% 1 (#2 see math bellow)
val=(val+rand1())%2; // prob 51.28% 0, and 48.72% 1
val=(val+rand1())%2; // prob 49.488% 0, and 50.512% 1
val=(val+rand1())%2; // prob 50.2048% 0, and 49.7952% 1
You get the idea. so it is up to you to figure out how close you want the probabilities. every subsequent call will gets you closer to 50% 50% but it will never be exactly equal.
If you want the math for the probabilities:
1
prob ((val+rand1()%2) = 0) = (prob(val = 0)*prob(rand1() = 0)) + (prob(val = 1)*prob(rand1() = 1)
= (0.3*0.3)+(0.7*0.7)
= 0.09 + 0.49
= 0.58
= 58%
prob ((val+rand1()%2) = 1) = (prob(val = 1)*prob(rand1() = 0)) + (prob(val = 0)*prob(rand1() = 1)
= (0.7*0.3)+(0.3*0.7)
= 0.21 + 0.21
= 0.42
= 42%
2
prob ((val+rand1()%2) = 0) = (prob(val = 0)*prob(rand1() = 0)) + (prob(val = 1)*prob(rand1() = 1)
= (0.58*0.3)+(0.42*0.7)
= 0.174 + 0.294
= 0.468
= 46.8%
prob ((val+rand1()%2) = 1) = (prob(val = 1)*prob(rand1() = 0)) + (prob(val = 0)*prob(rand1() = 1)
= (0.42*0.3)+(0.58*0.7)
= 0.126 + 0.406
= 0.532
= 53.2%
Below rand2 function will provide 50% probability for occurence of zero or one.
#define LIMIT_TO_CALCULATE_PROBABILITY 10 //set any even numbers
int rand2()
{
static int one_occurred = 0;
static int zero_occured = 0;
int rand_value = 0;
int limit = (LIMIT_TO_CALCULATE_PROBABILITY / 2);
if (LIMIT_TO_CALCULATE_PROBABILITY == (one_occured + zero_occured))
{
one_occured = 0;
zero_occured = 0;
}
rand_value = rand1();
if ((1 == rand_value) && (one_occured < limit))
{
one_occured++;
return rand_value;
}
else if ((0 == rand_value) && (zero_occured < limit))
{
zero_occured++;
return rand_value;
}
else if (1 == rand_value)
{
zero_occured++;
return 0;
}
else if (0 == rand_value)
{
one_occured++;
return 1;
}
}

Resources