How to compute the distance of a set points - matlab

I have a problem about computing the distance of points. Let see my definition. I have a finite set points:
S={a_i=(a_i1,a_i2) ∈ Ω, 1<=i<=k }
where Ω is image domain, i is index of pixel.
The distance function d is tuned by parameter sigma that allows adjustment according to the number of points to be fitted:
Let I:Ω->R given by
I= [200 219 226 228 228 240 243 245 245
212 222 229 233 241 247 248 252 252
220 226 234 239 247 250 250 255 253
225 231 244 248 249 248 247 253 250
233 238 251 252 254 249 242 242 235
243 250 255 246 250 244 230 216 200
252 255 250 231 225 211 187 166 153
250 249 234 213 192 164 129 111 114
236 226 195 168 138 119 93 84 91]
Now, I want to compute distance d with a given sigma=3, I want to compute the distance d that follows the above equation. Could you help me implement it by matlab code? Thank you in advance.

If I'm interpreting the equation right, you have k row/column coordinates. For each pair of row/column coordinates you have ai1,ai2, you wish to compute the term inside the brackets of the expression in your post. This results in k matrices, and you'll then have a matrix d such that it's the same size as your image and it computes the product of all of these matrices together.
However, for numerical stability, if you take the logarithmic sum, add up the terms, and then take the exponential of the result, you'll get the same thing and it's actually much quicker (tip of the hat goes to Nikos M. for the tip).
I'd like to note that x seems to be dealing with image coordinates and has nothing to do with the intensities of the image itself. This makes sense given from what I read from the paper. The paper seems to stress that this distance measure looks at spatial locality of pixel locations.
In terms of ease, the quickest way to get something running would be to have a for loop that accumulates all of the results together.
Something like this:
ai1 = [3, 5, 7]; %// Example row coordinates
ai2 = [6, 8, 9]; %// Example column coordinates
%// Image defined by you
I= [200 219 226 228 228 240 243 245 245
212 222 229 233 241 247 248 252 252
220 226 234 239 247 250 250 255 253
225 231 244 248 249 248 247 253 250
233 238 251 252 254 249 242 242 235
243 250 255 246 250 244 230 216 200
252 255 250 231 225 211 187 166 153
250 249 234 213 192 164 129 111 114
236 226 195 168 138 119 93 84 91];
sigma = 3; %// Defined by you
out = zeros(size(I)); %// Define output image
%// Define 2D grid of points
[x1,x2] = ndgrid(1:size(I,1), 1:size(I,2));
for idx = 1 : numel(ai1) %// Or numel(ai2) as it's the same size
%// Compute internal function
p = 1 - exp(-(x1 - ai1(idx)).^2 / (2*sigma^2)).*exp(-(x2 - ai2(idx)).^2 / (2*sigma^2));
%// Accumulate
out = out + log(p);
end
%// Take anti-log
out = exp(out);
Bear in mind that the above notation is with respect to 1-indexing as MATLAB starts indexing things at 1. Traditionally, image indexing starts at 0, so if you want to start at 0, simply offset ai1 and ai2 by 1, and also in the ndgrid call, subtract the values by 1.
So, modify here:
ai1 = [3, 5, 7] - 1; %// Example row coordinates
ai2 = [6, 8, 9] - 1; %// Example column coordinates
... and here:
%// Define 2D grid of points
[x1,x2] = ndgrid(1:size(I,1), 1:size(I,2));
x1 = x1 - 1; x2 = x2 - 1;
I'm assuming that the zero-indexing is what is desired. As such, with the above code, I get this as the output:
out =
Columns 1 through 8
1.6849 1.1763 0.7129 0.3843 0.2042 0.1387 0.1508 0.2215
1.5092 0.9580 0.4959 0.2025 0.0633 0.0242 0.0372 0.0784
1.4192 0.8515 0.4004 0.1353 0.0236 0 0.0089 0.0249
1.4240 0.8534 0.4032 0.1427 0.0348 0.0084 0.0057 0.0056
1.5171 0.9519 0.4857 0.2003 0.0682 0.0208 0.0047 0
1.6802 1.1341 0.6418 0.3054 0.1241 0.0424 0.0110 0.0029
1.8866 1.3832 0.8733 0.4735 0.2227 0.0903 0.0304 0.0073
2.1040 1.6730 1.1773 0.7265 0.3965 0.1940 0.0855 0.0342
2.3020 1.9666 1.5312 1.0730 0.6811 0.4020 0.2315 0.1446
Column 9
0.3566
0.1563
0.0594
0.0180
0.0056
0.0036
0
0.0199
0.1250
As you can see, the row and column coordinates of what we specified in ai1 and ai2 are zero in the distance matrix while the rest of the points reflect the rough distance from each of the anchor points. It honestly looks like a watered down version of the distance transform. The zero coefficients make perfect sense. Remember, we are taking the product of all of the k matrices together for the final output, and what's going to happen is that x1 and x2 will certainly have a ai1 / ai2 pair and so the subtraction in the exponent thus leads to a 1 output, and 1 - 1 = 0, and the product of anything (except infinity) with 0 is 0.... hence the reason why there's a 0 coefficient there!

Related

How to perform reduced row echelon form on a non-square GF matrix (GF(2^8)) in matlab

%GF(2^8)
m=8
mat1 = gf([160 28 233 185 176],8);
result1 = gf([160 28 233 185 176],8)/gf([160],8)
% 1 77 174 32 220
[R,jb] = rref([1 77 174 32 220;189 244 80 245 190])
I use the result from result1 as 1st row and progressively add the next row vector [189 244 80 245 190]
% reduced row echelon
mat2 = [1 77 174 32 220;189 244 80 245 190]
a = gf([1 77 174 32 220;189 244 80 245 190],8);
r2 = a(2,:); r1 = gf(189,8) * a(1,:);
subt = r2 -r1; a(2,:)= subt./gf(122,8);
a(1,:) = a(1,:)- (gf(77,8) *a(2,:));
disp(a)
mat3 = [[1 0 101 105 110]; [0 1 163 128 97]; [157 233 247 64 118]];
m3 = gf(mat3,8);
m3(3,:)= m3(3,:) - (gf(157,8) * m3(1,:))
m3(3,:)= m3(3,:) - (gf(233,8) * m3(2,:))
m3(3,:)= m3(3,:)./ gf(29,8) .
rref works without GF(2^8). But I am unable to perform the reduction using GF(2^8) . Can someone help me to find a solution and how to proceed?
I will be using the result from the above and append another row-vector to the it. Is there any function we can solve it, instead of going step-by-step

Color code points of 3D scatter plot according to density of points

I have a 3D scatter plot of points in the xyz-sphere. I was wondering if there is a way to colormap/hue the scatter plot based on the density of the data. Basically, the parts of the scatter plot with the most densely clustered data points would be dark red, semi densely clustered data points would be medium red, and sparsely clustered data points would be light red.
This is the way that I was thinking of, but (hopefully) there might be a simpler function or command to do this.
Set a threshold that a data point in the scatter has to be surrounded by:
[ >= 10 other points within a sphere of radius 1 to be colored dark red,
[ 5-9 other points within a sphere of radius 1 to be colored medium red, and
[ 0-4 within a sphere of radius 1 to be colored light red.
Of course, I'm hoping there is a simpler way to do this that involves more than 3 colors in the color map, so if anyone has any ideas how to code this, I'd appreciate the help! Thank you so much.
Here's a snippet of my array:
184 115 3915
185 115 3916
185 115 1205
186 115 4094
187 115 2237
192 115 1519
193 115 1327
201 115 1170
240 115 2946
241 115 1332
54 116 1244
58 116 3650
59 116 3984
60 116 1631
61 116 1198
61 116 1194
62 116 1189
65 116 1185
186 116 3669
188 116 3986
189 116 2027
197 116 1200
201 116 1254
226 116 3752
227 116 1457
242 116 1405
54 117 1191
54 117 1305
56 117 1177
58 117 1169
61 117 1367
62 117 1428
62 117 1434
62 117 1435
63 117 1422
198 117 1197
229 117 1312
230 117 1179
243 117 1272
55 118 1236
56 118 1166
61 118 1191
65 118 1755
57 119 1213
57 119 1176
58 119 1253
62 119 1365
62 119 1331
63 119 1457
63 119 1251
66 119 1842
66 119 1468
59 120 1489
59 120 1387
60 120 1218
60 120 1224
61 120 1214
61 120 1440
62 120 1198
64 120 1240
205 120 3601
205 120 1168
206 120 3727
207 120 4089
208 120 2128
208 120 1160
56 121 1293
57 121 1183
59 121 1371
59 121 1347
61 121 1314
64 121 1346
207 121 3562
208 121 3845
209 121 3534
210 121 1201
210 121 1405
83 122 1794
206 122 1259
207 122 1161
83 123 3550
In my approach I'm using a threshold factor T to determine how many other points are considered in the calculation of distances for each individual point. T = 1 means for every point the average distance to all other points is calculated, T = 0.01 means for every point the average distance to the closest 1% of the the other points is calculated.
figure
%// example data
[X,Y,Z] = sphere(15);
x = [0.1*X(:); 0.4*X(:); 0.7*X(:)];
y = [0.2*Y(:); 0.5*Y(:); 0.8*Y(:)];
z = [0.3*Z(:); 0.6*Z(:); 0.9*Z(:)];
D = [x(:), y(:), z(:)];
N = numel(x);
%// calculation of color vector
[n,m] = ndgrid(1:N,1:N);
%// euclidian distance of each point to every other point
X = arrayfun(#(a,b) sum( (D(a,:) - D(b,:)).^2 ), n, m);
%% subplot 1
%// threshold factor
T = 0.01;
%// sort distances of points
Y = sort(X,2);
%// calculate average distance of the closest T% of all points
Z = mean(Y(:,2:ceil(N*T)),2);
%// plot
subplot(121)
scatter3(x,y,z,20,Z,'filled');
title('T = 0.01')
colormap
colorbar
%% subplot 2
%// threshold factor
T = 1;
Y = sort(X,2);
Z = mean(Y(:,2:ceil(N*T)),2);
%// plot
subplot(122)
scatter3(x,y,z,20,Z,'filled');
title('T = 1')
colormap
colorbar
This is a pretty crude function, but I think it achieves a similar result to what you want.
Loop through each point, calculate the number of points within some tolerance distance.
Plot these points, using the count of nearby points as a scaling for the colour.
Code:
a = rand(1000,3); % Create random matrix, use your data here
n = zeros(size(a,1),1); % Set up array for number of nearby points
tol = 0.2; % Tolerance for (squared) distance to count as "nearby"
sz = size(a,1); % Shorthand for size of data
% Loop over every point
for ii = 1:sz;
dists = sum((repmat(a(ii,:), sz, 1) - a).^2, 2); % Get standard Euclidean distance
n(ii) = nnz(dists < tol); % Count number of points within tolerance
end
% Plot, colouring by an nx3 RGB array, in this case just
% scaling the red and having no green or blue.
scatter3(a(:,1), a(:,2), a(:,3), [], [n./max(n), zeros(numel(n),2)], 'filled');
grid on;
Output:

MATLAB accessing conditional values and performing operation in single column

Just started MATLAB 2 days ago and I can't figure out a non-loop method (since I read they were slow/inefficient and MATLAB has better alternatives) to perform a simple task.
I have a matrix of 5 columns and 270 rows. What I want to do is:
if the value of an element in column 5 of matrix goodM is below 90, I want to take that element and and subtract it from 90.
So far I tried:
test = goodM(:,5) <= 90;
goodM(test) = 999;
It changes all goodM values within column 1 not 5 into 999, in addition this method doesn't allow me to perform operations on the elements below 90 in column 5. Any elegant solution to doing this?
edit:: goodM(:,5)(test) = 999; doesn't seem to work either so I have no idea to specify the target column.
I am assuming you are looking to operate on elements that have values below 90 as your text in the question reads, rather than 'below or equal to' as represented by '<=' as used in your code. So try this -
ind = find(goodM(:,5) < 90) %// Find indices in column 5 that have values less than 90
goodM(ind,5) = 90 - goodM(ind,5) %// Operate on those elements using indices obtained from previous step
Try this code:
b=90-a(a(:,5)<90,5);
For example:
a =
265 104 479 13 176
26 110 447 208 144
379 163 179 366 464
301 48 274 391 26
429 374 174 184 297
495 375 312 373 82
465 272 399 447 420
205 170 373 122 84
1 417 63 65 252
271 277 412 113 500
then,
b=90-a(a(:,5)<90,5);
b =
64
8
6

Comparing 2 different image

I am trying to compare multiple image using corr2 to see the similarity in correlation.
for i=1:2
first_img = imread(sprintf('%g.jpg',i));
first_size = size(first_img);
size_temp = size(first_size);
max_size = max(size_temp);
if max_size == 3
first_img = rgb2gray(first_img);
first_size = size(first_img);
end
for j=i+1:2
second_img = imread(sprintf('%g.jpg',j));
second_size = size(second_img);
size_temp = size(second_size);
max_size = max(size_temp);
if max_size == 3
second_img = rgb2gray(second_img);
second_size = size(second_img);
end
if i == j
continue;end
if first_size ~= second_size
continue;end
if first_size == second_size
correlation_fs = corr2(first_img,second_img);
if correlation_fs == 1
fprintf('%g is the same as %g\n',first_img,second_img);
end
end
end
end
now, the problem show up when the first image compared to the 3rd dummy image which is exactly the same as the first image.
219 is the same as 219
220 is the same as 220
221 is the same as 221
221 is the same as 222
224 is the same as 223
222 is the same as 221
221 is the same as 222
223 is the same as 224
218 is the same as 236
242 is the same as 232
217 is the same as 219
226 is the same as 228
220 is the same as 229
241 is the same as 251
254 is the same as 253
250 is the same as 247
253 is the same as 253
252 is the same as 248
237 is the same as 224
217 is the same as 218
225 is the same as 219
219 is the same as 223
219 is the same as 214
222 is the same as 237
I don't know why this is showing up, it should print that image 1 is the same as image 3, at least is what i want it to.
You are printing out the entire image matrices instead of the image number. Try:
fprintf('%g is the same as %g\n',i,j)
Think about what first_img is, it's a matrix of pixel intensities. So you're printing out all the pixel values.
fprintf('%g is the same as %g\n',first_img,second_img);
Here you are passing two images as arguments. You should have passed the image numbers instead.
fprintf('%g is the same as %g\n', i, j);

Adding multiple nth elements of a matrix repeatedly

I have a matrix 63 rows x 7 columns
I want to select every 7th,8th,9th ongoing value in each column and add them to create a new value.
i.e.
7 8 9th added to a new value
16 17 18th added to a new value...etc
25 26 27th
34 35 36th
43 44 45th
52 53 54th
61 62 63th
So I should end up with a 7x7 matrix.
Without doing this manually, is there a simple command so that if the dimensions of the matrix changes, the output will always be correct?
You can do that easily with a bit of reshaping.
originalMatrix = (1:63)'*(1:7); %'
[nRows,nCols] = size(originalMatrix); %# =63 in this example
stepSize = 9;
nTriplets = floor(nRows/stepSize); %# =7 in this example
%# create index list
idx = bsxfun(#minus,stepSize:stepSize:nRows,[2 1 0]'); %'
idx = idx(:); %# reshape to a vector
%# create 3-by-7-by-7 array from original matrix
tmpMatrix = reshape(originalMatrix(idx,:),3,nTriplets,nCols);
%# sum along dim 1 (to sum e.g. the 7th, 8th, and 9th value)
result = squeeze(sum(tmpMatrix,1));
result =
24 48 72 96 120 144 168
51 102 153 204 255 306 357
78 156 234 312 390 468 546
105 210 315 420 525 630 735
132 264 396 528 660 792 924
159 318 477 636 795 954 1113
186 372 558 744 930 1116 1302
matrix=(1:63)'*(1:7);
n=7;
startind = n:(n+2):size(matrix,1);
endind = (n+2):(n+2):size(matrix,1);
tmp=cumsum(matrix);
tmp(endind,:)-tmp(startind,:)
This will, of course, only work if startind and endind have the same length, which would not be the case for, say, a matrix of size 62x7.
If I had understood your question properly, this slip of code should do what you want. But I admit, maybe it's not the most efficient Matlab code ever-written...
k = 9; n = 7; m = k*n; % 63
A = randi(5,m,n);
startIdx = k*(1:n)+n-k;
endIdx = k*(1:n);
B = zeros(n,n);
for i = 1:n
tmp = A(startIdx(i):endIdx(i),:);
B(i,:) = sum(tmp,1);
end