Как FindContours проходит по изображению? OpenCV 2.3 - PullRequest
3 голосов
/ 17 ноября 2011

Мы пишем программу, которая получает данные с веб-камеры, вычитает все цвета, кроме значений зеленого цвета, находит отдельные BLOB-объекты и нумерует их. В конце концов, это будет использоваться в качестве входа для видеоигры, но сейчас это не имеет значения.

Код, о котором идет речь, - это не код, который фактически делает все это, а переписанный сегмент кода, чтобы проверить, как на самом деле работает FindContours. Обычно, при обработке изображений, мы думали, что изображение читается сверху вниз, справа налево, но после некоторого тестирования кажется, что оно делает противоположное, начиная с нижнего правого угла и двигаясь в верхний левый! *

Итак, вопрос здесь: в каком порядке FindContours находит его Contours? Я прав в своем предположении, или это мой собственный код, сбивающий меня с толку?

Ввод: Blobtest06

Окно "Компоненты"

Консоль

#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: извините за ужасный синтаксис. Сайт трудный, и он только на обеде.

1 Ответ

5 голосов
/ 17 ноября 2011

Если вам интересны детали реализации OpenCV, которая, кстати, является библиотекой с открытым исходным кодом, вы всегда можете загрузить исходный код и прочитать его самостоятельно.

Предупреждение : API C ++ использует C API для некоторых вещей, включая FindCountours(). Поэтому, если вы проверите файл: modules/imgproc/src/contours.cpp line 1472 , вы увидите реализацию этой функции на C ++:

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     }

вызов cvFindContours() из C API, определенного в этом же файле в строке 1424 .

Сам процесс сканирования описан в cvFindNextContour(), расположенном в строке 794 :

793 CvSeq *
794 cvFindNextContour( CvContourScanner scanner )
795 {

и вы можете ясно видеть:

824     for( ; y < height; y++, img += step )
825     {
826         for( ; x < width; x++ )
827         {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...