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;
} |
Partager