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

OpenCV Discussion :

Affichage d'image en transparence sur une capture vidéo


Sujet :

OpenCV

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2012
    Messages : 4
    Points : 6
    Points
    6
    Par défaut Affichage d'image en transparence sur une capture vidéo
    Bonjour à tous,
    Je vais essayer d’expliquer mon problème le plus facilement possible. Dans le cadre d'un projet je suis en train de développer un programme de reconnaissance et d’apprentissage du langage des signes, ou du moins on essaye .

    Perso je m'occupe d'une partie qui permet à l'utilisateur de choisir un signe sur lequel il pourra s'exercer. Lorsqu'il choisit le signe son contour s'affiche en transparence sur la vidéo et il doit faire en sorte de bien positionner sa main de telle façon à bien coller avec ce contour.

    Si ça colle la couleur du contour, initialement rouge, passe en vert. Mon problème survient à ce moment.

    L'image source est la suivante : http://img11.hostingpics.net/pics/693857tpl.jpg
    Lors du changement de couleur des pixels blancs en pixels rouge ou vert et de la suppression du fond noir pour l'affichage en transparence. Je vois apparaître une sorte de bruit en arrière plan et je n'arrive pas à comprendre d'où cela peut venir.

    J'ai testé mes fonctions de masque et de changement de couleur à part et cela marche très bien ...

    Donc merci à vous si vous pouvez m'aider où même trouver un autre moyen, je reste ouvert

    Je vous poste mon code simplifié (pour l'image main voici le lien http://img11.hostingpics.net/pics/246723main.jpg et pour l'image tpl c'est le lien précédent) .

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    /* 
    Partie apprentissage :
    mise à part le seuillage qui reste à determiner il faut regler le probleme du 
    switch des couleur avec l'apparition d'une sorte de bruit dans le rectangle.
     
    Pour compiler : 
    g++ test.cpp -lopencv_core -lopencv_highgui -lopencv_imgproc -o test
    */
    #include "opencv/highgui.h"
    #include "opencv/cv.h"
    #include <iostream>
     
    using namespace cv;
    using namespace std;
     
    /** \brief createMask
     * Fonction qui créee un masque pour pouvoir afficher le 
     * contour en transparence sur la vidéo
     * @param image image source
     * @return mask image résultat
     */
    IplImage* createMask(IplImage* image) {
    	IplImage *mask;
    	mask = cvCreateImage(cvGetSize(image), 8, 1);
    	//si pixels compris entre la couleur 0,0,0 et 200,200,200 on le remplace par du vide
    	cvInRangeS(image, cvScalar(0, 0, 0), cvScalar(200, 200, 200), mask);
    	cvNot(mask, mask);
    	return mask;
    }
     
    /** \brief changeColorPixel
     * Fonction qui change la couleur des pixels blancs 
     * @param image image source
     * @param c couleur voulue
     * @return result
     */
    IplImage* changeColorPixel(IplImage* image, CvScalar c)
    {
      CvScalar pixel;
      IplImage* result;
      result = cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,3);
      for(int i=0;i<image->height;i++){
        for(int j=0;j<image->width;j++){
          pixel=cvGet2D(image,i,j);
          //si valeur pixel superieur à 250,250,250 (donc plutot blanc), on remplace
          if(pixel.val[0]>=250 && pixel.val[1]>=250 && pixel.val[2]>=250){
    	pixel.val[0]=c.val[0];
    	pixel.val[1]=c.val[1];
    	pixel.val[2]=c.val[2];
    	cvSet2D(result,i,j,pixel);
          }
        }
      }
      return result;
    }
     
     
    int main() {
     
    	IplImage *image, //image de la capture video
    		 *source, //image contour bdd
    		 *contour, //copie de source pour les changements de couleurs
    		 *mask1, // masque que l'on applique sur le contour pour enlever fond noir
    		 *imageM, //image du signe a reconnaitre
    		 *imageM2, //copie de l'image signe en Gray
    		 *tpl; //image template en Gray extraite de la capture video pour comparaison avec le signe
    	IplImage* resultat = cvCreateImage(cvSize(1,1), IPL_DEPTH_32F, 1);//image resultat du matchTemplate
    	// CApture Video
    	CvCapture * capture;
    	// key pour les events clavier
    	char key;
     	//valeur des seuils pour le matchTemplate, seul min_val est utilisé
    	double min_val=1;
    	double max_val=1;
    	//dimension de la capture video (peut changer selon la webcam)
    	int CptWidth = 640;
    	int CptHeight = 480;
     
    	// Importation des images
    	source = cvLoadImage("tpl.jpg"); //contour simple présent dans la bdd
    	imageM = cvLoadImage("main.jpg"); //signe de la bdd choisit par l'utilisateur
     
    	// Creation des fenetres
       	cvNamedWindow("Mode leçon", CV_WINDOW_AUTOSIZE);
     
    	// Initialisation capture video
     	capture = cvCreateCameraCapture(200);
        	if (!capture) {
    		printf("Can't initialize the video capture.\n");
            	return -1;
     	}
     	if(!cvGrabFrame( capture ))
    		printf("Capture de FRAME impossible !\n");
     
    	//transformation de l'image du signe en Gray pour s'affranchir de la contrainte de l'eclairage
    	imageM2 = cvCreateImage(cvGetSize(imageM),8,1);
    	cvCvtColor( imageM, imageM2, CV_BGR2GRAY );
    	cvCanny(imageM2, imageM2, 127,127);
    	cvNot(imageM2, imageM2);
    	//on selectionne la partie de l'image du signe correspondant au template
     	cvSetImageROI(imageM2, cvRect((CptWidth-source->width)/2,(CptHeight-source->height)/2, source->width, source->height));
     
    	while(key != 'Q' && key != 'q') {
     
    		// on prend l'image courante puis on l'inverse pour avoir un effet mirroir
    		image = cvQueryFrame(capture);
    		cvFlip (image, 0, 1);
    		// Si pas d'image tu sors !
    		if(!image)
    			continue;
     
    		//transformation du template en Gray pour comparaison avec le signe
    		tpl = cvCreateImage (cvGetSize(image),8,1);
    		cvCvtColor(image, tpl,CV_BGR2GRAY);
    		//on selectionne la partie de la video correspondant au template
    		cvSetImageROI(tpl, cvRect((CptWidth-source->width)/2,(CptHeight-source->height)/2, source->width, source->height));
     
    		//matchTemplate entre image template et le signe
    		//puis récuperation des valeurs min et max
    		cvMatchTemplate(tpl,imageM2,resultat, CV_TM_SQDIFF_NORMED);
    		cvResetImageROI(tpl);
    		cvMinMaxLoc(resultat, &min_val, &max_val);
    		//affichage des valeurs dans console
    		cout<<"max : "<<max_val<<" min :"<<min_val<<endl;
     
    		//preparation du contour pour affichage en transparence sur l'image de la capture video
    		 contour = changeColorPixel(source, cvScalar(0,0,255)); // au départ rouge
    		 mask1 = createMask(contour); //on enleve le fond noir
    		 //on y affiche le rectangle sur image	
    		 cvRectangle(image, cvPoint((CptWidth-source->width)/2, (CptHeight-source->height)/2), cvPoint((CptWidth-source->width)/2+source->width, (CptHeight-source->height)/2+source->height), cvScalar(0,0,255));	
    		 cvSetImageROI(image, cvRect((CptWidth-source->width)/2,(CptHeight-source->height)/2, source->width, source->height));
    		 //on applique le masque
    		 cvCopy(contour, image, mask1);
    		 cvResetImageROI(image);//on revient à la taille de départ mais maintenant le signe est présent en transparence avec un rectangle autour
     
    		 //Si resultat satisfaisant on change la couleur du contour et du rectangle en vert
    		 //Seuil à regler
    		 if(min_val<=0.2)
    		{
    		  contour=changeColorPixel(source, cvScalar(0,255,0));//vert
    		  mask1 = createMask(contour);
    		  cvRectangle(image, cvPoint((CptWidth-source->width)/2, (CptHeight-source->height)/2), cvPoint((CptWidth-source->width)/2+source->width, (CptHeight-source->height)/2+source->height), cvScalar(0,255,0));	
    		  cvSetImageROI(image, cvRect((CptWidth-source->width)/2,(CptHeight-source->height)/2, source->width, source->height));
    		  cvCopy(contour, image, mask1);
    		  cvResetImageROI(image);
    		}
    		//on affiche 
    		cvShowImage("Mode leçon", image);
    		//Release des images ne servant plus à la fin de la boucle
    		//et surtout EVITE depassement de memoire
    		cvReleaseImage(&tpl);
    		cvReleaseImage(&mask1);
    		cvReleaseImage(&contour);
     
    		key = cvWaitKey(10);
    	}
     
    	// Destroy the window we have created
    	cvDestroyAllWindows();
    	// Destroy all created images
    	cvReleaseImage(&mask1);
    	cvReleaseImage(&source);
    	cvReleaseImage(&imageM);
    	cvReleaseImage(&imageM2);
    	cvReleaseImage(&resultat);
    	cvReleaseImage(&contour);
    	cvReleaseImage(&tpl);
    	cvReleaseImage(&image);
    	// Destroy the capture
    	cvReleaseCapture(&capture);
     
    	return 0;
    }

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Ton problème vient de la fonction changeColorPixel() : si ta condition est remplie, tu mets ton pixel à la valeur rentrée en paramètre, mais si elle n'est pas remplie, tu ne recopies pas la valeur de celui de l'image.
    Ainsi ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if(pixel.val[0]>=250 && pixel.val[1]>=250 && pixel.val[2]>=250){
    	pixel.val[0]=c.val[0];
    	pixel.val[1]=c.val[1];
    	pixel.val[2]=c.val[2];
    	cvSet2D(result,i,j,pixel);
    }
    Devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if(pixel.val[0]>=250 && pixel.val[1]>=250 && pixel.val[2]>=250){
    	cvSet2D(result,i,j,c);
    }else{
    	cvSet2D(result,i,j,pixel);
    }
    Remarques :
    • Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      //dimension de la capture video (peut changer selon la webcam)
      	int CptWidth = 640;
      	int CptHeight = 480;
      Pour cela, tu as la fonction cvGetCaptureProperty() avec les constantes CV_CAP_PROP_FRAME_WIDTH et CV_CAP_PROP_FRAME_HEIGHT
    • Tu as beau faire du C++, tu utilises l'interface C d'OpenCV. Tu te compliques inutilement la vie.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2012
    Messages : 4
    Points : 6
    Points
    6
    Par défaut
    Un grand merci à toi !
    J'aurai quand même pu m'en apercevoir... Mais bon tout marche comme je le voulais, c'est l'essentiel

    Et merci pour cvGetCaptureProperty je ne l'avais pas vu dans la doc, c'est bien pratique.

    Merci encore .

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

Discussions similaires

  1. [Images] Transparence sur une image
    Par Shandler dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 06/11/2008, 12h10
  2. Affichage d'une image de fond sur une JFrame
    Par nashpimp dans le forum Agents de placement/Fenêtres
    Réponses: 21
    Dernier message: 04/08/2008, 15h26
  3. Ecrire un texte transparent sur une image.
    Par insane_80 dans le forum VB.NET
    Réponses: 2
    Dernier message: 28/02/2008, 13h10
  4. Bleu transparent sur une image.
    Par Franck26 dans le forum C++Builder
    Réponses: 7
    Dernier message: 30/07/2007, 15h00
  5. dégradé transparent sur une image
    Par Dionyzos dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 25/04/2005, 15h47

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