Code en C++ permettant avec la Bibliotheque OpenCV de "marquer" des regions d'interets dans des images, notamment pour la realisation de Machine Learning. Le code source original n'est pas de moi, j'ai cependant realiser des modifications afin de rendre le programme plus efficient, et compatible pour les utilisateurs travaillant avec Windows.
Source / Exemple :
/***************objectmarker.cpp******************
Objectmarker for marking the objects to be detected from positive samples and then creating the
description file for positive images.
compile this code and run with two arguments, first one the name of the descriptor file and the second one
the address of the directory in which the positive images are located
while running this code, each image in the given directory will open up. Now mark the edges of the object using the mouse buttons
then press then press "SPACE" to save the selected region, or any other key to discard it. Then use "b" to move to next image. the program automatically
quits at the end. press ESC at anytime to quit.
author: achu_wilson@rediffmail.com
author: provost.kevin@gmail.com
#include <opencv/cv.h>
#include <opencv/cvaux.h>
#include <opencv/highgui.h>
// for filelisting
#include <stdio.h>
#include <io.h>
// for fileoutput
#include <string>
#include <fstream>
#include <sstream>
#include <dirent.h>
#include <sys/types.h>
using namespace std;
IplImage* image=0;
IplImage* image2=0;
int roi_x0=0;
int roi_y0=0;
int roi_x;
int roi_x1=0;
int roi_y1=0;
int roi_y;
int numOfRec=0;
int startDraw = 0;
char* window_name="<SPACE>add <b>save and load next <ESC>exit";
string IntToString(int num)
{
ostringstream myStream; //creates an ostringstream object
myStream << num << flush;
return(myStream.str()); //returns the string form of the stringstream object
};
void on_mouse(int event,int x,int y,int flag, void *param)
{
if(event==CV_EVENT_LBUTTONDOWN)
{
if(!startDraw)
{
roi_x0=x;
roi_y0=y;
startDraw = 1;
} else {
roi_x1=x;
roi_y1=y;
startDraw = 0;
}
}
if(event==CV_EVENT_MOUSEMOVE && startDraw)
{
//redraw ROI selection
image2=cvCloneImage(image);
cvRectangle(image2,cvPoint(roi_x0,roi_y0),cvPoint(x,y),CV_RGB(255,0,255),5);
cvShowImage(window_name,image2);
cvReleaseImage(&image2);
}
}
int main(int argc, char** argv)
{
char iKey=0;
string strPrefix;
string strPostfix;
string input_directory;
string output_file;
if(argc != 1)
{
fprintf(stderr, "%s output_info.txt raw/data/directory/\n", argv[0]);
return -1;
}
input_directory = argv[2];
output_file = argv[1];
/* Get a file listing of all files with in the input directory */
DIR *dir_p = opendir (input_directory.c_str());
struct dirent *dir_entry_p;
if(dir_p == NULL)
{
fprintf(stderr, "Failed to open directory %s\n", input_directory.c_str());
return -1;
}
fprintf(stderr, "Object Marker: Input Directory: %s Output File: %s\n", input_directory.c_str(), output_file.c_str());
// init highgui
cvAddSearchPath(input_directory);
cvNamedWindow(window_name,CV_WINDOW_KEEPRATIO);
cvSetMouseCallback(window_name,on_mouse, NULL);
fprintf(stderr, "Opening directory...");
// init output of rectangles to the info file
ofstream output(output_file.c_str());
fprintf(stderr, "done.\n");
while((dir_entry_p = readdir(dir_p)) != NULL)
{
numOfRec=0;
if(strcmp(dir_entry_p->d_name, ""))
fprintf(stderr, "Examining file %s\n", dir_entry_p->d_name);
strPostfix="";
strPrefix=input_directory;
fprintf(stderr, "Nom repertoire 1 %s\n", strPrefix.c_str());
strPrefix+=dir_entry_p->d_name;
fprintf(stderr, "Nom repertoire 2 %s\n", strPrefix.c_str());
fprintf(stderr, "Loading image %s\n", strPrefix.c_str());
image=cvLoadImage(strPrefix.c_str(),1);
printf("Valeure image %i \n", image);
//Work on current image
if(image != 0)
{
do
{
cvShowImage(window_name,image);
// used cvWaitKey returns:
// <b> save added rectangles and show next image
// <ESC>=27 exit program
// <Space>=32 add rectangle to current image
iKey=cvWaitKey(0);
switch(iKey)
{
case 27:
cvReleaseImage(&image);
cvDestroyWindow(window_name);
return 0;
case 32:
numOfRec++;
printf(" %d. rect x=%d\ty=%d\tx2h=%d\ty2=%d\n",numOfRec,roi_x0,roi_y0,roi_x1,roi_y1);
if(roi_x0 > roi_x1)
{
roi_x=roi_x1;
roi_x1 = roi_x0;
roi_x0 = roi_x;
}
if(roi_y0 > roi_y1)
{
roi_y=roi_y1;
roi_y1 = roi_y0;
roi_y0 = roi_y;
}
printf(" %d. rect x=%d\ty=%d\twidth=%d\theight=%d\n",numOfRec,roi_x0,roi_y0,roi_x1-roi_x0,roi_y1-roi_y0);
strPostfix+=" "+IntToString(roi_x0)+" "+IntToString(roi_y0)+" "+IntToString(roi_x1-roi_x0)+" "+IntToString(roi_y1-roi_y0);
cvRectangle(image,cvPoint(roi_x0,roi_y0),cvPoint(roi_x1,roi_y1),CV_RGB(0,0,205),5);
break;
}
}
while(iKey!='b');
{
// save to info file as later used for HaarTraining:
if(numOfRec>0 && iKey=='b')
{
output << strPrefix << " "<< numOfRec << strPostfix <<"\n";
cvReleaseImage(&image);
}
else
{
fprintf(stderr, "Failed to load image, %s\n", strPrefix.c_str());
}
}
}
}
output.close();
cvDestroyWindow(window_name);
closedir(dir_p);
cvWaitKey(0);
return 0;
}
17 juil. 2012 à 14:36
Quelques remarques.
Sur le fond:
- Efficient => efficace. "Efficient" est la traduction anglaise.
- Si le programme n'est pas entièrement de toi, merci de mettre un lien vers la source originale et de citer l'auteur dans la description et le code.
Sur la forme:
- Évite les using namespace: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- Utilise 0 au lieu de NULL (ou mieux nullptr si tu es en C++0x): http://0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp
- Proscrit les variables globales !
- En C++, point besoin de printf ou de fprintf. Tu as les flux (fstream, sstream, stream...).
- Les commentaires sont moyens, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/ecrire-de-bons-commentaires
- Le "output.close();" n'est pas nécessaire, puisque le close est appelé à la destruction de l'objet.
27 janv. 2013 à 21:11
Merci pour ce code surtout qu'il est destiné aux utilisateurs travaillant avec Windows.
Cependant, j'ai compilé ce code sous Code::Blocks avec openCV,il y a pas d'erreur, mais pendant le 'run' rien ne s'affiche et c'est normal puisque j'ai pas trouvé ou je dois mettre le nom de dossier 'input_directory'ou se trouve mes images ???
je veux savoir comment exécuter ce code sous windows??
Merci
28 janv. 2013 à 01:14
Plusieurs mois après, je reprend mon code pour te répondre.
Regarde ces 2 lignes là :
input_directory = argv[2];
output_file = argv[1];
Il te suffit de passer en argument (lors de l'appel de ton programme en console) ton dossier d'entrée et ton fichier de sortie.
En espérant t'avoir répondu, n'hésite pas si tu as d'autres soucis.
28 janv. 2013 à 11:39
Merci de me répondre.J'ai bien résolu le problème de l'exécution(en modifiant le code il reçoit directement le nom de dossier d'entrée).Mais,les images affichées sont tous en gris !!! Je sais pas c'est quoi le problème exactement? est ce qu'il y a une contrainte à propos de taille de l'image?
NB: mes images sont de type jpg
Merci
30 janv. 2013 à 13:16
C'est tout à fait normal, la très grande majorité des algos de traitement d'images se font en niveau de gris.
De toute façon, le résultat de ce programme est un fichier texte, qui n'est en rien changé par les couleurs des images.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.