2012-07-26 3 views
11

Sto tentando di iniziare con il rilevamento dei contorni in OpenCV 2.4.2. A tal fine, ho impostato un progetto per OpenCV e copiato l'intero codice di esempio trovato nello documentation. Per riferimento futuro, ecco il codice:Codice di esempio OpenCV per trovare contorni: problema di deallocation vettoriale

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

Si compila bene in Visual Studio 11 RC (Windows 7 SP1), ma ottengo un errore alla fine della funzione thresh_callback. Ecco 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 

(Si noti che in realtà io sono una versione leggermente modificata del codice di esempio, ha aggiunto un paio di printf-s, e un invito contours.clear(), che è in linea di 143, e che innesca il vettore deallocation [che avverrà automaticamente alla fine della funzione] che sembra essere la fonte del problema. Lo stesso identico problema si verifica con il codice esatto di esempio.)

Il problema sembra essere con la deallocazione di il vettore contours. Lo stesso accade se provo a chiamare contours.clear(). Ho esaminato il contenuto della variabile nel debugger VS, ma non c'è nulla di insolito per quanto posso dire.

Ho provato a cancellare il vettore non appena non era più necessario (dopo il ciclo for), ma non è stato di aiuto. Ho provato anche a cambiare il Toolset Platform per Visual Studio 10, che a sua volta non sarà nemmeno compilare con i messaggi di errore che sono al di là di me:

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) 

Qualsiasi aiuto sarebbe molto apprezzato. Si noti che non sono un programmatore C++: ho pochissime conoscenze e meno esperienza con la programmazione C++ e la programmazione nativa in generale.

Modifica: si scopre che il debugger ha visualizzato la riga sbagliata come origine dell'errore. Avrei dovuto vedere nello stack di chiamate che il problema era con vettore>. Quindi il vettore problematico è contours, non hierarchy!

Modifica # 2: Ho anche provato a riprodurre il problema con una quantità minima di codice che crea un vector<vector<cv::Point> >, mette alcuni elementi in esso, poi si schiarisce, ma non riuscivo a riprodurre il problema.

+0

Lo sai che non c'è alcuna necessità di cancellare i contorni oggetto, giusto? Sarà raccolto dalla spazzatura alla fine della chiamata alla funzione thresh_callback. Il tuo codice funziona senza questa linea? –

+1

@ RégisB .: Credo di averlo menzionato nella mia domanda che lo stesso errore si verifica senza la linea. L'unica ragione per cui ho chiamato esplicitamente 'contours.clear' qui è di evidenziare dove si sta verificando il problema. – ShdNx

+0

'Tutte le configurazioni -> Generale -> Set di strumenti della piattaforma -> Visual Studio 2010 (v100)' problema risolto per me. – vkalit

risposta

16

Si sta creando l'applicazione in modalità di debug e si collega al CRT DLL di debug multithreading. Sai a quale CRT sono collegate le DLL OpenCV? Se è collegato a un CRT statico, riempirà il vettore con i dati allocati da un heap separato, il che provoca un'asserzione nel CRT di debug che stai utilizzando.

Se si crea l'applicazione in modalità di rilascio, non si dovrebbe più vedere l'asserzione, ma si potrebbe finire per perdere memoria. La cosa migliore sarebbe assicurarsi che sia l'applicazione che le DLL OpenCV siano collegate allo stesso CRT DLL multithreaded.

MODIFICA: se non è possibile ricostruire OpenCV per utilizzare lo stesso CRT dell'applicazione, è possibile provare a dire al linker di utilizzare la stessa versione CRT di OpenCV per l'applicazione modificando il manifest dell'applicazione. Vedere How to Enforce C++ compiler to use specific CRT version? per ulteriori informazioni su come farlo.

+0

Ho scaricato il codice sorgente OpenCV e l'ho creato sul mio computer. Non so a cosa sia collegato: non ho modificato l'impostazione predefinita. Dove posso vedere queste informazioni? Ho provato a compilare ed eseguire la mia applicazione in modalità di rilascio, ma il problema persiste. – ShdNx

+0

Dependency Walker (http://www.dependencywalker.com/) può mostrare per un determinato DLL/EXE a quali DLL ha dipendenze. Se qualcosa chiamato MSVC * si apre nell'albero delle dipendenze, puoi confrontarlo con quello che sta usando la tua applicazione. Se non viene trovata alcuna dipendenza, la DLL è probabilmente collegata staticamente al CRT. – Michael

+0

Inoltre, dal momento che dici che stai costruendo OpenCV da solo (usando anche lo studio visivo?), Puoi entrare nelle proprietà del progetto quando crei OpenCV e assicurati di utilizzare lo stesso CRT della tua applicazione (Generazione di codice -> Libreria di runtime). – Michael

0

Accedi alle opzioni della soluzione, lì le impostazioni di c-runtime (CRT) e controlla il collegamento (CRT come accennato in precedenza) ... se il tuo progetto è/è (una volta) creato con VS10 e usi un nuovo versione, basta modificare i link per non essere 10, ma 11 o 12 ..

0

Aggiungi al percorso di sistema (ad esempio): H: \ Source \ opencv_v2_4_13_2 \ output \ bin \ Debug

dove directory: "H: \ Source \ opencv_v2_4_13_2 \ output" viene utilizzato da CMake come directory di destinazione per i progetti opencv di Visual Studio 14 (2015).

Il progetto utilizza file dll OpenCV, ma non è stato trovato: opencv_core2413d.dll