Я делаю приложение, которое обрабатывало бы некоторые изображения для меня, используя 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
)). Некоторые функции также будут инкапсулированы непосредственно в базовый класс (если они не требуют спецификации данных, например, получение ширины/высоты изображения приходит в голову).
Кто-нибудь знает, как помочь в исправлении кода или достижении желаемой функциональности?
Я думаю, что вы чрезмерно усложнять это, если ваша единственная цель состоит в том, чтобы знать, как получить доступ к данным OpenCV ... Любая конкретная проблема, которую вы хотите решать? – Miki
@Miki Изображения представляют собой различные сигналы радара (высота, интенсивность и т. Д.). Некоторые примеры функциональных возможностей: предварительная обработка (общая обработка деталей через данные, интерполяция для любых отсутствующих элементов будет зависеть от типа изображения, высоты и интенсивности, интерполированных по-разному). Отображение изображения (так что человек может его интерпретировать): все изображения, нормализованные до 0-255, а затем, в зависимости от типа данных, одинаковы, отображаются в линейном масштабе, другие - в логарифмическом (например, изображения интенсивности имеют очень мало высоких точек). Тогда будут некоторые общие части, такие как max из примера (просто введите diff) – penelope
Я бы сделал проще ... Постройте классы RadarResponseHeight, 'RadarResponseIntensity' и т. Д. Как' struct RadarResponseXXX {Mat1f мат; ...} 'или какой бы тип вы ни знали, ваши данные будут. Затем вы можете решить, как отображать каждое изображение в соответствии с его смысловым значением, а не только с типом данных ... – Miki