2012-07-26 5 views
11

Tôi đang cố bắt đầu dò tìm đường viền trong OpenCV 2.4.2. Để kết thúc này, tôi thiết lập một dự án cho OpenCV và sao chép toàn bộ mã ví dụ được tìm thấy trong documentation. Để tham khảo trong tương lai, đây là mã:Mã ví dụ OpenCV để tìm đường bao: vấn đề deallocation vector

#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!! 
} 

Nó biên dịch tốt trong Visual Studio 11 RC (Windows 7 SP1), nhưng tôi nhận được một lỗi ở phần cuối của thresh_callback chức năng. Đây là stacktrace:

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 

(Lưu ý rằng thực sự tôi có một phiên bản sửa đổi một chút các mã ví dụ, thêm một vài printf-s, và một contours.clear() cuộc gọi, đó là tại dòng 143, và đó gây nên các vector deallocation [điều đó sẽ xảy ra tự động ở cuối hàm] mà dường như là nguồn gốc của vấn đề. Vấn đề tương tự cũng xảy ra với mã ví dụ chính xác.)

Vấn đề có vẻ là với sự thỏa thuận vector contours. Điều tương tự cũng xảy ra nếu tôi cố gắng gọi contours.clear(). Tôi đã kiểm tra nội dung của biến trong trình gỡ rối VS, nhưng không có gì khác thường như tôi có thể nói.

Tôi đã cố gắng xóa véc-tơ ngay sau khi nó không còn cần thiết nữa (sau vòng lặp for), nhưng không hiệu quả. Tôi cũng đã cố gắng để chuyển đổi Platform Toolset để Visual Studio 10, mà lần lượt sẽ không biên dịch với các thông báo lỗi vượt ra ngoài tôi:

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) 

Bất kỳ trợ giúp sẽ được đánh giá rất nhiều. Xin lưu ý rằng tôi không phải là lập trình viên C++: Tôi có rất ít kiến ​​thức và thậm chí ít kinh nghiệm hơn với lập trình C++ và lập trình bản địa nói chung.

Chỉnh sửa: hóa ra trình gỡ lỗi hiển thị dòng sai là nguồn lỗi. Tôi nên đã nhìn thấy trong cuộc gọi ngăn xếp rằng vấn đề là với vector>. Vì vậy, vectơ có vấn đề là contours, không phải hierarchy!

Chỉnh sửa # 2: Tôi cũng cố gắng tạo lại vấn đề với mã tối thiểu tạo vector<vector<cv::Point> >, đặt một số mục vào đó, sau đó xóa nó, nhưng tôi không thể tái tạo sự cố.

+0

Bạn biết rằng không có nhu cầu để xóa đối tượng những đường nét, đúng không? Nó sẽ được thu gom rác vào cuối cuộc gọi hàm thresh_callback. Mã của bạn có hoạt động không có dòng này không? –

+1

@ RégisB .: Tôi tin rằng tôi đã đề cập đến nó trong câu hỏi của tôi rằng cùng một lỗi xảy ra mà không có dòng. Lý do duy nhất tôi gọi một cách rõ ràng là 'contours.clear' ở đây là để làm nổi bật nơi xảy ra sự cố. – ShdNx

+0

'Tất cả cấu hình -> Chung -> Platform Toolset -> Visual Studio 2010 (v100)' giải quyết vấn đề cho tôi. – vkalit

Trả lời

16

Bạn đang xây dựng ứng dụng của mình ở chế độ gỡ lỗi và liên kết với CRT DLL đa luồng. Bạn có biết CRT của OpenCV DLL (s) nào được liên kết không? Nếu nó được liên kết với một CRT tĩnh, nó sẽ điền vào vectơ với dữ liệu được phân bổ từ một đống riêng biệt, gây ra một xác nhận trong CRT gỡ lỗi bạn đang sử dụng.

Nếu bạn xây dựng ứng dụng ở chế độ Phát hành, bạn sẽ không còn thấy xác nhận, nhưng bạn có thể sẽ bị rò rỉ bộ nhớ. Điều tốt nhất là để đảm bảo rằng cả hai ứng dụng của bạn và các DLL OpenCV (s) được liên kết với cùng một CRT Multithreaded DLL.

EDIT: Nếu bạn không thể xây dựng lại OpenCV để sử dụng cùng một CRT như ứng dụng của bạn, bạn có thể thử yêu cầu trình liên kết sử dụng cùng một phiên bản CRT như OpenCV cho ứng dụng của bạn bằng cách sửa đổi tệp kê khai ứng dụng. Xem How to Enforce C++ compiler to use specific CRT version? để biết thêm thông tin về cách thực hiện điều đó.

+0

Tôi đã tải xuống mã nguồn OpenCV và xây dựng nó trên máy của mình. Tôi không biết nó liên kết với cái gì - tôi không thay đổi cài đặt định sẵn. Tôi có thể xem thông tin này ở đâu? Tôi đã cố gắng biên dịch và chạy ứng dụng của mình ở chế độ Phát hành, nhưng sự cố vẫn tiếp diễn. – ShdNx

+0

Phụ thuộc Walker (http://www.dependencywalker.com/) có thể hiển thị cho bạn một DLL/EXE đã cho mà DLL có phụ thuộc. Nếu bất cứ thứ gì có tên như MSVC * bật lên trong cây phụ thuộc, bạn có thể so sánh với những gì ứng dụng của bạn đang sử dụng. Nếu không tìm thấy sự phụ thuộc như vậy, DLL có thể được liên kết tĩnh với CRT. – Michael

+0

Ngoài ra, vì bạn đề cập rằng bạn đang xây dựng OpenCV cho mình (cũng sử dụng visual studio?), Bạn có thể đi vào các thuộc tính của dự án khi xây dựng OpenCV và đảm bảo bạn đang sử dụng cùng một CRT cho ứng dụng của bạn (Code Generation -> Thư viện thời gian chạy). – Michael

0

Chuyển sang tùy chọn giải pháp, có cài đặt thời gian chạy (CRT) và kiểm tra liên kết (CRT như đã đề cập ở trên) ... nếu dự án của bạn là/(một lần) được tạo bằng VS10 và bạn sử dụng phiên bản mới hơn Phiên bản, chỉ cần chỉnh sửa các liên kết không được 10, nhưng 11 hoặc 12 ..

0

Thêm vào hệ thống đường dẫn (như là một ví dụ): H: \ Source \ opencv_v2_4_13_2 \ đầu ra \ bin \ Debug

nơi thư mục: "H: \ Source \ opencv_v2_4_13_2 \ đầu ra" được sử dụng từ CMake làm thư mục đích cho các dự án opencv trực quan Studio 14 (2015).

dự án của bạn sử dụng file dll opencv, nhưng không tìm thấy: opencv_core2413d.dll