regroupement de segments d’image dans opencv

Je travaille sur la détection de mouvement avec une caméra non statique utilisant opencv. J’utilise une approche assez basique de soustraction de fond et de seuillage pour avoir une idée globale de tout ce qui bouge dans un exemple de vidéo. Après le seuillage, j’inscris tous les “patchs” séparables de pixels blancs, les stocke en tant que composants indépendants et les colore de manière aléatoire en rouge, vert ou bleu. L’image ci-dessous montre cela pour une vidéo de football où tous ces composants sont visibles. Segments mobiles

Je crée des rectangles sur ces composants détectés et j’obtiens cette image:

Image originale

Donc, je peux voir le défi ici. Je souhaite regrouper tous les composants “similaires” et proches en une seule entité, de sorte que les rectangles de l’image de sortie représentent un joueur se déplaçant dans son ensemble (et non ses membres indépendants). J’ai essayé de faire du clustering K-means mais, dans l’idéal, je ne saurais pas dire le nombre d’entités en mouvement, je ne pouvais progresser.

S’il vous plaît guidez-moi sur comment je peux faire cela. Merci

ce problème peut être presque parfaitement résolu par l’algorithme de clustering dbscan. Ci-dessous, je fournis l’image d’implémentation et de résultat. Gray blob signifie aberration ou bruit selon dbscan. J’ai simplement utilisé des boîtes en tant que données d’entrée. Initialement, les centres de la boîte étaient utilisés pour la fonction de distance. Cependant, pour les cases, il ne suffit pas de caractériser correctement la distance. Ainsi, la fonction de distance actuelle utilise la distance minimale des 8 coins de deux cases.

#include "opencv2/opencv.hpp" using namespace cv; #include  #include  template  inline std::ssortingng to_ssortingng (const T& t) { std::ssortingngstream ss; ss << t; return ss.str(); } class DbScan { public: std::map labels; vector& data; int C; double eps; int mnpts; double* dp; //memoization table in case of complex dist functions #define DP(i,j) dp[(data.size()*i)+j] DbScan(vector& _data,double _eps,int _mnpts):data(_data) { C=-1; for(int i=0;i neighbours = regionQuery(i); if(neighbours.size() neighbours) { labels[p]=C; for(int i=0;i neighbours_p = regionQuery(neighbours[i]); if (neighbours_p.size() >= mnpts) { expandCluster(neighbours[i],neighbours_p); } } } } bool isVisited(int i) { return labels[i]!=-99; } vector regionQuery(int p) { vector res; for(int i=0;i > getGroups() { vector > ret; for(int i=0;i<=C;i++) { ret.push_back(vector()); for(int j=0;j= 1.0f) fH = 0.0f; fH *= 6.0; // sector 0 to 5 fI = floor( fH ); // integer part of h (0,1,2,3,4,5 or 6) iI = (int) fH; // " " " " fF = fH - fI; // factorial part of h (0 to 1) p = fV * ( 1.0f - fS ); q = fV * ( 1.0f - fS * fF ); t = fV * ( 1.0f - fS * ( 1.0f - fF ) ); switch( iI ) { case 0: fR = fV; fG = t; fB = p; break; case 1: fR = q; fG = fV; fB = p; break; case 2: fR = p; fG = fV; fB = t; break; case 3: fR = p; fG = q; fB = fV; break; case 4: fR = t; fG = p; fB = fV; break; default: // case 5 (or 6): fR = fV; fG = p; fB = q; break; } } // Convert from doubles to 8-bit integers int bR = (int)(fR * double_TO_BYTE); int bG = (int)(fG * double_TO_BYTE); int bB = (int)(fB * double_TO_BYTE); // Clip the values to make sure it fits within the 8bits. if (bR > 255) bR = 255; if (bR < 0) bR = 0; if (bG >255) bG = 255; if (bG < 0) bG = 0; if (bB > 255) bB = 255; if (bB < 0) bB = 0; // Set the RGB cvScalar with GBR, you can use this values as you want too.. return cv::Scalar(bB,bG,bR); // R component } int main(int argc,char** argv ) { Mat im = imread("c:/data/football.png",0); std::vector > contours; std::vector hierarchy; findContours(im.clone(), contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); vector boxes; for(size_t i = 0; i < contours.size(); i++) { Rect r = boundingRect(contours[i]); boxes.push_back(r); } DbScan dbscan(boxes,20,2); dbscan.run(); //done, perform display Mat grouped = Mat::zeros(im.size(),CV_8UC3); vector colors; RNG rng(3); for(int i=0;i<=dbscan.C;i++) { colors.push_back(HSVtoRGBcvScalar(rng(255),255,255)); } for(int i=0;i 

résultat

Je suis d’accord avec Sebastian Schmitz: vous ne devriez probablement pas chercher le clustering.

Ne vous attendez pas à ce qu’une méthode mal informée telle que k-means fasse de la magie pour vous. En particulier, une heuristique aussi rudimentaire que k-means, et qui vit dans un monde mathématique idéalisé, et non dans des données confuses, réelles.

Vous avez une bonne compréhension de ce que vous voulez. Essayez de mettre cette intuition en code. Dans votre cas, vous semblez rechercher des composants connectés.

Pensez à sous- échantillonner votre image à une résolution inférieure, puis à réexécuter le même processus! Ou exécutez-le immédiatement sur la résolution inférieure (pour réduire les artefacts de compression et améliorer les performances). Ou append des filtres , tels que le flou.

J’attendrais des résultats optimaux et rapides en examinant les composants connectés dans l’image sous-échantillonnée / filtrée.

Je ne suis pas tout à fait sûr que vous recherchiez vraiment le clustering (au sens du Data Mining).

Le clustering est utilisé pour regrouper des objects similaires selon une fonction de distance. Dans votre cas, la fonction distance utiliserait uniquement les qualités spatiales. De plus, dans k-signifie le clustering, vous devez spécifier ak, que vous ne connaissez probablement pas auparavant.

Il me semble que vous souhaitez simplement fusionner tous les rectangles dont les frontières sont plus rapprochées qu’un seuil prédéterminé. Dans un premier temps, essayez donc de fusionner tous les rectangles qui se touchent ou qui sont plus rapprochés qu’une demi-hauteur de joueur.

Vous voudrez probablement inclure un contrôle de taille pour minimiser le risque de fusion de deux joueurs en un seul.

Éditer: si vous voulez vraiment utiliser un algorithme de clustering, utilisez-en un qui estime le nombre de clusters pour vous.

Je suppose que vous pouvez améliorer votre tentative initiale en utilisant des transformations morphologiques. Jetez un coup d’oeil à http://docs.opencv.org/master/d9/d61/tutorial_py_morphological_ops.html#gsc.tab=0 . Vous pouvez probablement traiter ensuite un ensemble fermé pour chaque entité, en particulier avec des lecteurs distincts tels que vous les avez dans votre image d’origine.