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

Silverlight Discussion :

Traitement en arrière plan d'images


Sujet :

Silverlight

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Homme Profil pro
    Développeur
    Inscrit en
    Août 2003
    Messages
    1 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Août 2003
    Messages : 1 496
    Par défaut Traitement en arrière plan d'images
    Bonjour,

    J'ai une première interface qui me permet de choir les images à traiter. Quand je click sur mon bouton "commencer le traitement", j'ai une ChildWindow (DialogResult) qui s'ouvre et qui lance les traitements et affiche les résultats dans un graph.
    Cependant, je me suis heurté au problème suivant : à partir de 5 images la durée des traitements commence à être importante et Silverlight m'indique que mon programme à planté au bout de 30s d'exécution.
    Je me suis donc tourné vers les threads :

    Dans un premier temps j'ai essayé avec un BackgroundWorker mais j'ai l'erreur suivante :
    Accès inter-thread non valide.
    Avec l'objet Thread, je n'ai pas réussi à faire tourner mon programme en arrière plan sans monopoliser toutes les ressouces.

    Voici la structure de mes objets :
    DialogResult :
    Contient mes listes d'images, l'objet graphique accueillant les résultats.

    Traitement :
    - PSNR : sous fonction effectuant des traitements à partir de 2 images.
    - SSIM : objet créant de nombreux sous objet à cause de la complexité du traitement.

    Voici le code avec le BackgroundWorker (erreur ci-dessus) :
    Code c# : 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
    void DoWork(object sender, DoWorkEventArgs e)
            {
                System.Threading.Thread.Sleep(500);
                double r;
                Mark m;
                //processing count
                int n = 0;
                foreach (PictureGroup pg in data.groups) n += pg.picturesWithDistorsion.Count; //image count
                n *= 2;//2 processings: PSNR & SSIM
                //process images
                int i = 0;
                foreach (PictureGroup pg in data.groups)
                {
                    BitmapImage io = pg.original.Image;
                    foreach (Picture p in pg.picturesWithDistorsion)
                    {
                        r = modules.metrics.RunnableMetric.PSNR(io, p.Image);
                        m = new Mark { filename = p.file.Name, mosp = r, metric = "PSNR" };
                        p.marks.Add(m);
                        System.Threading.Thread.Sleep(100);
                        bw.ReportProgress(100 * (++i / n));
                        r = modules.metrics.RunnableMetric.SSIM(io, p.Image);
                        m = new Mark { filename = p.file.Name, mosp = r, metric = "SSIM" };
                        p.marks.Add(m);
                        System.Threading.Thread.Sleep(100);
                        bw.ReportProgress(100 * (++i / n));
                    }
                }
            }

    Je suis ouvert à vos propositions pour effectuer mes traitements en arrière plan et si possible actualiser mon graph au fur et à mesure.

  2. #2
    Nouveau candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 2
    Par défaut
    Bonjour smarties,

    Je pense que la source de tes problèmes dans le multithreading est que tu manipules des objets de type DispatcherObject (BitmapSource en fait partie par exemple) dans ton backgroundworker.
    Les objects de type DispatcherObject ont une affinité avec le thread dans lequel ils sont déclarés, ils ne peuvent pas être utilisés dans d'autres threads.

    Si tu souhaites utiliser tes bitmaps dans un autre thread je ne vois que 2 moyens possibles:
    - instancier tes images dans dans le backgroundworker (l'idéal est d'avoir un stream à disposition pour ça).
    - récupérer les infos de ton images (bytes, dimensions ect) et recréer une image dans ton nouveau thread à partir de ces infos.

    J’espère que ces informations t'aideront.
    En ce qui concerne le transfert des images d'un thread à l'autre, j'ai moi même été confronté à ce problème récemment pour un autre cas de figure. Je t'invite à regarder ma solution que je propose sur mon blog (encore en construction, désolé):
    http://charly-studio.com/blog/generateur-dimage-wpf/

    N'hésites pas à demander des précisions si mon explication n'est pas clair.

    Bon courage

    Charles HETIER

  3. #3
    Membre éprouvé
    Homme Profil pro
    Développeur
    Inscrit en
    Août 2003
    Messages
    1 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Août 2003
    Messages : 1 496
    Par défaut
    Citation Envoyé par ModiCharly Voir le message
    Bonjour smarties,

    Je pense que la source de tes problèmes dans le multithreading est que tu manipules des objets de type DispatcherObject (BitmapSource en fait partie par exemple) dans ton backgroundworker.
    Les objects de type DispatcherObject ont une affinité avec le thread dans lequel ils sont déclarés, ils ne peuvent pas être utilisés dans d'autres threads.

    Si tu souhaites utiliser tes bitmaps dans un autre thread je ne vois que 2 moyens possibles:
    - instancier tes images dans dans le backgroundworker (l'idéal est d'avoir un stream à disposition pour ça).
    - récupérer les infos de ton images (bytes, dimensions ect) et recréer une image dans ton nouveau thread à partir de ces infos.
    Merci, ça m'éclaire beaucoup, je vais essayer lundi avec les données de l'images (pixels + dimensions) dans un premier temps.

  4. #4
    Membre éprouvé
    Homme Profil pro
    Développeur
    Inscrit en
    Août 2003
    Messages
    1 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Août 2003
    Messages : 1 496
    Par défaut
    Le travail en arrière plan fonctionne correctement mais maintenant j'ai quelques problèmes d'affichage :
    - ma ProgressBar ne se met pas à jour ;
    - mes données ne s'actualisent pas avec mon databinding.
    Code c# : 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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
            #region Background Thread Worker
            /// <summary>
            /// When image processing is done
            /// </summary>
            void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                progressText.Text = "Processing complete! " + e.Error.Message;
            }
            public delegate void Run(out double result, BitmapImage img1, BitmapImage img2);
            /// <summary>
            /// Process images in background
            /// </summary>
            void DoWork(object sender, DoWorkEventArgs e)
            {
                System.Threading.Thread.Sleep(500);
                double r;
                Mark m;
                //processing count
                int n = 0;
                foreach (PictureGroup pg in data.groups) n += pg.picturesWithDistorsion.Count; //image count
                n *= 2;//2 processings: PSNR & SSIM
                //process images
                int i = 0;
                foreach (PictureGroup pg in data.groups)
                {
                    foreach (Picture p in pg.picturesWithDistorsion)
                    {
                        r = modules.metrics.RunnableMetric.PSNR(pg.original.pixels, p.pixels, pg.original.Width, pg.original.Height);
                        m = new Mark { filename = p.file.Name, mosp = r, metric = "PSNR" };
                        p.marks.Add(m);
                        bw.ReportProgress(100 * (++i / n));
                        r = modules.metrics.RunnableMetric.SSIM(pg.original.pixels, p.pixels, pg.original.Width, pg.original.Height);
                        m = new Mark { filename = p.file.Name, mosp = r, metric = "SSIM" };
                        p.marks.Add(m);
                        bw.ReportProgress(100 * (++i / n));
                    }
                }
            }
            /// <summary>
            /// Update display (progressbar & text)
            /// </summary>
            void ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                progressText.Text = "Processing images...";
                progress.Value = e.ProgressPercentage;
                if (OriginalList.Items.Count > 0 && OriginalList.SelectedIndex == -1) OriginalList.SelectedIndex = 0;
            }
            #endregion
    J'ai l'erreur suivante dans la console Firefox :
    Error: Unhandled Error in Silverlight Application La référence d'objet n'est pas définie à une instance d'un objet. à imageQuality.upload.LocalResult.RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
    à System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
    à System.ComponentModel.BackgroundWorker.<OnRun>b__1(Object state)
    marks, pictureWithDistorsion sont des ObservableCollection. Je me demande si ça pose problème avec les threads.

  5. #5
    Nouveau candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 2
    Par défaut
    Smarties,

    Les instructions de ton background worker qui impactent l'IHM (mise à jour des propriétés bindées par exemple) doivent s'effectuer dans le thread STA dans lequel ton Application est lancée (thread UI).

    pour cela, tu peux utiliser le dispatcher associé à ton application (Application.Current.Dispatcher) pour effectuer ces opérations dans le thread de ton UI -> utilise la méthode BeginInvoke qui va intercaler "judicieusement" ton opération dans le thread UI.

    Attention de ne pas surcharger en longueur et en quantité d'opérations le dispatcher. En effet, le dispatcher va empiler les opérations à lancer jusqu'à ce qu'il trouve un créneau. Si tu empile trop d'opérations trop vite, la pile va grossir et prendre du retard. Si les opérations sont trop longues, ça risque d'avoir des conséquence sur le bon déroulement du live cycle de l'affichage.

    Ca fonctionnera pour ta progress bar, en revanche, tu risques d'avoir le même problème que dans ton premier post pour ce qui est des images si tu as recréé des Objects de type DispatcherObject et si tu cherches à binder ces images dans ton IHM. Tu risque de devoir repenser à une solution qui exporte le contenu de tes images...

    bon courage!

    A+
    Charles HETIER

  6. #6
    Membre éprouvé
    Homme Profil pro
    Développeur
    Inscrit en
    Août 2003
    Messages
    1 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Août 2003
    Messages : 1 496
    Par défaut
    Depuis le dernier messages que j'ai écrit je traite un tableau de byte[] correspondants aux couleurs en niveau de gris.
    Mais le problème d'affichage donne l'erreur citée dans Firefox

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Traitement en arrière-plan
    Par Hiraa dans le forum VB.NET
    Réponses: 6
    Dernier message: 02/08/2013, 18h45
  2. [XL-2003] Cacher le traitement en arrière plan
    Par pitoumad dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 22/06/2010, 09h24
  3. Réponses: 17
    Dernier message: 17/02/2009, 22h37
  4. Réponses: 1
    Dernier message: 05/10/2008, 22h51

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