2011-11-17 4 views
3

Nous écrivons un programme qui prend l'entrée d'une webcam, soustrait toutes les couleurs à l'exception des valeurs vertes, trouve les BLOB séparés et les numéralise. Finalement, cela sera utilisé comme une entrée pour un jeu vidéo, mais c'est irréligieux en ce moment.Comment FindContours parcourt-il l'image? OpenCV 2.3

Le code en question n'est pas le code qui fait réellement tout cela, mais plutôt un segment réécrit du code pour tester le fonctionnement de FindContours. Habituellement, avec le traitement d'image, on nous a dit que l'image est lue de haut en bas à gauche, mais après quelques tests, il semble qu'elle fasse exactement le contraire, en commençant dans le coin inférieur droit et en haut à gauche!

Donc la question ici est: Dans quel ordre FindContours trouve-t-il ses Contours? Ai-je raison dans mon hypothèse ou est-ce mon propre code qui me perturbe?

Entrée: Blobtest06

"Components" window

Console

#include <opencv2/opencv.hpp> 
#include <iostream> 
#include <opencv2/core/mat.hpp> 
#include <Windows.h> //for sleep function 

using namespace cv; 
using namespace std; 

void IsolateGreen(Mat mIn, Mat& mOut) 
{ 
Mat inImg (mIn.rows, mIn.cols, CV_8UC3, Scalar(1,2,3)); 
inImg.data = mIn.data; 
Mat channelRed (inImg.rows, inImg.cols, CV_8UC1); 
Mat channelGreen (inImg.rows, inImg.cols, CV_8UC1); 
Mat channelBlue (inImg.rows, inImg.cols, CV_8UC1); 
Mat outImg[] = {channelRed, channelGreen, channelBlue}; 

int fromTo[] = { 0,2, 1,1, 2,0}; 
mixChannels(&inImg, 1, outImg, 3, fromTo, 3); 

mOut = (channelGreen) - (channelRed + channelBlue); 

threshold(mOut, mOut, 5, 255, THRESH_BINARY); 

erode(mOut, mOut, Mat(), Point (-1,-1), 1); 
dilate(mOut, mOut, Mat(), Point(-1,-1), 2); 

} 

void FindContours(Mat& mDst, Mat mGreenScale, vector<vector<Point>>& vecContours, vector<Vec4i>& vecHierarchy, Mat img) 
{ 
//This is empty at all times. We need it to avoid crashes. 
vector<Vec4i> vecHierarchy2; 

// mGreenScale = mGreenScale > 1; //// MIGHT be entirely unneeded 

mDst = img > 1; 
findContours(mGreenScale, vecContours, vecHierarchy, 
     CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); 

/* Colors, in order: 
1st. = Red 
2nd. = Dark red 
3rd. = Purple 
4th. = Blue 
5th. = Baby blue 
6th. = Green 
7th. = Olive green 
8th. = Dark green 
*/ 

int aRed[] = {255, 100, 128, 0, 191, 0, 202, 0}; 
int aGreen[] = {0, 0, 0, 0, 239, 255, 255, 100}; 
int aBlue[] = {0, 0, 128, 255, 255, 0, 112, 0}; 
string sColor[] = {"Red", "Dark red", "Purple", "Blue", "Baby blue", "Green", "Light green", "Dark green"}; 

//its important that we check if there is anything in vecHierarchy (else) {crash} :P 
//function drawContours cannot handle an empty vedHierarchy 
if (vecHierarchy != vecHierarchy2) 
{ 
    // iterate through all the top-level contours, 
    for(int idx = 0; idx >= 0; idx = vecHierarchy[idx][0]) 
    { 
     // draw each connected component with its own FIXED color 
     Scalar color(aBlue[idx], aGreen[idx], aRed[idx]); 
     drawContours(mDst, vecContours, idx, color, /*1*/ CV_FILLED, 8, vecHierarchy); 
     cout << vecContours[idx][0] << " - - " << sColor[idx] << " - - Index: " << idx << endl; 
    } 
} 
cout << "Objects: "; 
cout << vecContours.size(); 
cout << endl; 

} 




int main() 
    { 
    Mat img = imread("Blobtest06.png"); 
    Mat mGreenScale; 

    //These next 5 instances ties to contourfinding     
    cvtColor(img, mGreenScale, CV_8UC3); //sets the right rows and cols 
    vector<vector<Point>> vecContours; //points to each pixel in a contour 
    vector<Vec4i> vecHierarchy; //A hierarchy for the functions 
    Mat mDst = Mat::zeros(mGreenScale.rows, mGreenScale.cols, CV_8UC3); //mDst image 


    IsolateGreen(img, mGreenScale); 
    FindContours(mDst, mGreenScale, vecContours, vecHierarchy, img); 

    namedWindow("Components", 1); 
    imshow("Components", mDst); 
    namedWindow("Source", 1); 
    imshow("Source", mGreenScale); 

    waitKey(); 
    return 0; 
    } 

PS: Désolé pour la syntaxe horrible. Le site est difficile et c'est juste à l'heure du déjeuner.

Répondre

5

Si vous vous intéressez aux détails de la mise en œuvre d'OpenCV, qui est une bibliothèque Open Source, vous pouvez toujours download the source et le lire vous-même.

Avertissement: l'API C++ utilise l'API C pour certaines opérations, notamment FindCountours(). Donc, si vous vérifiez le fichier: modules/imgproc/src/contours.cpp ligne vous verrez l'implémentation C++ de cette fonction:

1472 void cv::findContours(InputOutputArray _image, OutputArrayOfArrays _contours, 
1473     OutputArray _hierarchy, int mode, int method, Point offset) 
1474 { 
1475  Mat image = _image.getMat(); 
1476  MemStorage storage(cvCreateMemStorage()); 
1477  CvMat _cimage = image; 
1478  CvSeq* _ccontours = 0; 
1479  if(_hierarchy.needed()) 
1480   _hierarchy.clear(); 
1481  cvFindContours(&_cimage, storage, &_ccontours, sizeof(CvContour), mode, method, offset); 
1482  if(!_ccontours) 
1483  { 
1484   _contours.clear(); 
1485   return; 
1486  } 

appelant cvFindContours(), ce qui est de l'API C, défini dans ce même fichier en ligne .

Le processus de balayage lui-même est décrit sur cvFindNextContour(), situé à la ligne :

793 CvSeq * 
794 cvFindNextContour(CvContourScanner scanner) 
795 { 

et vous pouvez voir clairement:

824  for(; y < height; y++, img += step) 
825  { 
826   for(; x < width; x++) 
827   { 
+0

Merci pour la réponse - Mais! Je n'arrive pas à saisir la réponse, entièrement. Je peux voir la façon dont les mathématiques fonctionneraient, mais cela ne donne aucune idée de la direction. De quel pixel commence-t-il et où finit-il? Je suis un peu un débutant, sur une sidenote, alors supportez-moi. :) –

Questions connexes