matlab - Calculate Euclidean distance between RGB vectors in a large matrix -
matlab - Calculate Euclidean distance between RGB vectors in a large matrix -
i have rgb matrix of set of different pixels. (n pixels => n rows, rgb => 3 columns). have calculate minimum rgb distance between 2 pixels matrix. tried loop approach, because set big (let's n=24000), looks take forever programme finish. there approach? read pdist
, rgb euclidean distance cannot used it.
k=1; = 1:n j = 1:n if (i~=j) dist_vect(k)=rgb_dist(u(i,1),u(j,1),u(i,2),u(j,2),u(i,3),u(j,3)) k=k+1; end end end
euclidean distance between 2 pixels: so, pdist syntax this: d=pdist2(u,u,@calc_distance());
, u obtained this:
rgbimage = imread('peppers.png'); rgb_columns = reshape(rgbimage, [], 3) [u, m, n] = unique(rgb_columns, 'rows','stable');
but if pdist2
loops itself, how should come in parameters function?
function[distance]=rgb_dist(r1, r2, g1, g2, b1, b2),
where r1,g1,b1,r2,g2,b2 components of each pixel.
i made new function this:
function[distance]=rgb_dist(x,y) distance=sqrt(sum(((x-y)*[3;4;2]).^2,2)); end
and called d=pdist(u,u,@rgb_dist);
, got 'error using pdist (line 132) 'distance' argument must string or function.'
testing rgb_dist new function alone, these input set
x=[62,29,64; 63,31,62; 65,29,60; 63,29,62; 63,31,62;]; d=rgb_dist(x,x); disp(d);
outputs values of 0.
contrary post says, can utilize euclidean distance part of pdist
. have specify flag when phone call pdist
.
the loop have described above can computed by:
dist_vect = pdist(u, 'euclidean');
this should compute l2
norm between each unique pair of rows. seeing matrix has rgb pixel per row, , each column represents single channel, pdist
should totally fine application.
if want display distance matrix, row i
, column j
corresponds distance between pixel in row i
, row j
of matrix u
, can utilize squareform
.
dist_matrix = squareform(dist_vect);
as additional bonus, if want find 2 pixels in matrix share smallest distance, can find
search on lower triangular half of dist_matrix
. diagonals of dist_matrix
going zero vector distance should 0. in addition, matrix symmetric , upper triangular half should equal lower triangular half. therefore, can set diagonal , upper triangular half inf
, search minimum elements remaining. in other words:
indices_to_set = true(size(dist_matrix)); indices_to_set = triu(indices_to_set); dist_matrix(indices_to_set) = inf; [v1,v2] = find(dist_matrix == min(dist_matrix(:)), 1);
v1
, v2
contain rows of u
rgb pixels contained smallest euclidean distance. note specify sec parameter 1
want find 1 match, post has stated requirement. if wish find all vectors match same distance, remove sec parameter 1
.
seeing how want weight each component of euclidean distance, can define own custom function calculate distances between 2 rgb pixels. such, instead of specifying euclidean
, can specify your own function can calculate distances between 2 vectors within matrix calling pdist
so:
pdist(x, @(xi,xj) ...);
@(xi,xj)...
anonymous function takes in vector xi
, matrix xj
. pdist
need create sure custom distance function takes in xi
1 x n
vector single row of pixels. xj
m x n
matrix contains multiple rows of pixels. such, function needs homecoming m x 1
vector of distances. therefore, can accomplish weighted euclidean distance so:
weights = [3;4;2]; weuc = @(xi, xj, w) sqrt(bsxfun(@minus, xi, xj).^2 * w); dist_matrix = pdist(double(u), @(xi, xj) weuc(xi, xj, weights));
bsxfun
can handle nicely replicate xi
many rows need to, , should compute single vector every single element in xj
subtracting. square each of differences, weight weights
, take square root , sum. note didn't utilize sum(x,2)
, used vector algebra compute sum. if recall, computing dot product between square distance of each component weight. in other words, x^{t}y
x
square distance of each component , y
weights each component. sum(x,2)
if like, find more elegant , easy read... plus it's less code!
now know how you're obtaining u
, type uint8
need cast image double
before anything. should accomplish weighted euclidean distance talked about.
as check, let's set in matrix in example, run through pdist
squareform
x=[62,29,64; 63,31,62; 65,29,60; 63,29,62; 63,31,62]; weights = [3;4;2]; weuc = @(xi, xj, w) sqrt(bsxfun(@minus,xi,xj).^2 * w); %// create sure cast double, image uint8 %// don't have here x double, %// remind so! dist_vector = pdist(double(x), @(xi, xj) weuc(xi, xj, weights)); dist_matrix = squareform(dist_vector) dist_matrix = 0 5.1962 7.6811 3.3166 5.1962 5.1962 0 6.0000 4.0000 0 7.6811 6.0000 0 4.4721 6.0000 3.3166 4.0000 4.4721 0 4.0000 5.1962 0 6.0000 4.0000 0
as can see, distance between pixels 1 , 2 5.1962
. check, sqrt(3*(63-62)^2 + 4*(31-29)^2 + 2*(64-62)^2) = sqrt(3 + 16 + 8) = sqrt(27) = 5.1962
. can similar checks among elements within matrix. can tell distance between pixels 5 , 2 0 have made these rows of pixels same. also, distance between each of 0 (along diagonal). cool!
matlab image-processing matrix rgb euclidean-distance
Comments
Post a Comment