I have an interesting question about matrix. In Gibbs distribution, a Gibbs energy U(x) can be compute as
which is a sum of clique potentials Vc(x) over all possible cliques C (right image). A clique c is defined as a subset of sites in S (are neighborhood of x- blue color pixels are neighbor of yellow pixel in left figure) in which every pair of distinct sites are neighbors, except for single-site cliques
In which V(x) is computed as following:
My goal is how to compute U(x). In my above example, x={1,2}. However, I have some stuck at pixel at corner of image that only has less than 8 neighbors (a pixel often has 8 neighbor pixels in normal case). To solve it, I added zeros at corner of edge by convolution image with an mask. But I think it maybe affect to U(x). From above definition, could you help me find U(x=1) and U(x=2) when i consider pixels at corner of image (gray color)? I tried to solve it by below solution but I think my solution is so long and I am not sure is whether correct or not.
This is what I do
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
mask=[ 0 0 0;0 1 0;0 0 0];
Imlabel=conv2(Imlabel,mask); % To solve pixel in corner
num_class=2; % x={1,2}
beta=1;
for label=1:num_class
for i=2:size(Imlabel,1)-1
for j=2:size(Imlabel,2)-1
sum_V=0;
%North, south, east and west neighbors
if(label==Imlabel(i-1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Diagonal pixels
if(label==Imlabel(i-1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i-1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Save
U(i-1,j-1,label)=sum_V; %% Because Index is extended before
end
end
end
Update: Normalization
Currently, based on my understand at here. I computed normalized term as well as gibbs distribution as
P=zeros(size(U));
Z=sum(exp(-U),3);
for i=1:num_class
P(:,:,i)=exp(-U(:,:,i))./Z;
end
Your explanation makes sense as well as the code. However, you can totally get this vectorized by being smart about the kinds of functions you want to use.
For the interested readers, given your source code, what you want to do is the following (in pseudocode):
Create a matrix U that is size(Imlabel,1) x size(Imlabel,2) x num_class large. Each slice of this matrix will determine which the Gibbs energy costs for the 8 neighbouring pixels at each coordinate (i,j) in this slice.
For each class label x...
a. For each pixel in the image (i,j)...
Find those locations defined in an 8-pixel neighbourhood of (i,j) that are equal to x and set them to beta
Find those locations defined in an 8-pixel neighbourhood of (i,j) that are not equal to x and set them to -beta
Compute the sum of all of these beta and -beta values within this 8-pixel neighbourhood and set this at location U(i,j,x)
Therefore, what I would do is create a 3D matrix of costs... let's call this C, where each slice y has the same dimensions as size(Imlabel,1) x size(Imlabel,2) but each location (i,j) in a slice will be beta if Imlabel(i,j) == y and -beta otherwise. Once you do this, you can perform an N-D convolution of this matrix, but using a 2D kernel so that you can compute the summation of the 8-pixel neighbourhoods of each slice separately.
Today's magic menu consists of bsxfun, convn and a side-order of permute to sweeten the pot.
To get the cost matrix C, you can do this. This is assuming Imlabel is not padded with zeros along the boundaries:
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
C = double(bsxfun(#eq, Imlabel, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
The permute function is used to create a single 3D vector that goes from 1 up to as many classes as you have defined. The reason why this is required is because bsxfun does what is known as broadcasting. What will happen in this case is given your matrix Imlabel, using the 3D vector will create a 3D cost matrix in conjunction with the eq or equals function. Each slice of this cost matrix will give you the locations of where it is either equal to the label in question, or it isn't.
You can verify that what we have for the locations matrix that is output from bsxfun is correct:
>> C = double(bsxfun(#eq, Imlabel, permute(1:num_class, [1 3 2])))
C(:,:,1) =
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 0 0 0 1 1 1 1 1
1 1 0 0 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
C(:,:,2) =
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 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 0 0 0 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
As you can see, for each slice, we can see which locations shared that label that is enumerated by that slice and those that don't share the same label. Once we have these locations, we need to cast this to double so that we can modify this to be a cost matrix where -beta is a location that isn't equal to a label for a particular slice and beta is. That is done by the two assignment statements after the bsxfun call.
Once you have this cost matrix, you can pad the boundaries like you did before, but make sure that the boundaries are set to a cost of -beta as you have done in your code:
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
The first line of code denotes the [0 0 0; 0 1 0; 0 0 0] mask that you defined in your code. Now to pad each slice independently to have a border of zeroes, we can use convn to help us do that.
Now that we have that set up, all you have to do is perform the calculation of Gibbs' energy independently per slice:
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
The first line of code denotes a mask where every value is 1 except for the middle, which is 0 and it is a 3 x 3 mask. The reason why you want to do this is because this replaces the if/else statements in your double for loop logic. What you are doing is essentially a convolution where you are adding up all of the 8 neighbours except for the middle itself. This can be accomplished by using a mask that has all 1s except for the central pixel and you set that to 0.
Next, we use convn to compute the Gibbs' energy per slice independently, but using the 'valid' flag so that we can remove the zero-padded border we included at the beginning.
Now, if you take a look at out, it compares with what you have with U, but there is a slight shift because of the way you are indexing into U. Nevertheless, with the above output of out, you can verify that what we have is correct and this will handle the border cases nicely:
>> out
out(:,:,1) =
-2 2 2 2 2 2 2 2 2 -2
2 8 8 8 8 8 6 6 6 2
2 8 8 8 8 8 6 8 6 2
2 6 4 2 4 6 6 6 6 2
2 4 2 0 4 6 8 8 8 2
2 4 2 0 2 6 8 6 6 0
2 6 4 4 6 8 8 6 8 0
2 8 8 8 8 8 8 6 6 0
-2 2 2 2 2 2 2 2 2 -2
out(:,:,2) =
-8 -8 -8 -8 -8 -8 -8 -8 -8 -8
-8 -8 -8 -8 -8 -8 -6 -6 -6 -8
-8 -8 -8 -8 -8 -8 -6 -8 -6 -8
-8 -6 -4 -2 -4 -6 -6 -6 -6 -8
-8 -4 -2 0 -4 -6 -8 -8 -8 -8
-8 -4 -2 0 -2 -6 -8 -6 -6 -6
-8 -6 -4 -4 -6 -8 -8 -6 -8 -6
-8 -8 -8 -8 -8 -8 -8 -6 -6 -6
-8 -8 -8 -8 -8 -8 -8 -8 -8 -8
For example, if we took a look at the top left corner of the first slice, we see that the east, south and south east corners have the same label of 1, and so since beta = 1, our sum would be 3, but then there are the other 5 directions that we didn't consider, and in your code, you set those to -beta and so 3 - 5 = -2.
Let's also take a look at the 6th row, 4th column and let's take a look at the second label or slice. This means that any cardinal directions that are equal to label 2, we should sum these with beta / 1 while anything that isn't equal to label 2 is -beta / -1. As you can see, there are exactly 4 labels of 1 and 4 labels of 2, and so these should cancel out and give us a 0.
You can verify that what we did for all of the other locations in this matrix result in the right calculations.
The full code is simply:
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
C = double(bsxfun(#eq, Imlabel, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
In the case of timing, we can check to see how fast the above approach is compared to your original loop code. I used timeit to help facilitate that.
Here's the script I set up that sets up all of the relevant variables, and measures the time taken with your code and mine:
function test_clique_timing
% Setup
Imlabel_orig =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
num_class=2; % x={1,2}
beta = 1;
function test_orig
mask=[ 0 0 0;0 1 0;0 0 0];
Imlabel=conv2(Imlabel_orig,mask); % To solve pixel in corner
beta=1;
for label=1:num_class
for i=2:size(Imlabel,1)-1
for j=2:size(Imlabel,2)-1
sum_V=0;
%North, south, east and west neighbors
if(label==Imlabel(i-1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Diagonal pixels
if(label==Imlabel(i-1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i-1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Save
U(i-1,j-1,label)=sum_V; %% Because Index is extended before
end
end
end
end
function test_conv
C = double(bsxfun(#eq, Imlabel_orig, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
end
time1 = timeit(#test_orig);
time2 = timeit(#test_conv);
fprintf('Loop code time: %f seconds\n', time1);
fprintf('Vectorized code time: %f seconds\n', time2);
fprintf('Speedup factor: %f', time1/time2);
end
Running the above script, I get these for times:
Loop code time: 0.000049 seconds
Vectorized code time: 0.000060 seconds
Speedup factor: 0.816667
This is done in seconds and I did this using MATLAB R2013a under Mac OS Mavericks 10.10.5. The speedup doesn't look that great. In fact it's a factor less than 1, which is terrible. However, what you have shown is such a small dataset. We should try with a larger dataset and see if this still holds. Let's make the matrix 2500 x 2500, with 10 class labels. I'm going to replace the Imlabel matrix with:
rng(123); %// Set seed for reproducibility
num_class = 10;
Imlabel_orig = randi(10,2500,2500);
This produces random integers from 1 to 10 in a 2500 x 2500 matrix. Doing this and running the code again gives:
Loop code time: 17.553669 seconds
Vectorized code time: 3.321950 seconds
Speedup factor: 5.284146
Yeah... that's much better. On the 2500 x 2500 matrix of 10 labels, it took roughly 17.5 seconds to compute, whereas the the vectorized code with bsxfun / convn / permute outperforms your original loop code by a factor of almost 5.2x.
As for the normalization term to factor into your Gibbs' energy calculation, you currently have this:
P=zeros(size(U));
Z=sum(exp(-U),3);
for i=1:num_class
P(:,:,i)=exp(-U(:,:,i))./Z;
end
If you take advantage of bsxfun, you can simply do this:
Z = sum(exp(-out),3)); %// out is U in my code
P = bsxfun(#rdivide, exp(-out), Z);
This achieves the same thing your code does. For each slice in P, we find the exp and negate the slice as input, and divide each term by Z. For bsxfun, the Z matrix gets replicated for as many slices as there are in out and does the element-wise division much like the loop code does.
Related
I am having trouble creating this matrix in matlab, basically I need to create a matrix that has -1 going across the center diagonal followed be 4s on the diagonal outside of that (example below). All the other values can be zero.
A5 = [-1 4 0 0 0;
4 -1 4 0 0;
0 4 -1 4 0;
0 0 4 -1 4;
0 0 0 4 -1];
I have tried using a command v = [4]; D = diag(v)
but that only works for the center diagonal.
This can also be done using a toeplitz matrix:
function out = tridiag(a,b,c,N)
% TRIDIAG generates a tri-diagonal matrix of size NxN.
% lower diagonal is a
% main diagonal is b
% upper diagonal is c
out = toeplitz([b,a,zeros(1,N-2)],[b,c,zeros(1,N-2)]);
>> tridiag(4,-1,4,5)
ans =
-1 4 0 0 0
4 -1 4 0 0
0 4 -1 4 0
0 0 4 -1 4
0 0 0 4 -1
Note #1: When your desired output is symmetric, you can omit the 2nd input to toeplitz.
Note #2: As the size of the matrix increases, there comes a point where it makes more sense to store it as sparse, as this saves memory and improves performance (assuming your matrix is indeed sparse, i.e. comprised mostly of zeros, as it happens with a tridiagonal matrix). Some useful functions are spdiags, sptoeplitzFEX and blktridiagFEX.
A little hackish, but here it goes:
N = 7; % matrix size
v = [11 22 33]; % row vector containing the diagonal values
w = [0 v(end:-1:1)];
result = w(max(numel(v)+1-abs(bsxfun(#minus, 1:N, (1:N).')),1))
This gives
result =
11 22 33 0 0 0 0
22 11 22 33 0 0 0
33 22 11 22 33 0 0
0 33 22 11 22 33 0
0 0 33 22 11 22 33
0 0 0 33 22 11 22
0 0 0 0 33 22 11
To understand how it works, see some intermediate steps:
>> abs(bsxfun(#minus, 1:N, (1:N).'))
ans =
0 1 2 3 4 5 6
1 0 1 2 3 4 5
2 1 0 1 2 3 4
3 2 1 0 1 2 3
4 3 2 1 0 1 2
5 4 3 2 1 0 1
6 5 4 3 2 1 0
>> max(numel(v)+1-abs(bsxfun(#minus, 1:N, (1:N).')),1)
ans =
4 3 2 1 1 1 1
3 4 3 2 1 1 1
2 3 4 3 2 1 1
1 2 3 4 3 2 1
1 1 2 3 4 3 2
1 1 1 2 3 4 3
1 1 1 1 2 3 4
Use D = diag(u,k) to shift u in k levels above the main diagonal, and D = diag(u,-k) for the opposite direction. Keep in mind that you need u to be in the right length of the k diagonal you want, so if the final matrix is n*n, the k's diagonal will have only n-abs(k) elements.
For you case:
n = 5; % the size of the matrix
v = ones(n,1)-2; % make the vector for the main diagonal
u = ones(n-1,1)*4; % make the vector for +1 and -1 diagonal
A5 = diag(v)+diag(u,1)+diag(u,-1) % combine everything together
Which gives:
A5 =
-1 4 0 0 0
4 -1 4 0 0
0 4 -1 4 0
0 0 4 -1 4
0 0 0 4 -1
I have a data in azimuth and elevation angles with radius 1, e.g., point = [azimuth, elevation, radius]. I would like to divide the sphere surface into 64 regions and get a histogram of the points. For example, in the image below, there are 12 points in the first bin (0 deg <= azimuth < 45 deg,0 deg <= elevation < 45 deg)
I am thinking of using Switch/Case to group the points but that would definitely be very inefficient. Is there any better way?
Edited: I would like to find a way to label the regions (any way will do) and get a histogram, e.g myHist = [... 1 1 ... 10 3 ... ]
I'm not completely sure about it, test it with your data, see how it goes,
r = ones(1,100);
a = 2*pi*rand(1,100);
e = 2*pi*rand(1,100);
[X,Y,Z] = sphere(8) ;
[x y z] = sph2cart(a,e,r);
surf(X,Y,Z);hold on;
plot3(x,y,z,'ko','MarkerFaceColor','k');
axis([-1 1 -1 1 -1 1]);
fields = linspace(0,2*pi,9);
c = {fields,fields};
Hist = hist3(cat(2,a',e'),'Edges',c);
Hist(:,end) = []; Hist(end,:) = [];
Hist =
2 1 0 2 2 2 1 0
0 0 2 1 2 2 3 2
1 2 3 2 0 4 4 2
1 0 0 1 1 2 1 4
0 3 1 1 4 1 3 1
3 3 1 3 4 1 1 0
1 5 2 1 0 0 2 0
0 0 3 1 1 0 2 2
sum(sum(Hist)) = 100;
I think it could be better if you use bar3
The question is about feature detection concept.
I'm stuck after I finding the corner of image and I want to know how to finding the feature point within the computed corners.
Suppose I have grayscale image that have data like this
A = [ 1 1 1 1 1 1 1 1;
1 3 3 3 1 1 4 1;
1 3 5 3 1 4 4 4;
1 3 3 3 1 4 4 4;
1 1 1 1 1 4 6 4;
1 1 1 1 1 4 4 4]
if I use
B = imregionalmax(A);
the result would be like this
B = [ 0 0 0 0 0 0 0 0;
0 1 1 1 0 0 1 0;
0 1 1 1 0 1 1 1;
0 1 1 1 0 1 1 1;
0 0 0 0 0 1 1 1;
0 0 0 0 0 1 1 1]
The question is how do I pick the highest peak inside max local region (in sample how did I chose 5 from 3 and 6 from 4)?
My idea was using B to detect each region and use imregionalmax() again but I'm not good at coding and I need some advice or other ideas.
There are a couple of other easy ways to implement a 2D peak finder: ordfilt2 or imdilate.
ordfilt2
The most direct method is to use ordfilt2, which sorts values in local neighborhoods and picks the n-th value. (The MathWorks example demonstrates how to implemented a max filter.) You can also implement a 3x3 peak finder with ordfilt2 by, (1) using a 3x3 domain that does not include the center pixel, (2) selecting the largest (8th) value and (3) comparing to the center value:
>> mask = ones(3); mask(5) = 0 % 3x3 max
mask =
1 1 1
1 0 1
1 1 1
There are 8 values considered in this mask, so the 8-th value is the max. The filter output:
>> B = ordfilt2(A,8,mask)
B =
3 3 3 3 3 4 4 4
3 5 5 5 4 4 4 4
3 5 3 5 4 4 4 4
3 5 5 5 4 6 6 6
3 3 3 3 4 6 4 6
1 1 1 1 4 6 6 6
The trick is compare this to A, the center value of each neighborhood:
>> peaks = A > B
peaks =
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0
imdilate
Image dilation is usually done on binary images, but grayscale image dilation is simply a max filter (see Definitions section of imdilate docs). The same trick used with ordfilt2 applies here: define a neighborhood that does not include the center neighborhood pixel, apply the filter and compare to the unfiltered image:
B = imdilate(A, mask);
peaks = A > B;
NOTE: These methods only find a single pixel peak. If any neighbors have the same value, it will not be a peak.
The function imregionalmax gives you the 8-connected region containing the maximum and its 8 neighbours (i.e. the 3x3-regions you are seeing). You could then use morphological operations with the same 3x3 structural element to thin out those regions to their centers. E.g.
B = imregionalmax(A);
C = imerode(B, ones(3));
or equivalently
B = imregionalmax(A);
D = bwmorph(B, 'erode');
Alternatively you could write your own maximum finding function using block-processing:
fun = #(block) % your code working on 'block' goes here ...
B = blockproc(A, ones(3), fun)
But most likely this will be slower than the built-in functions.
(I don't have the toolbox available right now, so I can't try that out.)
Also have a look here and here.
Say I have the following two matrices:
>> x = [1 4 3; 6 4 3; 6 9 3; 2 4 3; 5 4 0; 5 3 1; 6 4 7];
>> y = [0 0 1; 1 1 0; 1 1 0; 0 1 1; 0.2 0.8 0.54; 1 1 1; 0 0 0];
Where you can think of x as some image, and y as the degree of membership of each element of x to some region of interest.
Say I set those elements in x that have degree of membership = 1 to 1 (core) and the other elements to 0 as follows:
x = zeros(size(y));
x(y==1) = 1;
In which case I will have the following output:
0 0 1
1 1 0
1 1 0
0 1 1
0 0 0
1 1 1
0 0 0
Now, for the elements of 0, I substitute their values with the value of y in the corresponding location as follows:
x(x==0)=y(x==0);
Now, I select those pixels that are considered 4-neighbours of core but not in core as follows:
four_neighbourhood_pixels = imdilate(core, strel('diamond', 1)) - core;
My question is: how can we select a pixel p that belongs to four_neighbourhood_pixels that minimizes the distance between x & core?
Provided that for distance I calculate it as follows:
pdist([x,core],'minkowski');
Provided that x in the preceding command will be the matrix after substituting the zeros with the degree of membership values y i the corresponding location?
So, how can I select that pixel that belongs to four_neighbourhood_pixels that minimizes the distance between x with the zeros substituted and core?
Thanks.
If I understand correctly, core is the following matrix:
0 0 1
1 1 0
1 1 0
0 1 1
0 0 0
1 1 1
0 0 0
First find the distance between x and core.
dist=pdist([x,core],'minkowski');
dist1=squareform(dist);
[row1,row2]=find(dist1==min(dist1(:)); %interpretation: you get the minimum distance between row1 and row2 of [x core]
Veify if my understanding is correct:
You want a pixel from x which minimizes the distance dist and it should belong to four_neighbourhood_pixels. This is the matrix [x core]
1 4 3 0 0 1
6 4 3 1 1 0
6 9 3 1 1 0
2 4 3 0 1 1
5 4 0 0 0 0
5 3 1 1 1 1
6 4 7 0 0 0
Suppose you get the minimum value between 2nd row and 3rd row. Now based on this tell us what you mean by "find a pixel which minimizes..."
I'm mighty confused about how to correctly apply the FFT transform and its inverse in Matlab. I have a program where I need to
apply FFT2 to a matrix of size 4x32 (corresponding to modes m=-1:2, n=-15:16)
do some processing, which leads to a coefficient matrix for another function, whose Fourier coefficients relate to the first set of data by a simple algebraic (component-wise) formula
Use some properties of the two functions that lets me calculate what I need by just summing up an expression on the form 2*abs(A_n)*cos(phi+n*theta+alpha_n) where A_n is the nth coefficient of the m=1 mode and alpha_n = arg(A_n).
I have experimented a little with the FFT2 function and tried to understand how it arranges its output. From what I understand (from sources in my course literature), the coefficients will be ordered as is illustrated by the following script:
>>m = -1:2; n = -7:8;
>>[N,M] = meshgrid(n,m);
>>MN = M; MN(:,:,2) = N;
>>asfft = #(X) [X(2:4,8:16,:) X(2:4,1:7,:); X(1,8:16,:) X(1,1:7,:)];
>>asfft(MN)
ans(:,:,1) =
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
ans(:,:,2) =
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8 -7 -6 -5 -4 -3 -2 -1
where asfft reorders the indices in the same way I believe fft2 does, but does nothing else. In other words, each index is ordered from 0 up to the max, then from the min to -1. According to the documentation, I should be able to rearrange this so I get 0 in the middle by using fftshift, but it's not giving me the output I expect. Instead, I get this:
>> fftshift(asfft(MN))
ans(:,:,1) =
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
ans(:,:,2) =
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
As you can see, the max is on the wrong side of the spectrum - instead of -7 -6 ... -1 0 1 ... 8 and -1 0 1 2 I have 8 -7 6 ... and 2 -1 0 1. This is fatal for me, since to be able to do the calculation described in 3 above, I need to know the indices of the respective coefficients. (The two layers are also switched, but that doesn't matter for me since I'm only going to do this on MxN matrices, not on N-d-arrays, later.)
Why is this? What am I doing wrong here?
Considering the simple 1D case first, fft gives you:
[X(0) X(1) X(2) ... X(N/2-1) X(-N/2) X(-N/2+1) ... X(-1)]
where I'm using X(k) to denote elements of the mathematical DFT.
All fftshift does is rotate these by N/2, so you end up with:
[X(-N/2) X(-N/2+1) ... X(-1) X(0) X(1) X(2) ... X(N/2-1)]
i.e. linear order.1
In the multi-dimensional case, fftshift simply applies this rotation in all dimensions.
1. Although since by definition, X(k) == X(N+k) for a DFT, the unrotated vector is also in "linear" order!
Check this newsread entry too
http://www.mathworks.com/matlabcentral/newsreader/view_thread/285244
taking a queue from Oli, the problem is that you're not parsing it in the middle:
so for asfft = #(X) [X(2:4,8:16,:) X(2:4,1:7,:); X(1,8:16,:) X(1,1:7,:)];
size(8:16)
ans =
1 9
size(1:7)
ans =
1 7
so do:
asfft = #(X) [X(3:4,9:16,:) X(3:4,1:8,:); X(1:2,9:16,:) X(1:2,1:8,:)];