Ошибка доступа к вектору OpenCV - PullRequest
1 голос
/ 19 января 2011

Я использую этот код из проекта FingertipTuio3D

std::vector<cv::Point2i> detectFingertips(cv::Mat1f z, float zMin = 0.0f, float zMax = 0.75f, cv::Mat1f& debugFrame = cv::Mat1f()) {
    using namespace cv;
    using namespace std;    
    bool debug = !debugFrame.empty();

    vector<Point2i> fingerTips;

    Mat handMask = z < zMax & z > zMin;

    std::vector<std::vector<cv::Point>> contours;
    findContours(handMask.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); // we are cloning here since method will destruct the image

    if (contours.size()) {
        for (int i=0; i<contours.size(); i++) {
            vector<Point> contour = contours[i];
            Mat contourMat = Mat(contour);
            double area = cv::contourArea(contourMat);

            if (area > 3000)  { // possible hand
                Scalar center = mean(contourMat);
                Point centerPoint = Point(center.val[0], center.val[1]);

                vector<Point> approxCurve;
                cv::approxPolyDP(contourMat, approxCurve, 20, true);

                vector<int> hull;
                cv::convexHull(Mat(approxCurve), hull);

                // find upper and lower bounds of the hand and define cutoff threshold (don't consider lower vertices as fingers)
                int upper = 640, lower = 0;
                for (int j=0; j<hull.size(); j++) {
                    int idx = hull[j]; // corner index
                    if (approxCurve[idx].y < upper) upper = approxCurve[idx].y;
                    if (approxCurve[idx].y > lower) lower = approxCurve[idx].y;
                }
                float cutoff = lower - (lower - upper) * 0.1f;

                // find interior angles of hull corners
                for (int j=0; j<hull.size(); j++) {
                    int idx = hull[j]; // corner index
                    int pdx = idx == 0 ? approxCurve.size() - 1 : idx - 1; //  predecessor of idx
                    int sdx = idx == approxCurve.size() - 1 ? 0 : idx + 1; // successor of idx

                    Point v1 = approxCurve[sdx] - approxCurve[idx];
                    Point v2 = approxCurve[pdx] - approxCurve[idx];

                    float angle = acos( (v1.x*v2.x + v1.y*v2.y) / (norm(v1) * norm(v2)) );

                    // low interior angle + within upper 90% of region -> we got a finger
                    if (angle < 1 && approxCurve[idx].y < cutoff) {
                        int u = approxCurve[idx].x;
                        int v = approxCurve[idx].y;

                        fingerTips.push_back(Point2i(u,v));

                        if (debug) {
                            cv::circle(debugFrame, approxCurve[idx], 10, Scalar(1), -1);
                        }
                    }
                }

                if (debug) {
                    // draw cutoff threshold
                    cv::line(debugFrame, Point(center.val[0]-100, cutoff), Point(center.val[0]+100, cutoff), Scalar(1.0f));

                    // draw approxCurve
                    for (int j=0; j<approxCurve.size(); j++) {
                        cv::circle(debugFrame, approxCurve[j], 10, Scalar(1.0f));
                        if (j != 0) {
                            cv::line(debugFrame, approxCurve[j], approxCurve[j-1], Scalar(1.0f));
                        } else {
                            cv::line(debugFrame, approxCurve[0], approxCurve[approxCurve.size()-1], Scalar(1.0f));
                        }
                    }

                    // draw approxCurve hull
                    for (int j=0; j<hull.size(); j++) {
                        cv::circle(debugFrame, approxCurve[hull[j]], 10, Scalar(1.0f), 3);
                        if(j == 0) {
                            cv::line(debugFrame, approxCurve[hull[j]], approxCurve[hull[hull.size()-1]], Scalar(1.0f));
                        } else {
                            cv::line(debugFrame, approxCurve[hull[j]], approxCurve[hull[j-1]], Scalar(1.0f));
                        }
                    }
                }
            }
        }
    }

    return fingerTips;
}

Когда код достигает этой точки vector<Point> contour = contours[i];, происходит сбой с AccessViolation:

Необработанное исключение в 0x00b85039 вFingertipTuio3d.exe: 0xC0000005: Место чтения нарушения прав доступа 0x00000008.

Это расположение находится в функции size_type size() const в std :: vector.

Любая идея, которая вызывает проблему,и как это можно исправить?

Ответы [ 4 ]

0 голосов
/ 24 ноября 2014

Это ошибка сборки.посмотрите на это:

--#ifdef _DEBUG 
--#pragma comment(lib,"opencv_core249d.lib")
--#else
--#pragma comment(lib,"opencv_core249.lib")    <<---- your checked!!
--#endif  

: -)

0 голосов
/ 20 января 2011

Можете ли вы получить доступ к элементам через итератор? IOW, если вы добавите следующий код сразу после вызова к loadContours, какой вывод вы получите?

int i = 0;
for (std::vector<std::vector<cv::Point> >::iterator it = contours.begin();
     it != contours.end();
     ++it)
{
  std::cout << "contours[" << i << "].size() == " << it->size() << std::endl;
}
0 голосов
/ 24 августа 2012

потому что контур - это вектор вектора (std :: vector> contours;)

и контур - это вектор точек (векторный контур)

, поэтому он не может сделать векторный контур = контур [i];

если вы хотите скопировать контуры [i], вам нужно взять другой вектор вектора.

0 голосов
/ 19 января 2011

Ваш findContours фактически помещает что-нибудь в каждый контур?

Вы проверяете, что массив существует, но нет, что отдельные элементы действительны

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...