web-dev-qa-db-fra.com

utiliser OpenCV et SVM avec des images

J'ai des difficultés à lire une image, à extraire des fonctionnalités pour la formation et à tester de nouvelles images au format OpenCV à l'aide de SVM. quelqu'un peut-il m'indiquer un lien génial? J'ai consulté = Introduction à OpenCV sur les machines à vecteurs de support . Mais cela ne facilite pas la lecture des images, et je ne sais pas comment l’intégrer.


Mes objectifs sont de classer les pixels dans une image. Ces pixels appartiendraient à des courbes. Je comprends comprendre la matrice d’entraînement (par exemple, image A 1,1 1,2 1,3 1,4 1,5 2,1 2,2 2,3 2,4 2,5 3,1 3,2 3, 3 3,4 3,5

Je formerais ma matrice d’entraînement comme un [3] [2] = {{1,1} {1,2} {1,3} {1,4} {1,5} {2,1} .. {} }

Cependant, je suis un peu confus au sujet des étiquettes. De ma compréhension, je dois spécifier quelle ligne (image) dans la matrice de formation correspond, ce qui correspond à une courbe ou à une non-courbe. Mais comment identifier une ligne de matrice d'entraînement (image) s'il existe des pixels appartenant à la courbe et d'autres n'appartenant pas à une courbe. Par exemple, ma matrice de formation est [3] [2] = {{1,1} {1,2} {1,3} {1,4} {1,5} {2,1} .. {}} , les pixels {1,1} et {1,4} appartiennent à la courbe, mais pas le reste.

63
Carnez Davis

J'ai eu à faire face à cela récemment, et voici ce que j'ai fini par faire pour que SVM fonctionne pour les images.

Pour former votre SVM sur un ensemble d’images, vous devez d’abord construire la matrice d’entraînement pour le SVM. Cette matrice est spécifiée comme suit: chaque ligne de la matrice correspond à une image et chaque élément de cette ligne correspond à une caractéristique de la classe - dans ce cas, la couleur du pixel à un certain point. Comme vos images sont en 2D, vous devrez les convertir en matrice 1D. La longueur de chaque ligne correspondra à la zone des images (notez que les images doivent avoir la même taille).

Supposons que vous vouliez entraîner le SVM sur 5 images différentes et que chaque image faisait 4x3 pixels. Vous devez d’abord initialiser la matrice de formation. Le nombre de lignes dans la matrice serait de 5 et le nombre de colonnes serait la surface de l'image, 4 * 3 = 12.

int num_files = 5;
int img_area = 4*3;
Mat training_mat(num_files,img_area,CV_32FC1);

Idéalement, num_files Et img_area Ne seraient pas codés en dur, mais seraient obtenus en parcourant un répertoire, en comptant le nombre d'images et en prenant la surface réelle d'une image.

L'étape suivante consiste à "remplir" les lignes de training_mat Avec les données de chaque image. Vous trouverez ci-dessous un exemple d'utilisation de ce mappage pour une ligne.

Convert 2D image matrix to 1D matrix

J'ai numéroté chaque élément de la matrice d'image avec son emplacement approprié dans la ligne correspondante de la matrice d'apprentissage. Par exemple, s'il s'agissait de la troisième image, il s'agirait de la troisième ligne de la matrice de formation.

Vous devez parcourir chaque image et définir la valeur dans la matrice de sortie en conséquence. Voici un exemple pour plusieurs images:

Training matrix with multiple images

Pour ce qui est de la procédure à suivre dans le code, vous pouvez utiliser reshape() , mais cela me pose problème en raison du fait que les matrices ne sont pas continues. Dans mon expérience, j'ai fait quelque chose comme ça:

Mat img_mat = imread(imgname,0); // I used 0 for greyscale
int ii = 0; // Current column in training_mat
for (int i = 0; i<img_mat.rows; i++) {
    for (int j = 0; j < img_mat.cols; j++) {
        training_mat.at<float>(file_num,ii++) = img_mat.at<uchar>(i,j);
    }
}

Faites cela pour chaque image d'entraînement (en vous rappelant d'incrémenter file_num). Ensuite, votre matrice d’entraînement doit être configurée correctement pour pouvoir passer aux fonctions SVM. Le reste des étapes devrait être très similaire aux exemples en ligne.

Notez que vous devez également définir des étiquettes pour chaque image de formation. Ainsi, par exemple, si vous classifiez les yeux et les non-yeux en fonction des images, vous devez spécifier quelle ligne de la matrice de formation correspond à un œil et à un non-œil. Ceci est spécifié en tant que matrice 1D, chaque élément de la matrice 1D correspondant à chaque ligne de la matrice 2D. Choisissez des valeurs pour chaque classe (par exemple, -1 pour les non-yeux et 1 pour les yeux) et définissez-les dans la matrice des étiquettes.

Mat labels(num_files,1,CV_32FC1);

Donc, si le 3ème élément de cette matrice labels était -1, cela signifie que la 3ème ligne de la matrice d'apprentissage est dans la classe "non-yeux". Vous pouvez définir ces valeurs dans la boucle où vous évaluez chaque image. Vous pouvez, par exemple, trier les données d'apprentissage dans des répertoires distincts pour chaque classe, parcourir les images de chaque répertoire et définir les étiquettes en fonction du répertoire.

La prochaine chose à faire est de configurer vos paramètres SVM. Ces valeurs peuvent varier en fonction de votre projet, mais vous devez en principe déclarer un objet CvSVMParams et définir les valeurs suivantes:

CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::POLY;
params.gamma = 3;
// ...etc

Il existe plusieurs exemples en ligne sur la manière de définir ces paramètres, comme dans le lien que vous avez posté dans la question.

Ensuite, vous créez un objet CvSVM et vous le formez en fonction de vos données!

CvSVM svm;
svm.train(training_mat, labels, Mat(), Mat(), params);

Selon la quantité de données dont vous disposez, cela peut prendre beaucoup de temps. Une fois la formation terminée, vous pouvez toutefois sauvegarder le SVM formé afin de ne pas avoir à le recycler à chaque fois.

svm.save("svm_filename"); // saving
svm.load("svm_filename"); // loading

Pour tester vos images à l'aide du SVM formé, il vous suffit de lire une image, de la convertir en matrice 1D et de la transmettre à svm.predict():

svm.predict(img_mat_1d);

Il renverra une valeur en fonction de ce que vous définissez comme étiquettes (par exemple, -1 ou 1, en fonction de l'exemple ci-dessus, oeil ou non). Sinon, si vous souhaitez tester plusieurs images à la fois, vous pouvez créer une matrice au même format que la matrice d'apprentissage définie précédemment et passer cela en tant qu'argument. La valeur de retour sera différente, cependant.

Bonne chance!

216
Walfie