2015-08-22 67 views
1

我想写一个程序,可以创建一个多边形(任意数量的边)围绕某个对象,并找到多边形的质心。为此,我选择使用凸凹和findContours函数。在下面的程序中,您会看到两个窗口。一个窗口包含用于更改过滤器的HSV和形态值的轨道栏,另一个窗口包含已过滤的图像。在过滤图像并获得二值图像后,您必须点击'c'找到轮廓,然后点'h'找到凸凹。过滤图像并执行形态学操作不是问题。主要问题是找到轮廓。Opencv 3.0.0,C++,Visual Studio 2015 - 错误发现轮廓和ConvexHull

#include<iostream> 
#include<opencv2\highgui\highgui.hpp> 
#include<opencv2\imgproc\imgproc.hpp> 
#include<opencv2\core\core.hpp> 
#include<opencv2\video\background_segm.hpp> 
#include<Windows.h> 
using namespace cv; 
using namespace std; 

//functions prototypes 
void on_trackbar(int, void*); 
void createTrackbars(); 
void showimgcontours(Mat &threshedimg, Mat &original); 
void toggle(int key); 
void morphit(Mat &img); 
void blurthresh(Mat &img); 

//function prototypes ends here 

//boolean toggles 

bool domorph = false; 
bool doblurthresh = false; 
bool showchangedframe = false; 
bool showcontours = false; 
bool showhull = false; 

//boolean toggles end 


int H_MIN = 0; 
int H_MAX = 255; 
int S_MIN = 0; 
int S_MAX = 255; 
int V_MIN = 0; 
int V_MAX = 255; 

int kerode = 1; 
int kdilate = 1; 
int kblur = 1; 
int threshval = 0; 


int main(void) 
{ 
    createTrackbars(); 
    on_trackbar(0, 0); 

    Mat frame, hsvframe, rangeframe; 
    int key; 
    VideoCapture cap(0); 
    while ((key = waitKey(30)) != 27) 
    { 
     toggle(key); 
     cap >> frame; 
     flip(frame, frame, 180); 
     cvtColor(frame, hsvframe, COLOR_BGR2HSV); 

     inRange(hsvframe, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX, S_MAX, V_MAX), rangeframe); 

     if (domorph) 
      morphit(rangeframe); 

     if (doblurthresh) 
      blurthresh(rangeframe); 

     if (showcontours) 
      showimgcontours(rangeframe, frame); 

     if (showchangedframe) 
      imshow("Camera", frame); 
     else 
      imshow("Camera", rangeframe); 

    } 

} 


void on_trackbar(int, void*) 
{//This function gets called whenever a 
// trackbar position is changed 
    if (kerode == 0) 
     kerode = 1; 
    if (kdilate == 0) 
     kdilate = 1; 
    if (kblur == 0) 
     kblur = 1; 
} 
void createTrackbars() 
{ 
    String trackbarWindowName = "TrackBars"; 
    namedWindow(trackbarWindowName, WINDOW_NORMAL); 
    createTrackbar("H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar); 
    createTrackbar("H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar); 
    createTrackbar("S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar); 
    createTrackbar("S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar); 
    createTrackbar("V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar); 
    createTrackbar("V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar); 
    createTrackbar("Erode", trackbarWindowName, &kerode, 31, on_trackbar); 
    createTrackbar("Dilate", trackbarWindowName, &kdilate, 31, on_trackbar); 
    createTrackbar("Blur", trackbarWindowName, &kblur, 255, on_trackbar); 
    createTrackbar("Thresh", trackbarWindowName, &threshval, 255, on_trackbar); 

} 

void morphit(Mat &img) 
{ 
    erode(img, img, getStructuringElement(MORPH_RECT, Size(kerode, kerode))); 
    dilate(img, img, getStructuringElement(MORPH_RECT, Size(kdilate, kdilate))); 
} 
void blurthresh(Mat &img) 
{ 
    //medianBlur(img,img,kblur%2+3+kblur); 
    blur(img, img, Size(kblur, kblur), Point(-1, -1), BORDER_DEFAULT); 
    threshold(img, img, threshval, 255, THRESH_BINARY_INV); 
} 
void toggle(int key) 
{ 

    //toggle line start 
    if (key == 'm') 
     domorph = !domorph; 
    if (key == 'b') 
     doblurthresh = !doblurthresh; 
    if (key == 'r') 
     showchangedframe = !showchangedframe; 
    if (key == 'c') 
     showcontours = !showcontours; 
    if (key == 'h') 
     showhull = !showhull; 
    //toggle line end 
} 

void showimgcontours(Mat &threshedimg, Mat &original) 
{ 
    vector<vector<Point> > contours; 
    vector<Vec4i> hierarchy; 
    int largest_area = 0; 
    int largest_contour_index = 0; 

    findContours(threshedimg, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); 

    vector<vector<Point> >hull(contours.size()); 

    //find a hull for each contour 
    for (int i = 0; i < contours.size(); i++) 
    { 
     convexHull(Mat(contours[i]), hull[i], false); 
    } 

    //this will find the largest contour 
    for (int i = 0; i< contours.size(); i++) // iterate through each contour. 
    { 
     double a = contourArea(contours[i], false); // Find the area of each contour 
     if (a>largest_area) 
     { 
      largest_area = a; 
      largest_contour_index = i;    //Store the index of the largest contour 
     } 

    } 
    //search for the largest contour has end 

    if (contours.size() > 0) 
    { 
     drawContours(original, contours, largest_contour_index, CV_RGB(0, 255, 0), 2, 8, hierarchy); 
     //if you want to show every contour, use the following 
     //drawContours(original,-1, CV_RGB(0, 255, 0), 2, 8, hierarchy); 
     if (showhull) 
      drawContours(original, hull, largest_contour_index, CV_RGB(0, 0, 255), 2, 8, hierarchy); 
     //if you want to show every hull(s), use the following 
     //drawContours(original,-1, CV_RGB(0, 255, 0), 2, 8, hierarchy); 
    } 
} 

的问题是,它总是会触发一个断点向量类模板(某处void Tidy())每当我尝试运行findcontours()函数。弹出一个对话框并显示以下消息:

“ConsoleApplication2.exe中的0x00007FF9374CD328(ucrtbase.dll)未处理的异常:将无效参数传递给认为无效参数致命的函数。

http://i60.tinypic.com/1zvdf1t.png

然后对话框重定向我到向量类模板,并显示在下面段第7行设置一个断点。

void _Tidy() 
    { // free all storage 
    if (this->_Myfirst() != pointer()) 
     { // something to free, destroy and deallocate it 
     this->_Orphan_all(); 
     _Destroy(this->_Myfirst(), this->_Mylast()); 
     this->_Getal().deallocate(this->_Myfirst(), 
      this->_Myend() - this->_Myfirst()); 
     this->_Myfirst() = pointer(); 
     this->_Mylast() = pointer(); 
     this->_Myend() = pointer(); 
     } 
    } 

http://i61.tinypic.com/2yx0p37.png

这是与findContours功能或矢量类或完全不同的东西出了问题?

+0

[csumike](http://stackoverflow.com/users/5572856)认为这可能是由已知的错误引起的:http://code.opencv.org/issues/4452#note-3 – cgmb

+0

([他认为他的答案应该已经被删除](http://stackoverflow.com/review/low-quality-posts/10236232),因为它提供了一个看起来有用和有效的答案。不幸的是,作为一个新用户并开始你的帖子与'我有同样的问题'我您很可能会将您的答案删除,因为新用户对答案使用答案框是一种常见的错误。这就是评论的方式,有时候。) – cgmb

回答

5

这可能是一个简单的链接问题。

如果您在调试模式下进行编译,链接器需要输入变量opencv_world310d.lib不是opencv_world310.lib(注意点前d)。

只有当您编译版本模式时,您必须键入opencv_world310.lib

我有同样的问题。花费我一天的时间来弄清楚。

+0

虽然这可能在理论上回答这个问题,[这将是更可取的](// meta.stackoverflow.com/q/8259)在这里包括答案的基本部分,并提供链接供参考。 – manetsus

0

我和我的情况一样。 (opencv 3.0) 我试过了,然后findcontours()运作良好。

我想,你已经输入的信息如下.. 链接器 - >输入(입력) - >附加依赖

opencv_world300d.lib opencv_world300.lib opencv_ts300d.lib opencv_ts300.lib

没有编辑过的库,我只是对齐它(300d.lib - > 300.lib) 并应用!它运作良好!根据该