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

Qt Discussion :

Comment feriez-vous pour afficher des images provenant d'une caméra ?


Sujet :

Qt

  1. #1
    Membre actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2014
    Messages : 103
    Points : 224
    Points
    224
    Par défaut Comment feriez-vous pour afficher des images provenant d'une caméra ?
    Bonjour,

    Je dispose d'une IHM Qt et d'une caméra dont l'acquisition se déroule dans un QThread séparé de celui de l'IHM.

    La caméra acquiert des images selon une fréquence fixée, et stocke le résultat de cette acquisition dans une classe sous forme d'un tableau (unsigned char*). À chaque fois qu'une acquisition est réalisée et stockée, la classe de la caméra émet un signal à l'IHM.

    Je récupère le signal et les données dans l'IHM. Jusqu'ici, aucun souci. J'ai tenté différentes méthodes pour afficher les images récupérées, sans grand succès : cela fonctionnait pour les deux premières images et puis cela bloquait. Pourtant, les données provenant de la caméra continuaient à être récupérées.

    D'où cette question ouverte : comment feriez-vous pour afficher les images envoyées par cette caméra en les mettant à jour à chaque acquisition ?

    D'avance merci,

    Jimmy91

  2. #2
    Membre confirmé
    Avatar de deletme
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2011
    Messages : 257
    Points : 519
    Points
    519
    Par défaut
    Salut,

    Pourrais tu poster ton code (si tu es en droit de le poster bien sur) en lien avec ce que tu nous expliques ?

    Merci
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
    - Martin Golding
    Traduction obligatoire : "Toujours écrire du code en gardant en tête que le mec qui en assurera la maintenance est un psychopathe violent qui connait votre adresse"

  3. #3
    Membre actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2014
    Messages : 103
    Points : 224
    Points
    224
    Par défaut
    Bonjour deletme et merci pour votre réponse !

    Pour répondre à votre question, j'ai réécrit le code de manière allégée, dans le but de mieux comprendre.

    La caméra acquiert des images selon une fréquence donnée. À la fin de chaque acquisition, elle stocke l'image dans un worker travaillant dans le même thread, puis repart sur l'acquisition d'une autre image.

    Ce worker prévient l'interface graphique qu'une nouvelle image est récupérée. Ceci déclenche la récupération de l'image présente dans le worker par l'interface graphique, puis sa copie et son affichage dans le thread principal.

    C'est l'affichage que j'aimerais modifier. En effet, selon la console de debug, l'interface graphique semble récupérer et copier des images avec une fréquence raisonnable (10 Hz environ) alors que sur l'écran, je ne vois que les deux premières images puis il bloque (sans pour autant crasher l'application), alors que la console continue de me rapporter les images.

    Bref ! Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int main(int argc, char* argv)
    {
    	QApplication app(argc, argv);
    	InterfaceGraphique gui;
    	gui.initInterface();
    	gui.initAcquisition();
    	return app.exec();
    }
    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
     
    // Classe représentant la caméra
    class Camera
    {
    public :
    	Camera() 
    	{
     
    	}
     
    	// Les images seront copiées vers l'acquisition worker, il faut donc
    	// que l'objet le connaisse
    	void setAcquisitionWorker(AcquisitionWorker* aw)
    	{
    		acquisitionWorker = aw;
    	}
     
    	void acquisition
    	{
    		unsigned char* input;
    		while (true)
    		{
    			// Récupération de l'image
    			input = recupererImageCamera();
    			// Envoi de l'image vers acquisition worker
    			acquisitionWorker->copierImage(input);
    		}
    	}
    private :
    	AcquisitionWorker* acquisitionWorker;
     
    }
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
    // Classe communicant avec la caméra et l'interface graphique dans un thread séparé
    class AcquisitionWorker
    {
    public :
    	AcquisitionWorker(Camera* camera0) : camera(camera0)
    	{
    		donneesImage = (unsigned char*) malloc(1024 * 768 * sizeof(unsigned char));
    	}
     
    	void copierImage(unsigned char* input)
    	{
    		// Il ne faut pas qu'on puisse récupérer donneesImage pendant sa mise à jour
    		mutex.lock();
    		memcpy_s(donneesImage, 1024*768, input, 1024*768);
    		mutex.unlock();
    		// L'acquisition d'une image donne lieu à un signal qui déclenche la récupération de l'image
    		// dans le worker par l'interface graphique et son affichage
    		emit nouvelleImage();
    	}
     
    	// Copie du contenu de donneesImage vers *output
    	void getImage(unsigned char** output)
    	{
    		// Il ne faut pas qu'on puisse mettre à jour donneesImage pendant sa récupération
    		mutex.lock();
    		memcpy_s(*output, 1024*768, donneesImage, 1024*768);
    		mutex.unlock();
    	}
     
     
    public slots :
    	void acquisition()
    	{
    		camera->setAcquisitionWorker(this);
    		camera->acquisition();	
    	}
     
    signals :
    	void nouvelleImage();
     
    private :
    	// Les images sont récupérées à partir de cette camera
    	Camera* camera;
    	QMutex mutex;
    	// Les images seront copiées ici
    	unsigned char* donneesImage;
     
    };
    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
    37
    38
    39
    40
    41
    42
     
    // Classe communicant avec l'interface graphique dans le thread principal
    class Acquisition : public QObject
    {
    	Q_OBJECT
    public :
    	Acquisition()  
    	{
    		// Initialisation du driver de la caméra
    		camera = new Camera();
     
    		threadAcquisition = new QThread();
    		workerAcquisition = new Acquisitionworker(camera);
    	}
     
    	// output sera mis à jour avec le contenu de donneesImage (acquisitionWorker)
    	void getImage(unsigned char** output)
    	{
    		acquisitionWorker->getImage(output);
    	}
     
    	void initAcquisition()
    	{
    		workerAcquisition->moveToThread(&threadAcquisition);
    		connect(threadAcquisition, &QThread::started, workerAcquisition, &AcquisitionWorker::acquisition);
    		connect(workerAcquisition, &Acquisitionworker::nouvelleImage, this, &Acquisition::nouvelleImage);
    		// Connexions pour sortir du thread proprement
    		// ...
     
    		// Démarrage du thread séparé
    		threadAcquisition->start();
    	}
     
    signals :
    	void nouvelleImage();
    private :
    	QMutex mutex;
    	Camera* camera;
    	QThread* threadAcquisition;
    	AcquisitionworkerAcquisition* workerAcquisition;
     
    };
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    // Classe d'affichage des images acquises (thread principal)
    class InterfaceGraphique : public QObject
    {
    public :
    	InterfaceGraphique()
    	{
    		matrice = cv::Mat(1024, 768, CV_8UC1, cv::Scalar::all(0));	
    	}
     
    	void initInterface()
    	{
    		mainWindow = new QMainWindow();
    		scene = new QGraphicsScene();
    		vue = new QGraphicsView(scene);
    		item = new QGraphicsPixmapItem();
    		scene->addItem(item);
     
    		mainWindow->setCentralWidget(vue);
    		mainWindow->show();
    	}
     
    	void initAcquisition()
    	{
    		acquisition = new Acquisition();
    		connect(acquisition, &Acquisition::newImage, this, &InterfaceGraphique::rafraichir);
    		acquisition->initAcquisition();
    	}
     
    public slots :
    	void rafraichir()
    	{
    		unsigned char* inputImage = (unsigned char*) malloc (1024*768*sizeof(unsigned char));
    		// Copie de l'image récupérée par la caméra vers inputImage
    		acquisition->getImage(&inputImage);
    		image = QImage(inputImage, 1024, 768, Format_Indexed8);
    		// Affichage de l'image acquise
    		scene->setPixmap(QPixmap::fromImage(image));
    	}
    signals :
    private :
    	QMainWindow* mainWindow;
    	QGraphicsScene* scene;
    	QGraphicsView* vue;
    	QGraphicsPixmapItem* item;
     
    	QImage image;
     
    	Acquisition* acquisition;
    };

  4. #4
    Membre actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2014
    Messages : 103
    Points : 224
    Points
    224
    Par défaut
    Hmm, avant d'entrer dans ce code un peu long, je préfère vous prévenir que finalement les images ne sont peut-être pas si bien récupérées. Ne répondez pas pour le moment, merci ! Excusez-moi.

  5. #5
    Membre actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2014
    Messages : 103
    Points : 224
    Points
    224
    Par défaut
    Bon, j'ai vérifié et fait en sorte que les images de la caméra soient récupérées correctement dans la classe INterfaceGraphique. Désolé pour ce contretemps !

    En effet, ligne 36 du fichier d'InterfaceGraphique, je vérifie les pixels de image avec la fonction QImage::pixelIndex et cela me rend bien des valeurs comprises entre 0 et 255 selon l'image.

    J'ai vraiment l'impression qu'il s'agit là d'un problème d'affichage. Est-ce ma façon de construire l'image qui pose problème ?

    Si on veut reprendre les choses depuis le début, mon problème est en fait d'afficher correctement une image à partir d'un unsigned char*.

    Merci d'avance pour vos réponses !

  6. #6
    Membre confirmé
    Avatar de deletme
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2011
    Messages : 257
    Points : 519
    Points
    519
    Par défaut
    Ok, merci de nous prévenir. Dans l'attente de ton retour
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
    - Martin Golding
    Traduction obligatoire : "Toujours écrire du code en gardant en tête que le mec qui en assurera la maintenance est un psychopathe violent qui connait votre adresse"

  7. #7
    Membre actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2014
    Messages : 103
    Points : 224
    Points
    224
    Par défaut
    Malheureusement, mon problème n'est toujours pas résolu ! Les images sont bien récupérées par la caméra et intègres. Ce qui me pose problème, c'est leur affichage : à l'écran, je vois les deux premières images et l'affichage bloque ensuite, sans pour autant produire un crash de l'application...

    Je recherche donc toujours une manière efficace d'afficher des images à partir d'unsigned char* fournis en rafale par une caméra !

    Merci pour votre aide,

    Jimmy91

  8. #8
    Membre actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2014
    Messages : 103
    Points : 224
    Points
    224
    Par défaut
    Petite mise à jour : Problème partiellement résolu, mon utilisation de QGraphicsView n'était pas appropriée. En utilisant QLabel et en n'oubliant pas d'exécuter la fonction repaint, mon affichage fonctionne très bien...

Discussions similaires

  1. Comment faire pour afficher des images dans un textarea ? Sans WYSIWYG.
    Par Zachatim dans le forum Général Conception Web
    Réponses: 3
    Dernier message: 15/02/2016, 21h11
  2. Problème pour afficher des images
    Par stan314 dans le forum Ruby on Rails
    Réponses: 5
    Dernier message: 30/12/2008, 14h17
  3. Config du report server pour afficher des images
    Par squallJ dans le forum Reports
    Réponses: 3
    Dernier message: 26/09/2007, 15h16
  4. Réponses: 4
    Dernier message: 24/06/2007, 19h27
  5. Réponses: 2
    Dernier message: 08/05/2006, 10h03

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