2016-06-08 2 views
1

Я делаю приложение, которое обрабатывало бы некоторые изображения для меня, используя OpenCV. Он должен позволять обрабатывать различные типы изображений (тип, заданный пользователем).Шаблон с кодом OpenCV создает ошибки компиляции внутри класса Derived

Большая часть обработки выполняется аналогичным образом и зависит только от типа данных, хранящихся в cv:Mat (используется в таких функциях, как cv::Mat.at<type>() для правильной ссылки на данные). Для этого я построил базовый класс ImageProcessor, который будет содержать общую реализацию, виртуальные интерфейсы для функций, которые должны знать тип, и метод Factory. Я также построил шаблонный класс Derived TypedProcessor<datatype>, чтобы я мог реализовать методы доступа к данным.

Однако я получаю нечетную ошибку компиляции всякий раз, когда я использую шаблонные функции доступа OpenCV внутри класса Derived. Вот минимальный (не) Рабочий пример:

#include <iostream> 

#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/core/core.hpp> 

class ImageProcessor{ 
    public: 
     static ImageProcessor *NewProcessor(char option, std::string imgPath); 
     virtual ~ImageProcessor() {} 
     virtual void printMaxElem() = 0; 
    protected: 
     ImageProcessor(const std::string &imgPath) : workingImagePath(imgPath) { 
      this->workingImage = cv::imread(imgPath.c_str(), CV_LOAD_IMAGE_ANYDEPTH); 
     } 
     cv::Mat workingImage; 
     std::string workingImagePath; 
}; 


template <typename datatype> 
class TypedProcessor : public ImageProcessor{ 
    public: 
     TypedProcessor(std::string imgPath) : ImageProcessor(imgPath) {} 
     virtual ~TypedProcessor() {} 

     void printMaxElem(); 
     void preprocess(); 
    private: 
     void calculateDisplayValue(); 
}; 

template <typename datatype> 
void TypedProcessor<datatype>::printMaxElem(){ 
    std::cerr << (datatype)(*std::max_element(this->workingImage.begin<datatype>(), this->workingImage.end<datatype>())) << std::endl; 
} 

ImageProcessor* ImageProcessor::NewProcessor(char option, std::string imgPath){ 
    ImageProcessor *processor = NULL; 
    switch (option){ 
     case 'h': // input correctly as CV_32F 
      processor = new TypedProcessor<float>(imgPath); 
      // GOAL: AVOIDING THIS: 
      //std::cerr << (float)(*std::max_element(processor->workingImage.begin<float>(), processor->workingImage.end<float>())) << std::endl; 
      break; 
     case 'i': // input as CV_16U but should be interpreted as CV_16S 
      processor = new TypedProcessor<short>(imgPath); 
      processor->workingImage.flags = (processor->workingImage.flags & ~CV_MAT_TYPE_MASK) | CV_16S; 
      // GOAL: AVOIDING THIS: 
      //std::cerr << (short)(*std::max_element(processor->workingImage.begin<short>(), processor->workingImage.end<short>())) << std::endl; 
      break; 
     default: 
      break; 
    } 

    processor->printMaxElem(); 

    return processor; 
} 


int main(void){ 
    ImageProcessor *myprocessor = ImageProcessor::NewProcessor('h', "user/will/input/this"); 
    return 0; 
} 

Ошибки я получаю является:

In member function ‘void TypedProcessor<datatype>::printMaxElem()’: 
test.cpp:35:84: error: expected primary-expression before ‘>’ token 
     std::cerr << (datatype)(*std::max_element(this->workingImage.begin<datatype>(), this->workingImage.end<datatype>())) << std::endl; 
                        ^
test.cpp:35:86: error: expected primary-expression before ‘)’ token 
    std::cerr << (datatype)(*std::max_element(this->workingImage.begin<datatype>(), this->workingImage.end<datatype>())) << std::endl; 
                       ^

Я также получить эквивалентные ошибки для this->workingImage.end<datatype>(). Очень похожая ошибка появляется, если я заменю datatype на short (не функциональность, которую я хочу, только для целей тестирования). Переменная this->workingImage обычно видима внутри функции, как и ожидалось (и я могу использовать любые переменные, объявляемые как protected внутри ImageProcessor), и вызов функции проходит нормально, если я меняю тело.

Ошибки возникают только тогда, когда я специально с использованием любых шаблонные функций доступа из OpenCV (в begin и end из примера, at и т.д ...).

Еще более любопытно, если я раскомментировал строки, обозначенные GOAL: AVOIDING THIS, они скомпилируются и исполняются отлично. Однако это не вариант, так как весь смысл этой структуры заключается в том, чтобы избежать этого и реализовать либо зависящие от типа данных, либо функции, связанные с типом данных, используя шаблонный класс Derived.

Примечание: функциональность, а также типы изображений, поддерживаемых в этом примере , не являются окончательными. На данный момент существует только два типа изображений, но это может измениться в будущем. Кроме того, функции обработки иногда будут одинаковыми (за исключением необходимости указывать другой тип данных), иногда они будут иметь общую часть и часть, зависящую от типа данных/изображения (например, для предварительной обработки требуется циклическое перемещение по всем элементам, получение мин и максимальные значения (общие), а затем интерполировать все отсутствующие значения (разные подходы для моих изображений float и short)). Некоторые функции также будут инкапсулированы непосредственно в базовый класс (если они не требуют спецификации данных, например, получение ширины/высоты изображения приходит в голову).

Кто-нибудь знает, как помочь в исправлении кода или достижении желаемой функциональности?

+0

Я думаю, что вы чрезмерно усложнять это, если ваша единственная цель состоит в том, чтобы знать, как получить доступ к данным OpenCV ... Любая конкретная проблема, которую вы хотите решать? – Miki

+0

@Miki Изображения представляют собой различные сигналы радара (высота, интенсивность и т. Д.). Некоторые примеры функциональных возможностей: предварительная обработка (общая обработка деталей через данные, интерполяция для любых отсутствующих элементов будет зависеть от типа изображения, высоты и интенсивности, интерполированных по-разному). Отображение изображения (так что человек может его интерпретировать): все изображения, нормализованные до 0-255, а затем, в зависимости от типа данных, одинаковы, отображаются в линейном масштабе, другие - в логарифмическом (например, изображения интенсивности имеют очень мало высоких точек). Тогда будут некоторые общие части, такие как max из примера (просто введите diff) – penelope

+0

Я бы сделал проще ... Постройте классы RadarResponseHeight, 'RadarResponseIntensity' и т. Д. Как' struct RadarResponseXXX {Mat1f мат; ...} 'или какой бы тип вы ни знали, ваши данные будут. Затем вы можете решить, как отображать каждое изображение в соответствии с его смысловым значением, а не только с типом данных ... – Miki

ответ

1

Ужасно, все, похоже, я просто не знал, как найти правильную проблему.

Объяснение на меньшем примере представлено в this answer. По-видимому, мне нужно префикс вызовов функций на template, и это работает как шарм.Таким образом, рассматриваемая функция должна быть переписана как:

template <typename datatype> 
void TypedProcessor<datatype>::printMaxElem(){ 
    std::cerr << (datatype)(*std::max_element(this->workingImage.template begin<datatype>(), this->workingImage.template end<datatype>())) << std::endl; 
} 
Смежные вопросы