Добавление к CvSeq или другому типу динамической памяти в C / C ++ в проекте OpenCV - PullRequest
1 голос
/ 17 ноября 2011

Вопрос ответил, см. Решение в конце вопроса. Другие комментарии / ответы все еще приветствуются.

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

Я в первую очередь программист на Java, поэтому я, вероятно, буду использовать некоторые термины Java вместо эквивалента C и, возможно, упомяну неправильные типы при обращении к объектам C, поэтому я заранее одобряю это (и не понимаю начал по указателям).

В конечном итоге я пытаюсь взять все дефекты выпуклости на изображении и сохранить их в одном непрерывном пространстве, которое я затем передам обратно в Java через JNI. Тип магазина не важен, на данном этапе мне просто нужно, чтобы он работал, и я могу поработать над оптомизацией, если мы добьемся успеха, но я думаю, что стек, очередь, список, вектор или что-то подобное сделает эту работу. В настоящее время я пытаюсь циклически добавлять группы объектов CvSeq в один большой CvSeq, я опубликую свой код и обсудю его после публикации:

 CvSeq *allDefects;
allDefects = cvCreateSeq(0, sizeof (CvSeq), sizeof (CvConvexityDefect), mem_storage4);

CvContourScanner scanner3 = cvStartFindContours(img_bin, mem_storage3);
while ((c2 = cvFindNextContour(scanner3)) != NULL) {
    if (threshold != 0 && cvContourPerimeter(c2) < threshold) {
        cvSubstituteContour(scanner3, NULL);
    } else { // otherwise create the hull
        CvSeq* c_new;
        c_new = cvConvexHull2(c2, mem_storage5, CV_CLOCKWISE, 0);
        CvMemStorage* storage;
        storage = cvCreateMemStorage(0);
        defects = cvConvexityDefects(c2, c_new, storage);
        allDefects = defects;
        //            for (int i = 0;  i < defects->total; i++){
        //            cvSeqPush(allDefects, CV_GET_SEQ_ELEM(CvSeq, defects, i));
        //            }
    }
}

Итак, мы создаем сканер и, в то время как мы можем найти контуры, мы делаем это и проверяем, что он больше заданного порога. Предполагая, что это мы создаем вокруг него корпус, а затем находим дефекты между ним и корпусом. Это означает, что дефектов может содержать несколько объектов, которые я хочу добавить к allDefects каждый раз, когда мы зацикливаемся, но единственный способ добиться этого - сделать allDefects равно дефектов означает, что каждый цикл перезаписывается. Вы можете увидеть немного прокомментированного кода, где я пытаюсь выдвинуть его как стек, но он вылетает с ошибкой:

Утверждение не удалось: sizeof (((дефекты)) -> первый [0]) == sizeof (CvSeqBlock) && ((дефекты)) -> elem_size == sizeof (CvSeq), файл vtoolsModified.cpp, строка 1407

В соответствии с документацией «Процедура cvConvexityDefects () возвращает последовательность структур CvConvexityDefect», так что CvSeq полон CvConvexityDefect (s). Подпись cvConvexityDefects в случае, если это поможет:

 CVAPI(CvSeq*)  cvConvexityDefects( const CvArr* contour, const CvArr* 
    convexhull, CvMemStorage* storage CV_DEFAULT(NULL));

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

Кто-нибудь может помочь или указать мне в направлении источника, который может? (Я работаю над этой конкретной проблемой уже около 2 недель, поэтому потратил много ресурсов, и да, я чувствую себя действительно глупо из-за того, что не смог понять, что должно быть простым циклом самостоятельно.)

Спасибо

РЕДАКТИРОВАТЬ - более подробно добавлено в результате комментариев.

РЕДАКТИРОВАТЬ 2 - Ответ на вопрос, результирующий, фиксированный код ниже

Похоже, мое непонимание C было основной проблемой. Я предполагал, что мне нужно использовать CvSeq в месте, где я должен был использовать CvConvexityDefect. Исправленный код выглядит следующим образом:

CvSeq *defects;
CvSeq *allDefects;
allDefects = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvConvexityDefect), mem_storage4);

CvContourScanner scanner3 = cvStartFindContours(img_bin, mem_storage3);
while ((c2 = cvFindNextContour(scanner3)) != NULL) {
    if (threshold != 0 && cvContourPerimeter(c2) < threshold) {
        cvSubstituteContour(scanner3, NULL);
    } else { // otherwise create the hull
        CvSeq* c_new;
        c_new = cvConvexHull2(c2, mem_storage5, CV_CLOCKWISE, 0);
        CvMemStorage* storage;
        storage = cvCreateMemStorage(0);
        defects = cvConvexityDefects(c2, c_new, storage);
        //            allDefects = defects;
        if (defects->total < 100) {
         for (int i = 0; i < defects->total; i++) {
          CvConvexityDefect* element = CV_GET_SEQ_ELEM(CvConvexityDefect, defects, i);
           if (element != 0){      
               cvSeqPush(allDefects, element);                    }
            }
        }
    }
}

Вы можете видеть, что я также проверяю, чтобы убедиться, что возвращено менее 100 дефектов (иногда это миллионы, которые разрушают систему), а также чтобы убедиться, что CV_GET_SEQ_ELEM не возвращает ноль (я не уверен, если это могу вернуть ноль, но я проверю на всякий случай.

1 Ответ

1 голос
/ 18 ноября 2011

Я предполагаю, что ваш цикл содержит ошибку в этой строке:

CV_GET_SEQ_ELEM(CvSeq, defects, i)

Если вы посмотрите на его определение:

#define CV_GET_SEQ_ELEM( elem_type, seq, index ) CV_SEQ_ELEM( (seq), elem_type, (index) )

, вы увидите, что первый параметрдолжен быть тип элемента (cvFindContours обычно создает последовательности CvPoint), а не тип последовательности (CvSeq)

Другими способами хранения ваших последовательностей будет использование

    void* cvCvtSeqToArray(const CvSeq* seq,
                          void* elements,
                          CvSlice slice = CV_WHOLE_SEQ
                         );

и сохраняйте массивы в списке, сохраняя дефекты отдельно для каждого объекта.Есть еще больше опций, в зависимости от того, что вам нужно.

EDIT2:

Хорошо, так что я просто просмотрел cvConvexityDefects и увидел, что он возвращает последовательность структур, а не CvPoint, тогда ваши allDefects должныбыть CvSeq на заказ, и вы будете изменять свой код, как это:

cvSeqPush(allDefects, CV_GET_SEQ_ELEM(CvConvexityDefect, defects, i));
...