performance - ruta - conduccion eficiente ahorro combustible
Clasificación de velocidad eficiente en Matlab (2)
Tengo una imagen de tamaño como RGB uint8(576,720,3)
donde quiero clasificar cada píxel a un conjunto de colores. Me he transformado utilizando rgb2lab
de RGB a LAB espacio, y luego rgb2lab
la capa L por lo que ahora es un double(576,720,2)
consiste en AB.
Ahora, quiero clasificar esto a algunos colores que he entrenado en otra imagen, y calculé sus respectivas representaciones AB como:
Cluster 1: -17.7903 -13.1170
Cluster 2: -30.1957 40.3520
Cluster 3: -4.4608 47.2543
Cluster 4: 46.3738 36.5225
Cluster 5: 43.3134 -17.6443
Cluster 6: -0.9003 1.4042
Cluster 7: 7.3884 11.5584
Ahora, para clasificar / etiquetar cada píxel a un clúster 1-7, actualmente hago lo siguiente (pseudocódigo):
clusters;
for each x
for each y
ab = im(x,y,2:3);
dist = norm(ab - clusters); // norm of dist between ab and each cluster
[~, idx] = min(dist);
end
end
Sin embargo, esto es terriblemente lento (52 segundos) a causa de la resolución de la imagen y de que paso manualmente cada x e y.
¿Hay algunas funciones integradas que pueda usar que realicen el mismo trabajo? Debe haber.
Para resumir: necesito un método de clasificación que clasifique imágenes de píxeles en un conjunto de conglomerados ya definidos.
Use pdist2
(Statistics Toolbox) para calcular las distancias de forma vectorializada:
ab = im(:,:,2:3); % // get A, B components
ab = reshape(ab, [size(im,1)*size(im,2) 2]); % // reshape into 2-column
dist = pdist2(clusters, ab); % // compute distances
[~, idx] = min(dist); % // find minimizer for each pixel
idx = reshape(idx, size(im,1), size(im,2)); % // reshape result
Si no tiene Statistics Toolbox, puede reemplazar la tercera línea por
dist = squeeze(sum(bsxfun(@minus, clusters, permute(ab, [3 2 1])).^2, 2));
Esto da una distancia cuadrada en lugar de distancia, pero con el propósito de minimizarla no importa.
Enfoque # 1
Para una matriz de puntos / píxeles de tamaño N x 2
, puede evitar el permute
como sugiere la otra solución de Luis , lo que podría ralentizar un poco las cosas, tener una especie de "permute-unrolled"
y también trabajar con bsxfun
hacia una matriz 2D
lugar de una matriz 3D
, que debe ser mejor con el rendimiento.
Por lo tanto, suponiendo que los clústeres se ordenan como una matriz de tamaño N x 2
, puede probar este otro bsxfun
basado en bsxfun
:
%// Get a''s and b''s
im_a = im(:,:,2);
im_b = im(:,:,3);
%// Get the minimum indices that correspond to the cluster IDs
[~,idx] = min(bsxfun(@minus,im_a(:),clusters(:,1).'').^2 + ...
bsxfun(@minus,im_b(:),clusters(:,2).'').^2,[],2);
idx = reshape(idx,size(im,1),[]);
Enfoque # 2
Puede probar otro enfoque que aproveche fast matrix multiplication in MATLAB
y se base en esta solución inteligente :
d = 2; %// dimension of the problem size
im23 = reshape(im(:,:,2:3),[],2);
numA = size(im23,1);
numB = size(clusters,1);
A_ext = zeros(numA,3*d);
B_ext = zeros(numB,3*d);
for id = 1:d
A_ext(:,3*id-2:3*id) = [ones(numA,1), -2*im23(:,id), im23(:,id).^2 ];
B_ext(:,3*id-2:3*id) = [clusters(:,id).^2 , clusters(:,id), ones(numB,1)];
end
[~, idx] = min(A_ext * B_ext'',[],2); %//''
idx = reshape(idx, size(im,1),[]); %// Desired IDs
¿Qué está pasando con el cálculo de la matriz de distancia basada en la multiplicación de matrices?
Consideremos dos matrices A
y B
entre las cuales queremos calcular la matriz de distancia. En aras de una explicación más sencilla que sigue a continuación, consideremos A
como 3 x 2
y B
como matrices de 4 x 2
, lo que indica que estamos trabajando con puntos XY. Si tuviéramos A
como N x 3
y B
como matrices de tamaño M x 3
, esos serían puntos XYZ
.
Ahora, si tenemos que calcular manualmente el primer elemento de la matriz del cuadrado de distancia, se vería así:
first_element = ( A(1,1) – B(1,1) )^2 + ( A(1,2) – B(1,2) )^2
cuál podría ser -
first_element = A(1,1)^2 + B(1,1)^2 -2*A(1,1)* B(1,1) + ...
A(1,2)^2 + B(1,2)^2 -2*A(1,2)* B(1,2) … Equation (1)
Ahora, de acuerdo con nuestra multiplicación de matrices propuesta, si usted verifica la salida de A_ext
y B_ext
después de que B_ext
el ciclo en el código anterior, se verían como los siguientes:
Por lo tanto, si realiza la multiplicación de la matriz entre A_ext
y la transposición de B_ext
, el primer elemento del producto sería la suma de la multiplicación por elementos entre las primeras filas de A_ext
y B_ext
, es decir, la suma de estos:
El resultado sería idéntico al resultado obtenido de la Equation (1)
anterior. Esto continuaría para todos los elementos de A
contra todos los elementos de B
que están en la misma columna que en A
Por lo tanto, terminaríamos con la matriz de distancia cuadrada completa. ¡¡Eso es todo lo que hay!!
Variaciones vectorizadas
Las variaciones vectorizadas de los cálculos de la matriz de distancia basada en la multiplicación de la matriz son posibles, aunque no se observaron grandes mejoras de rendimiento con ellas. Dos de estas variaciones se enumeran a continuación.
Variación n. ° 1
[nA,dim] = size(A);
nB = size(B,1);
A_ext = ones(nA,dim*3);
A_ext(:,2:3:end) = -2*A;
A_ext(:,3:3:end) = A.^2;
B_ext = ones(nB,dim*3);
B_ext(:,1:3:end) = B.^2;
B_ext(:,2:3:end) = B;
distmat = A_ext * B_ext.'';
Variación # 2
[nA,dim] = size(A);
nB = size(B,1);
A_ext = [ones(nA*dim,1) -2*A(:) A(:).^2];
B_ext = [B(:).^2 B(:) ones(nB*dim,1)];
A_ext = reshape(permute(reshape(A_ext,nA,dim,[]),[1 3 2]),nA,[]);
B_ext = reshape(permute(reshape(B_ext,nB,dim,[]),[1 3 2]),nB,[]);
distmat = A_ext * B_ext.'';
Por lo tanto, estas podrían considerarse como versiones experimentales también.