2013-05-13 3 views
1

У меня куча коррупции происходит со 100% уверенностью в функции findContours. Когда я его не использую, все работает нормально.OpenCV findContours - 2.4.5 Повреждение кучи

unsigned char* UCFromMatUC(cv::Mat& input) 
{ 
    int size = input.size.p[0] * input.size.p[1]; 
    unsigned char* result = new unsigned char[size]; 
    memcpy(result, input.data, size); 
    return result; 
} 

unsigned char* CannyEdgeCV(unsigned char* input, int width, int height) 
{ 
    std::vector<std::vector<cv::Point> > contours; 
    std::vector<cv::Vec4i> hierarchy; 

    cv::RNG rng(12345); 

    cv::Mat inp(cv::Size(width, height), CV_8UC1, input); 
    cv::Mat canny_output; 
    cv::Mat outp; 
    cv::blur(inp, outp, cv::Size(3,3)); 
    cv::Canny(outp, canny_output, 4.0, 8.0); 
    if(canny_output.type()!=CV_8UC1){ 
     return NULL; 
    } 

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

    cv::imwrite("contours.jpg", drawing); 

    unsigned char* result = UCFromMatUC(canny_output); 

    return result; 
} 

Первоначально я был только с помощью Осторожных карт краев, но позже я хотел проверить результаты функциональности контура.

Canny Edge отлично работает, и я получаю изображение, как ожидалось, но findContours (как в коде, так и в комментариях) терпят неудачу с ошибкой повреждения кучи. Что вызывает это?

Точка входа для этого является CannyEdgeCV() и вызывается с 640x480 8-битным серым изображением.

Редактировать: обновленный код.

Edit2: когда я попытался создать минимальный пример для воспроизведения этого кода, мой код не удался даже при чтении («imagename.bmp»); который был действительно странным, поэтому я начал исследовать, что может вызвать это. Теперь кто-то написал в соответствующем SO-вопросе, что вы не можете смешивать библиотеки режима отладки/выпуска, поэтому, если вы находитесь в отладке, вам нужно использовать DLL-файлы для отладки, и это сработало для меня сейчас, я получаю ожидаемые результаты.

ответ

3

Главным виновником является использование вами cv::Mat* и new. Это плохая идея. Нет необходимости и часто проблематично (как вы обнаружили) динамически выделять объекты cv::Mat. Лучшее решение - передать их по значению или const, поскольку базовые данные изображения пересчитаны, а cv::Mat неглубоко скопированы.

Первая конкретная проблема заключается в том, что вы вручную назначить data члена в CVMatFromUC():

resultMat->data = input 

Вы не должны делать это. cv::Mat имеет других членов, которые также ссылаются на местоположение данных, и вы просите о проблемах. Если вам необходимо создать cv::Mat заголовок для внешних данных, вы должны создать cv::Mat так:

cv::Mat inp(cv::Size(width, height), CV_8UC1, input); //Create cv::Mat header, no memory copied 

Кроме того, ваш чек типа для canny_output неверен. !canny_output.type() оценивается первым и неявно преобразуется в true, равно как и CV_8UC1. Таким образом, выражение всегда равно true. Состояние, которое вы хотите: canny_output.type() != CV_8UC1

Учитывая это, оказывается, что функция CVMatFromUC() не нужна.Улучшенная версия вашей функции следующим образом:

uchar* CannyEdgeCV(uchar* input, int width, int height) 
{ 
    std::vector<std::vector<cv::Point> > contours; 
    std::vector<cv::Vec4i> hierarchy; 

    cv::Mat inp(cv::Size(width, height), CV_8UC1, input); //Create cv::Mat header, no memory copied 
    cv::Mat canny_output; 
    cv::Mat outp; 
    cv::blur(inp, outp, cv::Size(3,3)); 

    cv::Canny(outp, canny_output, 10.0, 15.0); 
    if(canny_output.type()!=CV_8UC1){ 
     return NULL; 
    } 

cv::findContours(canny_output, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 
//cv::findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0)); 

    unsigned char* result = UCFromMatUC(&inp); 
    return result; 
} 

Я хотел бы отметить, что кажется, что CannyEdgeCV возвращает те же данные, которые он получает, так что это может быть возможным, чтобы удалить вызов UCFromMatUC() и связанные с ними данные, копировать полностью. Тем не менее, я пытался и получил ошибки памяти, поэтому могут возникнуть другие проблемы, скрывающиеся в других местах.

+0

Err, вы верны в отношении типа возврата. Я изначально имел это в Canny (outp, inp), поэтому inp держал карту края. Но при отладке этого я изменил его на большее количество переменных, вызвав неправильный возврат. Я внедрил ваши предложения, но я все равно получаю ту же самую кучу коррупции. (Обновленный код в редакции) – SinisterMJ

+1

Итак, часть ваших рекомендаций была необходима, чтобы исправить это, но главной проблемой стало то, что я связал библиотеки выпусков с моим отладочным приложением. – SinisterMJ

0

-Изменить поискКонкурсы следующим образом findContours (серый, контуры, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

  • Если это не сработает, ваша проблема - это, вероятно, неинициализированная память. Вы можете попытаться создать новый Mat outP2 и клонировать его оригинал.

  • Затем с помощью outP2 из следующего шага:

резюме :: Канни (* outP2, canny_output, 10,0, 15,0); ... ...

Смежные вопросы