2

Je souhaite créer des images de formation à partir de la sortie de transformation de bassin versant afin que chaque cellule comporte un seul segment d'image. Comment puis-je le faire de la manière la plus efficace?Quel est le moyen le plus efficace de construire des images d'entraînement à partir de la sortie de segmentation?

Plus de détails: suppose L est la sortie de la segmentation des bassins versants:

L = 

1  1  2 
1  0  2 
1  2  2 
0  0  2 
  • 0 est-fond
  • 1 est le numéro de segment 1, 2 est le numéro de segment 2 et ainsi de suite.

Je veux construire une cellule avec deux images, chacune contiennent un segment:

cell1= 

1  1 
1  0 
1  0 

cell2= 

0  2 
0  2 
2  2 
0  2 

Je sais que je peux le faire avec certains pour les boucles et si les conditions, mais je dois avoir une solution avec le meilleur coût de calcul. Peut-être que Matlab a une fonction de bulit-in pour cette tâche?

+1

Parfois, les boucles ne sont pas lentes. Essayez, profilez, améliorez. "L'optimisation précoce est la racine de tous les maux!" –

+1

Je suis d'accord avec @AnderBiguri, et l'utilisation d'une fonction intégrée ne signifie pas que cette fonction n'utilise pas de boucles! Ceci est juste une "boîte noire". – obchardon

+0

en attendant, j'ai trouvé une solution intégrée moi-même. – Woeitg

Répondre

2

Il peut être fait avec une suite linner ;-)

U = regionprops(L, 'Image') 

Comparaison entre les solutions (L est une image pixel 1200x1600):

>> tic; 
for index=1:100 
U = regionprops(L, 'Image'); 
end 
toc; 

Le temps écoulé est 20,138794 secondes.

>>tic; 
for index=1:100 
N = max(L(:)); %//number of segments 
C = cell(N,1); %//create Cell Array 
[height, width] = size(L); %//get dimensions of image 

for target=1:N %//for each segment.. 

    %//search column-wise to get first and last column index 
    col_start = ceil(find(L==target,1)/height); 
    col_end = ceil(find(L==target,1,'last')/height); 

    %//search row-wise to get first and last row index 
    row_start = ceil(find(L.'==target,1)/width); 
    row_end = ceil(find(L.'==target,1,'last')/width); 

    T = L(row_start:row_end , col_start:col_end); %//image segment of bounding box 
    T(T~=target) = 0; %//set non-targets to 0 

    C{target} = T; %//add to cell array 

end; 
end 
toc; 

temps écoulé est 300,744868 secondes.

>> tic; 
for index=1:100 
u = unique(L(:)); 
B = arrayfun(@(x) removePadding(L, x)*2, u(2:end), 'UniformOutput', false); 
end 
toc; 

temps écoulé est 182,193148 secondes.

+0

Oui mais est-ce rapide? Mesurer contre la solution de Lincoln. 'regionprops' est une fonction plutôt" lourde ", donc je m'intéresse à savoir s'il fonctionne rapidement. – tim

+0

Semble rapide ou vous avez simplement une machine de bête par rapport à la mienne ;-)) – tim

+0

Vous devriez l'exécuter comme quelques centaines de fois pour s'assurer que la charge actuelle de votre ordinateur ou certains outils d'arrière-plan n'influencera pas les résultats. Alors faites comme je l'ai fait ci-dessus: 'tic; pour i = 1: 500% ICI LA SOLUTION RÉELLE fin; toc' – tim

1

Puisque vous avez demandé un moyen efficace, je pense que la solution suivante devrait bien fonctionner. Bien qu'il utilise 1 boucle for, il boucle seulement N fois où N est le number of segments dans votre sortie transformée de bassin, ce qui est généralement très faible pour les segmentations d'image (N = 2 pour votre exemple).

N = max(L(:)); %//number of segments 
C = cell(N,1); %//create Cell Array 
[height, width] = size(L); %//get dimensions of image 

for target=1:N %//for each segment.. 

    %//search column-wise to get first and last column index 
    col_start = ceil(find(L==target,1)/height); 
    col_end = ceil(find(L==target,1,'last')/height); 

    %//search row-wise to get first and last row index 
    row_start = ceil(find(L.'==target,1)/width); 
    row_end = ceil(find(L.'==target,1,'last')/width); 

    T = L(row_start:row_end , col_start:col_end); %//image segment of bounding box 
    T(T~=target) = 0; %//set non-targets to 0 

    C{target} = T; %//add to cell array 

end 
+0

Merci pour la réponse. Je pense qu'une comparaison équitable entre votre réponse et les autres nécessite un calcul automatique du nombre de segments au début du code. Pouvez-vous le modifier? – Woeitg

+0

@Woeitg Je vais juste ajouter quelque chose comme 'longueur (unique (L)) - 1' ou quelque chose. – Lincoln

+0

cette modification a rendu votre code très lent (voir l'édition dans ma réponse) – Woeitg

1

J'ai écrit ici une solution propre/court, mais je ne sais pas s'il est plus rapide ou plus lent que celui de Lincoln. Essayez simplement vous-même en utilisant tic/toc.

function A = removePadding(L, x) 
    A = (L==x); 
    A(all(A == 0, 2), :)=[]; 
    A(:, all(A == 0, 1))=[]; 
end 

L = [1 1 2;1 0 2; 1 2 2; 0 0 2]; 
u = unique(L(:)) 
arrayfun(@(x) removePadding(L, x)*2, u(2:end), 'UniformOutput', false) 

sortie Will:

ans = 
{ 
    [1,1] = 

    1 1 
    1 0 
    1 0 

    [2,1] = 

    0 2 
    0 2 
    2 2 
    0 2 

} 

Attention: La fonction removePadding supprimera toutes les lignes/colonnes qui ne contiennent que des zéros. Cela signifie que cela ne fonctionnera pas si une région n'est pas connectée, car les lignes/cols intermédiaires seront également supprimés. Mais je pense que cela ne se produira pas dans votre cas car le bassin versant (IMO) ne retournera que le même indice de région (par exemple 1 pour la région 1) si la région est entièrement connectée.


Speedtest: D'abord, L et ma fonction est définie. Maintenant, le test:

>> tic; 
for i = 1:1000 
    u = unique(L(:)); 
    B = arrayfun(@(x) removePadding(L, x)*2, u(2:end), 'UniformOutput', false); 
end 
>> toc 
Elapsed time is 4.89563 seconds. 

Vous pouvez maintenant copier ce test-extrait et le modifier pour vérifier également la vitesse de calcul Lincolns.

EDIT2: Je défini comme solution Lincolns C = myFun(L) puis exécutez le nouveau test de vitesse:

>> tic; 
>> for i = 1:1000 
    B = myFun(L); 
end 
>> toc 
Elapsed time is 1.01026 seconds. 

semble beaucoup plus rapide :-) Même si en utilisant une boucle for.

+0

tnx pour la réponse. J'ai aussi trouvé moi-même une solution de bulit-in que j'ai envoyée séparément. le temps écoulé de votre code dans mon PC est 0.532072 secondes! pour mon propre code, le temps écoulé est de 0,018671 secondes. Cependant, je ne suis pas sûr si je calcule le temps écoulé de manière correcte ... – Woeitg