近来学习opencv的接口调用,opencv采用的是3.3.0版本的代码,是自己编译的,有如下一段代码(主要部分,采用vs2015编译,win7 64bit 系统):
vector vecHierarchy;
vector> vecContours;
// 寻找轮廓
findContours(cannyFrame, vecContours, vecHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
// 绘制轮廓
Mat drawingF = Mat::zeros(cannyFrame.size(), CV_8UC3);
Scalar color = Scalar(80, 160, 240);
int i;
for (i = 0; i < vecContours.size(); i++)
drawContours(drawingF, vecContours, i, color, 2, 8, vecHierarchy, 0);
imshow("效果图", drawingF);
以上,是从书上摘取的一段代码,查找物体边界然后画出来并显示。
在第一次执行这段代码时没有问题,在第二次执行完时程序崩溃,如下所示:
崩溃位置的代码在文件debug_heap.cpp中,如下所示:
_ASSERTE(__acrt_first_block == header);
__acrt_first_block = header->_block_header_next;
通过几次跟踪发现,是变量 vecHierarchy 在析构时导致挂掉,跟踪进去,即是其内容在销毁时出现问题。后搜索有人说opencv和调用者的程序采用同一版本的编译器编译后问题解决,但我编译用的都是vs2015,所以不存在这个问题。但是从问题的现象和描述上说,其根源是在opencv库中分配了内存,但在销毁时却是在外面,所以导致失败。
既然是这个原因,那就得把销毁也放在opencv中,为此没有查找到相关的接口,所以就自己对opencv进行了修改,添加了一个接口,对所有vector类传出的参数在使用完后调用此接口来释放内存即可。
定义的接口如下所示:
template
CV_EXPORTS_W void clearVec(std::vector<_Tp> &vecs);
此接口是一个模板,但只有这个模板似乎无法正常工作,所以参考如下两个网址:
https://blog.csdn.net/liyuanbhu/article/details/50363670
https://blog.csdn.net/zhengudaoer/article/details/73796261
对接口进行了修改,添加了可能用到的一些类型实例:
修改之后编译,再对测试代码进行少许修改:
vector vecHierarchy;
vector> vecContours;
// 寻找轮廓
findContours(cannyFrame, vecContours, vecHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
// 绘制轮廓
Mat drawingF = Mat::zeros(cannyFrame.size(), CV_8UC3);
Scalar color = Scalar(80, 160, 240);
int i;
for (i = 0; i < vecContours.size(); i++)
drawContours(drawingF, vecContours, i, color, 2, 8, vecHierarchy, 0);
clearVec(vecContours);
clearVec(vecHierarchy); // 这两行是新添加的
imshow("效果图", drawingF);
vecContours、vecHierarchy是在接口findContours()中分配的,所以在用完之后,调用新添加的接口对其内容进行清除。
这样修改之后,再运行程序,一切正常。对于调用者,需要多一个步骤就是在用完之后调用新增加的接口。
后面会找时间把修改后的opencv库上传上来,有需要的可以下载。
2018.8.2:
修改后的opencv下载:https://download.csdn.net/download/jszj/10579260