2017-02-15 18 views
2

С помощью этого простого автономного демо:резюме :: connectedComponentsWithStats в OpenCV 3.2.0 иногда падает с GCC 6.2

#include <opencv2/opencv.hpp> 

#include <iostream> 

int main(int argc, char *argv[]) { 
    // unsigned char data[] = {1, 0, 1}; // crashes 
    unsigned char data[] = {1, 1, 0}; // does not crash 

    cv::Mat1b testImage = cv::Mat1b(3, 1, data); 

    cv::Mat labeledImage; 
    cv::Mat stats; 
    cv::Mat centroids; 
    int neighborhood = 8; 

    int componentCount = cv::connectedComponentsWithStats(
     testImage, labeledImage, stats, centroids, neighborhood); 

    std::cout << "componentCount: " << componentCount << std::endl; 

    return EXIT_SUCCESS; 
} 

С GCC 5.4 он прекрасно работает для значений обоих 'данные'. С помощью GCC 6.2, он отлично работает для {1,1,0} но свалки это с data = {1,0,0}:

======= Memory map: ======== 
00400000-00407000 r-xp 00000000 08:01 15214967       /home/doria/build/Examples/c++/OpenCV/Bug/Bug 
00606000-00607000 rw-p 00006000 08:01 15214967       /home/doria/build/Examples/c++/OpenCV/Bug/Bug 
020b2000-0216c000 rw-p 00000000 00:00 0         [heap] 
7f2608000000-7f2608021000 rw-p 00000000 00:00 0 
7f2608021000-7f260c000000 ---p 00000000 00:00 0 
7f260cc1d000-7f260cc24000 r-xp 00000000 08:01 10883576     /lib/x86_64-linux-gnu/librt-2.23.so 
7f260cc24000-7f260ce23000 ---p 00007000 08:01 10883576     /lib/x86_64-linux-gnu/librt-2.23.so 
7f260ce23000-7f260ce24000 r--p 00006000 08:01 10883576     /lib/x86_64-linux-gnu/librt-2.23.so 
7f260ce24000-7f260ce25000 rw-p 00007000 08:01 10883576     /lib/x86_64-linux-gnu/librt-2.23.so 
7f260ce25000-7f260ce28000 r-xp 00000000 08:01 10883446     /lib/x86_64-linux-gnu/libdl-2.23.so 

Любые мысли?

+0

Hi David! Кажется, я заметил ошибку. Я напишу электронное письмо автору алгоритма, чтобы узнать, есть ли у него дополнительные знания. – Miki

ответ

3

Я несу ответственность за ошибку ... вздох.

Проблема в том, что алгоритм работает в 2x2 блоках на изображении. Максимальное количество меток - по одному на блок. К сожалению, если изображение имеет нечетное число строк и/или столбцов, оценка количества блоков неверна. Таким образом, чтобы исправить это, мы должны делать:

const size_t Plength = ((img.rows + 1)/2) * ((img.cols + 1)/2); 

Мы подадим запрос тянуть к OpenCV для этого сегодня. Плюс улучшенный набор тестов. Кстати, мы все еще ожидаем включения параллельной версии (многоядерности) алгоритма. Мы уже подали в ноябре pull request для параллельной версии (многоядерной) алгоритма, который также исправляет ошибку.

Вы можете найти исправленную версию в OpenCV 3.3 с июня 2017 года. Кроме того, она также включает параллельную версию.

3

Я могу воспроизвести эту ошибку с помощью Visual Studio 2015 (vc14 x64).

Проблемы кажется в строке 352 of connectedcomponents.cpp:

//A quick and dirty upper bound for the maximimum number of labels. 
const size_t Plength = img.rows*img.cols/4; 
LabelT *P = (LabelT *)fastMalloc(sizeof(LabelT)* Plength); 

С вашего тестового изображения, это PLength вычисляет 0:

Plength = (3*1)/4 = 0 

Так *P имеет нулевые элементы.

Тем не менее, это в течение присваивания нескольких местах в алгоритме:

P[lunique] = lunique; 

и lunique имеет значения >0. Таким образом, это вызывает кучу коррупции иногда.

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

+1

Хотел бы я дать +5 :) Это вызвало серьезные головные боли сегодня. –

+0

Я использовал как электрический забор, так и valgrind (по одному за раз), и на самом деле с ним он не сработал в случае, когда я указал «сбои». Как еще вы могли бы отследить что-то подобное? –

+0

@David Я предполагаю, что отладчик визуальной студии сделал неплохую работу. Крушение было расположено рядом с 'fastFree'' P', поэтому было ясно, что искать – Miki