2013-01-01 47 views
0

使用convexityDefects我嘗試使用convexHullconvexityDefects定義手。但是,當程序命中convexityDefects,總有一個錯誤說「向量下標超出範圍」。 這是我的代碼。如何在OpenCV中2.4

難道我用的功能以錯誤的方式?

#include "stdafx.h" 
#include <opencv2\opencv.hpp> 
#include <math.h> 
#include <iostream> 

using namespace cv; 
using namespace std; 
const int w = 500; 

int levels = 3; 

vector<vector<Point> > contours; 

vector<Vec4i> hierarchy; 

void on_trackbar(int, void*) 
{ 
    Mat cnt_img = Mat::zeros(w, w, CV_8UC3); 
    int _levels = levels - 3; 
    drawContours(cnt_img, contours, _levels <= 0 ? 3 : -1, Scalar(128,255,255), 
      3, CV_AA, hierarchy, std::abs(_levels)); 

    imshow("contours", cnt_img); 
} 

int main(int argc, char**) 
{ 
    Mat img = imread("out.jpg",0); 
    threshold(img,img,200,255,cv::THRESH_BINARY); 


    namedWindow("image", 1); 
    imshow("image", img); 
    //Extract the contours so that 
    vector<vector<Point> > contours0; 
    findContours(img, contours0, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); 

    contours.resize(contours0.size()); 
    for(size_t k = 0; k < contours0.size(); k++){ 
     std::cout<<"contours0.size"<<contours0[k].size()<<endl; 
     approxPolyDP(Mat(contours0[k]), contours[k], 0, true); 
    } 

    std::vector<Vec4i> defects; 
    vector<cv::vector<int> >hull(contours.size()); 

    for (int i = 0; i < contours.size(); i++) 
    { 
     std::cout<<"contours.size"<<contours[i].size()<<endl; 
     convexHull(contours[i], hull[i], false); 
     if (contours[i].size() >150) 
     { 
      convexityDefects(contours[i], hull[i], defects[i]); 
      std::cout<<"defects"<<defects[i].depth<<endl; 
     } 
    } 


    namedWindow("contours", 1); 
    createTrackbar("levels+3", "contours", &levels, 7, on_trackbar); 

    on_trackbar(0,0); 
    waitKey(); 

    return 0; 
} 

預先感謝您!

回答

0

它看起來像問題是convexityDefects()預計爲contourDefects參數數組:

void convexityDefects(InputArray contour, InputArray convexhull, OutputArray convexityDefects); 

兩個contourshullvector<vector<>>類型,這是正確的,但defects也需要一個vector<vector<>>。後來

... 

vector<std::vector<Vec4i>> defects(contours.size()); 

... 

在你的代碼,你將不得不遍歷defects[i]矢量打印depth爲好,如果:這樣,當您通過contours陣列循環,defects[i]將包含一個數組傳遞給convexityDefects()那就是你想要做的。

+0

感謝您的幫助,但不幸的是,我不認爲這是它不起作用的原因。 –

+0

@JaneWang我對這個代碼進行了測試,它在標準的[Lena](https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRuJLw2vd5lTs4uiiG0wnX1AY9x_dLqDM1XE9Evkun0X6e0fOce)上對我無影響,但它永遠不會崩潰打到調用'convexityDefects()'。你可以發佈你正在使用的'out.jpg'圖片嗎?你的代碼中有很多硬編碼的數字(比如'_levels <= 0?3:-1',所以如果你可以在崩潰的地方發佈行號,那也會有幫助。 – WildCrustacean

+0

@JaneWang Aha,I我認爲我現在已經複製了你的問題,看到我編輯的答案。 – WildCrustacean

0

我要發佈完整的工作的源代碼後面的答案,因爲我花了太多時間試圖找出如何使用這個convexityDefects()API。還要注意的是OpenCV的3.0版本,其中包含了返回的錯誤索引()在convexityDefects的錯誤(這是不是在OpenCV的2.X的問題)。因此,更新到最新的GitHub如果你正在運行與3.0版本的問題。

#include <iostream> 
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/opencv.hpp" 

// Test case for C++ impl of convexityDefects() that returns indexes into the 
// contours vector. 

using namespace cv; 
using namespace std; 

int main(int argc, char **argv) 
{ 
    if (argc != 1) { 
    fprintf(stderr, "usage : convexity_defects\n"); 
    exit(1); 
    } 

    const bool debugDumpImages = true; 

    // Result from findContours(binMat, contours, CV_RETR_LIST, CHAIN_APPROX_NONE); 

    // 4 point star pattern at 100x100 

    Point2i contour[140]; 
    contour[0] = Point2i(49,3); 
    contour[1] = Point2i(49,7); 
    contour[2] = Point2i(48,8); 
    contour[3] = Point2i(48,12); 
    contour[4] = Point2i(47,13); 
    contour[5] = Point2i(47,16); 
    contour[6] = Point2i(46,17); 
    contour[7] = Point2i(46,21); 
    contour[8] = Point2i(45,22); 
    contour[9] = Point2i(45,25); 
    contour[10] = Point2i(44,26); 
    contour[11] = Point2i(44,30); 
    contour[12] = Point2i(43,31); 
    contour[13] = Point2i(43,35); 
    contour[14] = Point2i(42,36); 
    contour[15] = Point2i(42,39); 
    contour[16] = Point2i(41,40); 
    contour[17] = Point2i(41,41); 
    contour[18] = Point2i(40,42); 
    contour[19] = Point2i(36,42); 
    contour[20] = Point2i(35,43); 
    contour[21] = Point2i(32,43); 
    contour[22] = Point2i(31,44); 
    contour[23] = Point2i(27,44); 
    contour[24] = Point2i(26,45); 
    contour[25] = Point2i(22,45); 
    contour[26] = Point2i(21,46); 
    contour[27] = Point2i(18,46); 
    contour[28] = Point2i(17,47); 
    contour[29] = Point2i(13,47); 
    contour[30] = Point2i(12,48); 
    contour[31] = Point2i(8,48); 
    contour[32] = Point2i(7,49); 
    contour[33] = Point2i(3,49); 
    contour[34] = Point2i(2,50); 
    contour[35] = Point2i(1,50); 
    contour[36] = Point2i(5,50); 
    contour[37] = Point2i(6,51); 
    contour[38] = Point2i(10,51); 
    contour[39] = Point2i(11,52); 
    contour[40] = Point2i(14,52); 
    contour[41] = Point2i(15,53); 
    contour[42] = Point2i(19,53); 
    contour[43] = Point2i(20,54); 
    contour[44] = Point2i(24,54); 
    contour[45] = Point2i(25,55); 
    contour[46] = Point2i(29,55); 
    contour[47] = Point2i(30,56); 
    contour[48] = Point2i(33,56); 
    contour[49] = Point2i(34,57); 
    contour[50] = Point2i(38,57); 
    contour[51] = Point2i(39,58); 
    contour[52] = Point2i(40,58); 
    contour[53] = Point2i(42,60); 
    contour[54] = Point2i(42,63); 
    contour[55] = Point2i(43,64); 
    contour[56] = Point2i(43,68); 
    contour[57] = Point2i(44,69); 
    contour[58] = Point2i(44,73); 
    contour[59] = Point2i(45,74); 
    contour[60] = Point2i(45,77); 
    contour[61] = Point2i(46,78); 
    contour[62] = Point2i(46,82); 
    contour[63] = Point2i(47,83); 
    contour[64] = Point2i(47,87); 
    contour[65] = Point2i(48,88); 
    contour[66] = Point2i(48,91); 
    contour[67] = Point2i(49,92); 
    contour[68] = Point2i(49,96); 
    contour[69] = Point2i(50,97); 
    contour[70] = Point2i(50,93); 
    contour[71] = Point2i(51,92); 
    contour[72] = Point2i(51,89); 
    contour[73] = Point2i(52,88); 
    contour[74] = Point2i(52,84); 
    contour[75] = Point2i(53,83); 
    contour[76] = Point2i(53,80); 
    contour[77] = Point2i(54,79); 
    contour[78] = Point2i(54,75); 
    contour[79] = Point2i(55,74); 
    contour[80] = Point2i(55,70); 
    contour[81] = Point2i(56,69); 
    contour[82] = Point2i(56,66); 
    contour[83] = Point2i(57,65); 
    contour[84] = Point2i(57,61); 
    contour[85] = Point2i(58,60); 
    contour[86] = Point2i(58,59); 
    contour[87] = Point2i(59,58); 
    contour[88] = Point2i(60,58); 
    contour[89] = Point2i(61,57); 
    contour[90] = Point2i(65,57); 
    contour[91] = Point2i(66,56); 
    contour[92] = Point2i(70,56); 
    contour[93] = Point2i(71,55); 
    contour[94] = Point2i(75,55); 
    contour[95] = Point2i(76,54); 
    contour[96] = Point2i(79,54); 
    contour[97] = Point2i(80,53); 
    contour[98] = Point2i(84,53); 
    contour[99] = Point2i(85,52); 
    contour[100] = Point2i(89,52); 
    contour[101] = Point2i(90,51); 
    contour[102] = Point2i(93,51); 
    contour[103] = Point2i(94,50); 
    contour[104] = Point2i(98,50); 
    contour[105] = Point2i(97,50); 
    contour[106] = Point2i(96,49); 
    contour[107] = Point2i(92,49); 
    contour[108] = Point2i(91,48); 
    contour[109] = Point2i(87,48); 
    contour[110] = Point2i(86,47); 
    contour[111] = Point2i(82,47); 
    contour[112] = Point2i(81,46); 
    contour[113] = Point2i(78,46); 
    contour[114] = Point2i(77,45); 
    contour[115] = Point2i(73,45); 
    contour[116] = Point2i(72,44); 
    contour[117] = Point2i(68,44); 
    contour[118] = Point2i(67,43); 
    contour[119] = Point2i(64,43); 
    contour[120] = Point2i(63,42); 
    contour[121] = Point2i(59,42); 
    contour[122] = Point2i(58,41); 
    contour[123] = Point2i(58,40); 
    contour[124] = Point2i(57,39); 
    contour[125] = Point2i(57,35); 
    contour[126] = Point2i(56,34); 
    contour[127] = Point2i(56,31); 
    contour[128] = Point2i(55,30); 
    contour[129] = Point2i(55,26); 
    contour[130] = Point2i(54,25); 
    contour[131] = Point2i(54,21); 
    contour[132] = Point2i(53,20); 
    contour[133] = Point2i(53,17); 
    contour[134] = Point2i(52,16); 
    contour[135] = Point2i(52,12); 
    contour[136] = Point2i(51,11); 
    contour[137] = Point2i(51,8); 
    contour[138] = Point2i(50,7); 
    contour[139] = Point2i(50,3); 

    vector<Point2i> contourVec; 

    for (int i = 0; i < sizeof(contour)/sizeof(Point2i); i++) { 
    Point2i p = contour[i]; 
    contourVec.push_back(p); 
    } 

    vector<vector<Point2i> > contoursVec; 
    contoursVec.push_back(contourVec); 

    if (debugDumpImages) { 
    Mat binMat(100, 100, CV_8UC1, Scalar(0)); 

    drawContours(binMat, contoursVec, 0, Scalar(0xFF)); 

    string fname = "contour_rendered.png"; 
    imwrite(fname, binMat); 
    cout << "wrote " << fname << endl; 
    } 

    assert(contourVec.size() > 3); 

    // hull around contour points 

    Mat contourMat(contourVec); 

    vector<int> hullVec; 

    convexHull(contourMat, hullVec, false); 

    int hullCount = (int)hullVec.size(); 

    if (1) { 
    cout << "convexHull returned " << hullCount << " hull indexes" << endl; 
    } 

    if (debugDumpImages) { 
    // Convert hull indexes into points so that result can be rendered with drawContours() 

    vector<Point2i> hullContourVec; 

    for (int i = 0; i < hullCount; i++) { 
     int offset = hullVec[i]; 
     Point pt = contourVec[offset]; 
     hullContourVec.push_back(pt); 
    } 

    vector<vector<Point2i> > hullContoursVec; 
    hullContoursVec.push_back(hullContourVec); 

    Mat binMat(100, 100, CV_8UC1, Scalar(0)); 

    drawContours(binMat, hullContoursVec, 0, Scalar(0xFF)); 

    string fname = "hull_contour_rendered.png"; 
    imwrite(fname, binMat); 
    cout << "wrote " << fname << endl; 
    } 

    // calculate convexityDefects() 

    vector<Vec4i> defectVec; 

    convexityDefects(contourVec, hullVec, defectVec); 

    Mat defectBinMat(100, 100, CV_8UC1, Scalar(0)); 
    Mat colorMat(100, 100, CV_8UC3, Scalar(0,0,0)); 

    drawContours(colorMat, contoursVec, 0, Scalar(0,0xFF,0), CV_FILLED, 8); // Draw contour as green filled region 

    for (int cDefIt = 0; cDefIt < defectVec.size(); cDefIt++) { 
    int startIdx = defectVec[cDefIt].val[0]; 
    int endIdx = defectVec[cDefIt].val[1]; 
    int defectPtIdx = defectVec[cDefIt].val[2]; 
    double depth = (double)defectVec[cDefIt].val[3]/256.0f; // see documentation link below why this 

    Point2i startP = contour[startIdx]; 
    Point2i endP = contour[endIdx]; 
    Point2i defectP = contour[defectPtIdx]; 

    printf("start %8d = (%4d,%4d)\n", startIdx, startP.x, startP.y); 
    printf("end %8d = (%4d,%4d)\n", endIdx, endP.x, endP.y); 
    printf("defect %8d = (%4d,%4d)\n", defectPtIdx, defectP.x, defectP.y); 
    printf("depth %0.3f\n", depth); 

    if (debugDumpImages) { 
     line(defectBinMat, startP, defectP, Scalar(255), 1, 0); 
     line(defectBinMat, endP, defectP, Scalar(128), 1, 0); 
    } 

    line(colorMat, startP, endP, Scalar(0xFF,0,0), 1, 0); 
    circle(colorMat, defectP, 4, Scalar(0,0,0xFF), 2); 
    } 

    if (debugDumpImages) { 
    string fname = "hull_contour_defects_rendered.png"; 
    imwrite(fname, defectBinMat); 
    cout << "wrote " << fname << endl; 
    } 

    if (debugDumpImages) { 
    string fname = "contour_defects_rendered.png"; 
    imwrite(fname, colorMat); 
    cout << "wrote " << fname << endl; 
    } 

    imshow("defects", colorMat); 
    waitKey(0); 
}