// Component Labelling(opencv내 함수 connectedComponentsWithStats를 이용하여) vector<obj_info> connectedComponentsLabelling(Mat frame) { vector<obj_info> result; result.clear(); Rect objectRegion(0, 0, 30, 30); // 레이블 저장할 사각형 obj_info *obj_array = (obj_info*)calloc(999, sizeof(obj_info)); // componentArray에 공간 할당 Mat img_labels, stats, centroids; int numOfLables = connectedComponentsWithStats(frame, img_labels, stats, centroids, 8, CV_32S); // label 갯수 반환 int index = 0; for (int i = 1; i < numOfLables; i++) { // height, width를 미리 지정 int height = stats.at<int>(i, CC_STAT_HEIGHT); int width = stats.at<int>(i, CC_STAT_WIDTH); // 영역박스 그리기, 레이블 크기를 필터링 하여(사람크기에 해당될 만큼) if (labelSizeFiltering(frame, width, height)) { // 유효한 레이블 인덱스를 저장 obj_array[index].label = index; // Component에 데이터 저장 obj_array[index] = dataAllocateAtComponent(stats, obj_array[index], i); // Rect타입 변수에 레이블된 오브젝트 저장 objectRegion = savingRectangle(frame, obj_array[index]); result.push_back(obj_array[index]); index++; } } return result; }
void *opencv(void * args) { /* DEBUT TRAITEMENT OPENCV */ Mat imgHSV; cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Passe de BGR a HSV inRange(imgHSV, Scalar(LH, LS, LV), Scalar(HH, HS, HV), imgDetection); //Met en noir les parties non comprit dans notre intervalle pour la balle //Retire les petits parasite en fond erode(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); dilate(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); dilate(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); erode(imgDetection, imgDetection, getStructuringElement(MORPH_ELLIPSE, Size(5, 5))); int i, nlabels; Rect box; int maxArea=0; Mat labels; Mat centroids; Mat stats; //Calcul des différentes composantes connexes de l'image nlabels=connectedComponentsWithStats(imgDetection, labels, stats, centroids, 4, CV_32S); //On recherche la composante connexe la plus grande for(i=1; i<(int)nlabels;i++) { int *row = (int *) &stats.at<int>(i,0); //printf("i : %d, mon area %d vs %d max \n", i, row[CC_STAT_AREA], maxArea); if(row[CC_STAT_AREA]>maxArea) { box = Rect(row[CC_STAT_LEFT], row[CC_STAT_TOP], row[CC_STAT_WIDTH], row[CC_STAT_HEIGHT]); maxArea=row[CC_STAT_AREA]; } } Moments position; //cout << maxArea << endl << (int)(Ball.lastdZone*0.3) << endl; //Si la composante connexe n'est pas assez grande ce n'est pas l'objet if(maxArea>200)//(int)(0.3*Ball.lastdZone)) { Ball.setFoundCV(true); rectangle(imgOriginal, box, Scalar(0,255,0), 4, 8, 0); //Calcule l emplacement de l objet position = moments(imgDetection(box)); double y = position.m01; //y double x = position.m10; //x double dZone = position.m00; //z //cout << "dZone " << dZone << endl << "LdZone " << Ball.lastdZone << endl; posX = x / dZone; posY = y / dZone; posX+=box.x; posY+=box.y; int posZ=0; if(dZone>Ball.lastdZone+Ball.lastdZone*0.2) { posZ=-1; //Trop près de l'objet, il faut reculer. } else if(dZone > Ball.lastdZone-Ball.lastdZone*0.2 && dZone < Ball.lastdZone+Ball.lastdZone*0.2) { posZ=0; //On est à distance correcte de l'objet } else { posZ=1; //Trop loin de l'objet, il faut avancer. } Ball.setCurrentCV((float)posX/fSize.width*100,(float)posY/fSize.height*100, (float)posZ); } else { if(activate) {//On passe ici quand la zone détectée est trop petite ou que l'on en détecte pas. //AtCmd::sendMovement(0, 0, 0, 0, 0); // CHANGE } Ball.setFoundCV(false); } /* FIN TRAITEMENT OPENCV */ return NULL; }