C++ 查找轮廓的 OpenCV 示例代码:向量释放问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11677118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:24:32  来源:igfitidea点击:

OpenCV example code for find contours: vector deallocation issue

c++memoryimage-processingopencv

提问by ShdNx

I'm trying to get started with contour detection in OpenCV 2.4.2. To this end, I set up a project for OpenCV and copied the whole example code found in the documentation. For future reference, here is the code:

我正在尝试开始在 OpenCV 2.4.2 中进行轮廓检测。为此,我为 OpenCV 设置了一个项目并复制了文档中的整个示例代码。为了将来参考,这里是代码:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);

/// Function header
void thresh_callback(int, void* );

/** @function main */
int main( int argc, char** argv )
{
  /// Load source image and convert it to gray
  src = imread( argv[1], 1 );

  /// Convert image to gray and blur it
  cvtColor( src, src_gray, CV_BGR2GRAY );
  blur( src_gray, src_gray, Size(3,3) );

  /// Create Window
  char* source_window = "Source";
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );
  imshow( source_window, src );

  createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
  thresh_callback( 0, 0 );

  waitKey(0);
  return(0);
}

/** @function thresh_callback */
void thresh_callback(int, void* )
{
  Mat canny_output;
  vector<vector<Point> > contours;
  vector<Vec4i> hierarchy;

  /// Detect edges using canny
  Canny( src_gray, canny_output, thresh, thresh*2, 3 );
  /// Find contours
  findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

  /// Draw contours
  Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
  for( int i = 0; i< contours.size(); i++ )
     {
       Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
       drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
     }

  /// Show in a window
  namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
  imshow( "Contours", drawing );

  contours.clear(); // Error!!
}

It compiles fine in Visual Studio 11 RC (Windows 7 SP1), but I get an error at the end of the thresh_callbackfunction. Here is the stacktrace:

它在 Visual Studio 11 RC (Windows 7 SP1) 中编译良好,但在thresh_callback函数结束时出现错误。这是堆栈跟踪:

msvcr110d.dll!_CrtIsValidHeapPointer(const void * pUserData) Line 2036
msvcr110d.dll!_free_dbg_nolock(void * pUserData, int nBlockUse) Line 1322
msvcr110d.dll!_free_dbg(void * pUserData, int nBlockUse) Line 1265
msvcr110d.dll!operator delete(void * pUserData) Line 54
std::allocator<cv::Point_<int> >::deallocate(cv::Point_<int> * _Ptr, unsigned int __formal) Line 586
std::_Wrap_alloc<std::allocator<cv::Point_<int> > >::deallocate(cv::Point_<int> * _Ptr, unsigned int _Count) Line 888
std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > >::_Tidy() Line 1542
std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > >::~vector<cv::Point_<int>,std::allocator<cv::Point_<int> > >() Line 901
std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > >::`scalar deleting destructor'(unsigned int)
std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > >::destroy<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > >(std::<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _Ptr) Line 624
std::allocator_traits<std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > > >::destroy<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > >(std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > > & _Al, std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _Ptr)758
std::_Wrap_alloc<std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > > >::destroy<std::vector<cv::Point_<int>,std::allocator<cv::Poin> > > >(std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _Ptr) Line 909
std::_Destroy_range<std::_Wrap_alloc<std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > > > >(std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _First, std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _Last, std::_Wrap_alloc<std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::<int> > > > > & _Al, std::_Nonscalar_ptr_iterator_tag __formal) Line 89
std::_Destroy_range<std::_Wrap_alloc<std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > > > >(std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _First, std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _Last, std::_Wrap_alloc<std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::<int> > > > > & _Al) Line 80
std::vector<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > >,std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> >::_Destroy(std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _First, std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > * _Last) Line 1480
std::vector<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > >,std::allocator<std::vector<cv::Point_<int>,std::allocator<cv::Point_<int> > > > >::c Line 1416
thresh_callback(int __formal, void * __formal) Line 143
opencv_highgui242d.dll!icvUpdateTrackbar(CvTrackbar * trackbar, int pos) Line 1938
opencv_highgui242d.dll!HGToolbarProc(HWND__ * hwnd, unsigned int uMsg, unsigned int wParam, long lParam) Line 1982

(Note that actually I have a slightly modified version of the example code, added a few printf-s, and a contours.clear()call, which is at line 143, and which triggers the vector deallocation [that would happen automatically at the end of the function] which seems to be the source of the problem. The very same issue occurs with the exact example code as well.)

(请注意,实际上我对示例代码做了一个稍微修改的版本,添加了一些 printf-s 和一个contours.clear()调用,该调用位于第 143 行,并触发了向量释放[这将在函数结束时自动发生]这似乎是问题的根源。完全相同的问题也发生在确切的示例代码中。)

The problem seems to be with the deallocation of the contoursvector. The same occurs if I try to call contours.clear(). I have examined the variable's contents in the VS debugger, but there's nothing unusual as far as I can tell.

问题似乎与contours向量的解除分配有关。如果我尝试调用contours.clear(). 我已经在 VS 调试器中检查了变量的内容,但据我所知,没有什么异常。

I tried to clear the vector as soon as it was no longer needed (after the forloop), but it didn't help. I also tried to switch the Platform Toolset to Visual Studio 10, which in turn won't even compile with error messages that are beyond me:

我试图在不再需要时(在for循环之后)清除向量,但它没有帮助。我还尝试将平台工具集切换到 Visual Studio 10,它甚至不会编译超出我的错误消息:

error C1083: Cannot open include file: 'SDKDDKVer.h': No such file or directory (C:\<project path>\targetver.h) (Line 8, Column 1)
IntelliSense: cannot open source file "SDKDDKVer.h" (C:\<project path>\targetver.h) (Line 8, Column 1)
IntelliSense: cannot open source file "windows.h" (C:\<opencv path>\build\include\opencv2\core\operations.hpp (Line 83, Column 3)

Any help would be greatly appreciated. Please note that I'm not a C++ programmer: I have very little knowledge, and even less experience with C++ programming and native programming in general.

任何帮助将不胜感激。请注意,我不是 C++ 程序员:我对 C++ 编程和本机编程的知识很少,而且经验更少。

Edit: it turns out that the debugger displayed the wrong line as the source of error. I should have seen in the call stack that the problem was with vector >. So the problematic vector is contours, not hierarchy!

编辑:事实证明,调试器将错误的行显示为错误源。我应该在调用堆栈中看到问题出在 vector > 上。所以有问题的向量是contours,不是hierarchy

Edit #2: I also tried to reproduce the issue with a minimal code that creates a vector<vector<cv::Point> >, puts some items in it, then clears it, but I couldn't reproduce the problem.

编辑#2:我还尝试使用创建一个的最小代码重现该问题vector<vector<cv::Point> >,将一些项目放入其中,然后将其清除,但我无法重现该问题。

回答by Michael

You're building your application in debug mode and linking against the Multithreaded Debug DLL CRT. Do you know which CRT the OpenCV DLL(s) are linked against? If it's linked against a static CRT it'll fill up the vector with data allocated from a separate heap, which causes an assertion in the Debug CRT you're using.

您正在调试模式下构建应用程序并链接到多线程调试 DLL CRT。您知道 OpenCV DLL 链接到哪个 CRT 吗?如果它与静态 CRT 链接,它将用从单独堆分配的数据填充向量,这会导致您正在使用的调试 CRT 中出现断言。

If you build your application in Release mode you should no longer see the assert, but you might end up leaking memory. The best thing would be to ensure that both your application and the OpenCV DLL(s) are linked against the same Multithreaded DLL CRT.

如果您在发布模式下构建应用程序,您应该不会再看到断言,但最终可能会泄漏内存。最好的办法是确保您的应用程序和 OpenCV DLL 都链接到同一个多线程 DLL CRT。

EDIT: If you can't rebuild OpenCV to use the same CRT as your application you could try telling the linker to use the same CRT version as OpenCV for your application by modifying the application manifest. See How to Enforce C++ compiler to use specific CRT version?for more information on how to do that.

编辑:如果您无法重建 OpenCV 以使用与您的应用程序相同的 CRT,您可以尝试通过修改应用程序清单来告诉链接器为您的应用程序使用与 OpenCV 相同的 CRT 版本。请参阅如何强制 C++ 编译器使用特定的 CRT 版本?有关如何执行此操作的更多信息。

回答by Rob

Go into your solution-options, there the c-runtime (CRT) settings and check the linking (CRT as mentioned above)... if your project was/is (once) created with VS10 and you use a newer version, just edit the links not to be 10, but 11 or 12 ..

进入您的解决方案选项,那里有 c-runtime (CRT) 设置并检查链接(如上所述的 CRT)...链接不是 10,而是 11 或 12 ..

回答by lightlion

Add to System Path (as an example): H:\Source\opencv_v2_4_13_2\output\bin\Debug

添加到系统路径(例如):H:\Source\opencv_v2_4_13_2\output\bin\Debug

where directory: "H:\Source\opencv_v2_4_13_2\output" is used from CMake as destination directory for visual Studio 14 (2015) opencv projects.

其中目录:“H:\Source\opencv_v2_4_13_2\output”从 CMake 用作 Visual Studio 14 (2015) opencv 项目的目标目录。

Your project uses opencv dll files, but is not find: opencv_core2413d.dll

您的项目使用 opencv dll 文件,但未找到:opencv_core2413d.dll