IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MATLAB Discussion :

Union d'enveloppes convexes


Sujet :

MATLAB

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2007
    Messages : 182
    Points : 52
    Points
    52
    Par défaut Union d'enveloppes convexes
    Bonjour à toutes et à tous,

    J'ai un ensemble d'enveloppes convexes qui se chevauchent sur une figure matlab et je souhaiterais calculer l'aire que représente l'union de ces enveloppes convexes. il peut y avoir plusieurs "patches" éloignées regroupant des ensemble d'enveloppes convexes, ce qui complique la chose.

    Un exemple en images (je cherche l'aire couverte par la zone noire totale) dans les fichiers attachés à ce topic.

    J'ai pensé aux méthodes d'imagerie: patcher les enveloppes convexes (comme dans l'image2) et ensuite estimer l'aire, problème: lent si beaucoup d'images différentes (ce qui est mon cas) et qui revient à une estimation dépendante de la résolution de l'image.

    Existe-t'il des solutions plus simples et moins couteuses en temps de calcul? La triangulation de Delaunay peut-elle m'être utile dans ce cas?

    Merci par avance,

    Gian

    Edit: je possède l'aire de chaque enveloppe convexe, et j'ai aussi pensé a la fonction polyarea() qui pourrait peut-être m'aider?
    Images attachées Images attachées   

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2007
    Messages : 182
    Points : 52
    Points
    52
    Par défaut
    Pour polybool() et polyarea(), un exemple simple montre que cette fonction n'est pas adaptée à mon problème (un polygone distant renvoie 'NaN' :-/):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    %définition de 3 carrés:
    x = [0,2; 0,0; 2,0 ;2,2; 0,2];
    y = x + 1;
    z = x + 5;
     
    [x(:,1), x(:,2)] = poly2cw(x(:,1),x(:,2));
    [y(:,1), y(:,2)] = poly2cw(y(:,1),y(:,2));
    [z(:,1), z(:,2)] = poly2cw(z(:,1),z(:,2));
     
    %Unions:
    [X,Y] = polybool('union',x(:,1),x(:,2),y(:,1),y(:,2));
    [X2,Y2] = polybool('union',X,Y,z(:,1),z(:,2));
    s = polyarea(X2,Y2);
     
    plot(x(:,1),x(:,2),'b-'); hold on;
    plot(y(:,1),y(:,2),'r-');
    plot(z(:,1),z(:,2),'r-');
    axis equal;

  3. #3
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Bonjour,

    Après union tu auras 2 polygones disjoints. Pour différencier ces 2 polygones, polybool les sépare avec des NaN dans ta liste (X2,Y2). Il faut que tu appliques polyarea à chaque liste séparée par des NaN.
    Pour une bonne utilisation des balises code c'est ici!
    Petit guide du voyageur MATLABien : Le forum La faq Les tutoriels Les sources


    La nature est un livre écrit en langage mathématique. Galilée.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2007
    Messages : 182
    Points : 52
    Points
    52
    Par défaut
    Ok, merci pour l'info, j'essaye ca!

    Je suis également en train d'implémenter une autre solution en partant sur l'idée des algorithmes d'imagerie et ca donne ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    %definir un carré:
    x = [0,2; 0,0; 2,0 ;2,2; 0,2];
    y = x + 1;
    z = x + 5;
     
    [x(:,1), x(:,2)] = poly2cw(x(:,1),x(:,2));
    [y(:,1), y(:,2)] = poly2cw(y(:,1),y(:,2));
    [z(:,1), z(:,2)] = poly2cw(z(:,1),z(:,2));
     
    %Unions:
    [X,Y] = polybool('union',x(:,1),x(:,2),y(:,1),y(:,2));
    [X2,Y2] = polybool('union',X,Y,z(:,1),z(:,2));
    s = polyarea(X2,Y2);
     
    h = figure;
    plot(x(:,1),x(:,2),'b-'); hold on;
    plot(y(:,1),y(:,2),'r-');
    plot(z(:,1),z(:,2),'r-');
    axis equal;
    %patch:
    patch(x(:,1),x(:,2),'k')
    patch(y(:,1),y(:,2),'k')
    patch(z(:,1),z(:,2),'k')
     
     
    %Export (sans les axes):
    saveas(h, 'toto.jpg', 'jpg');
    close
    %Reimport:
    BW = imread('toto.jpg','jpg');
     
    %Binarise:
    ZZ = BW > 255/2;
     
    STATS = regionprops(double(ZZ(:,:,1)),'Area');
    Seul problème, à quoi correspond l'aire? c'est l'aire des pixels noirs je suppose il faut donc que je fasse une opération vis à vis de la résolution et que j'estime la taille d'un pixel? (il faut aussi que j'exporte l'image correctement sans les axes).

    Gian

  5. #5
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Non, pour regionprops, une région c'est une zone de pixel blanc. Dans ton exemple, il faut donc inverser les pixels blancs/noirs.

    Sinon, tu peux éviter la sauvegarde de la figure en jpg :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    %definir un carré:
    x = [0,2; 0,0; 2,0 ;2,2; 0,2];
    y = x + 1;
    z = x + 5;
    
    [x(:,1), x(:,2)] = poly2cw(x(:,1),x(:,2));
    [y(:,1), y(:,2)] = poly2cw(y(:,1),y(:,2));
    [z(:,1), z(:,2)] = poly2cw(z(:,1),z(:,2));
    
    %Unions:
    [X,Y] = polybool('union',x(:,1),x(:,2),y(:,1),y(:,2));
    [X2,Y2] = polybool('union',X,Y,z(:,1),z(:,2));
    s = polyarea(X2,Y2);
    
    h = figure('Color',[1 1 1]);
    plot(x(:,1),x(:,2),'b-'); hold on;
    plot(y(:,1),y(:,2),'r-');
    plot(z(:,1),z(:,2),'r-');
    axis equal;
    %patch:
    patch(x(:,1),x(:,2),'k')
    patch(y(:,1),y(:,2),'k')
    patch(z(:,1),z(:,2),'k')
    
    axis off
    
    f = getframe;
    
    ZZ = rgb2gray(f.cdata) > 255/2;
    Puis le calcul de l'aire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    STATS = regionprops(~ZZ(:,:,1),'Area');
    tu peux aussi éviter l'inversion en changeant la couleur de tes patchs en blancs et changeant le fond de la figure en noir.
    Pour une bonne utilisation des balises code c'est ici!
    Petit guide du voyageur MATLABien : Le forum La faq Les tutoriels Les sources


    La nature est un livre écrit en langage mathématique. Galilée.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2007
    Messages : 182
    Points : 52
    Points
    52
    Par défaut
    Merci pour cette correction, c'est en effet plus propre, cependant tel quel ça ne fonctionne pas (regionprops veut une 'label matrix'). J'ai essayé de faire un cast en double():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ZZ = double(rgb2gray(f.cdata) > 255/2);
    STATS = regionprops(~ZZ,'Area');
    puis en utilisant bwlabel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    L = bwlabel(ZZ,8);
    STATS = regionprops(~L,'Area');
    mais regionprops() ne veut rien savoir.

    Ensuite question idiote, mais comment récupère-ton le vecteur unité de la figure pour connaitre la surface que représente un pixel?

    Merci encore pour ton aide.

  7. #7
    Modérateur

    Homme Profil pro
    Ingénieur en calculs scientifiques
    Inscrit en
    Août 2007
    Messages
    4 639
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Ingénieur en calculs scientifiques

    Informations forums :
    Inscription : Août 2007
    Messages : 4 639
    Points : 7 614
    Points
    7 614
    Par défaut
    Ben si, normalement tel quel le code aurait dû fonctionner, regionprops accepte les tableaux de valeurs logiques, et ZZ est un tableau de valeurs logiques :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ZZ = rgb2gray(f.cdata) > 255/2;
    STATS = regionprops(~ZZ,'Area');
    Quelle version de matlab as-tu?


    Pour la résolution, l'image jpg aurait peut-être permis d'aller plus rapidement. Tu peux avoir les intervalles des axes de ton image :
    puis tu divises les intervalles par la taille de l'image :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dx = (inter(2)-inter(1))/size(ZZ,1);
    dy = (inter(4)-inter(3))/size(ZZ,2);
    Avec le code du dessus, normalement, dx=dy.
    Pour une bonne utilisation des balises code c'est ici!
    Petit guide du voyageur MATLABien : Le forum La faq Les tutoriels Les sources


    La nature est un livre écrit en langage mathématique. Galilée.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    S'il demande une 'label matrix', alors je dirais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ZZ = rgb2gray(f.cdata) > 255/2;
    STATS = regionprops(bwlabel(~ZZ),'Area');

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2007
    Messages : 182
    Points : 52
    Points
    52
    Par défaut
    Avec cette dernière version ça marche correctement (en appliquant le bwlabel()), mais:
    -j'obtiens 2 aires par regionprops()??
    -mon estimation finale est très loin du résultat (j’obtiens une surface de 7 contre 11 en vrai), a quoi est du cette mauvaise estimation? faut-il augmenter la résolution obtenue avec getframe() ? Si oui, comment procède t-on?

    Je mets le code complet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    %definir trois carrés:
    x = [0,2; 0,0; 2,0 ;2,2; 0,2];
    y = x + 1;
    z = x + 5;
     
    h = figure('Color',[1 1 1]);
    plot(x(:,1),x(:,2),'b-'); hold on;
    plot(y(:,1),y(:,2),'r-');
    plot(z(:,1),z(:,2),'r-');
    axis equal;
    %axis square;
    %patch:
    patch(x(:,1),x(:,2),'k')
    patch(y(:,1),y(:,2),'k')
    patch(z(:,1),z(:,2),'k')
     
    axis off;
     
    f = getframe;
     
    %Binarise:
    ZZ = rgb2gray(f.cdata) > 255/2;
     
    STATS = regionprops(bwlabel(~ZZ),'Area');
    aire = STATS.Area;
     
    inter = axis;
    dx = (inter(2)-inter(1))/size(ZZ,1);
    dy = (inter(4)-inter(3))/size(ZZ,2);
     
    airenoire = aire*(dx*dy)
    Edit: Ah, j'ai une piste, en faisant un cast en double(), plutot qu'en passant par bwlabel():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    STATS = regionprops(double(~ZZ),'Area');
    j'obtiens une estimation plus correcte (=11.1368) et regionprops() ne retourne qu'une valeur d'aire. D'autre part, en jouant sur les axes, et la résolution on influ sur la solution (mais on le savait déjà! ). Toutefois je ne m'explique pas un telle différence avec bwlabel()... si vuos avez des idées pour optimiser la solution, je suis preneur!
    Edit2: Pour les deux areas de bwlabel() j'ai compris, il faut les sommer, ca correspond aux aires "disjointes"

Discussions similaires

  1. Enveloppe convexe : quel algo
    Par zenux dans le forum Développement 2D, 3D et Jeux
    Réponses: 6
    Dernier message: 17/02/2008, 18h54
  2. Enveloppe convexe masque
    Par coolzy dans le forum Images
    Réponses: 7
    Dernier message: 14/05/2007, 16h33
  3. Enveloppe Convexe 3D
    Par ToTo13 dans le forum 3D
    Réponses: 3
    Dernier message: 02/05/2007, 16h19
  4. enveloppe convexe
    Par hamdouch dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 15/04/2006, 17h37
  5. Calcul d'enveloppe convexe + triangulation
    Par Celelibi dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 24/11/2005, 18h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo