OpenCV模板化代码在派生类中产生编译错误

OpenCV templated code produces compile errors inside a Derived class

本文关键字:编译 错误 派生 代码 OpenCV      更新时间:2023-10-16

我正在制作一个应用程序,使用OpenCV为我处理一些图像。它应该允许处理不同类型的图像(由用户指定的类型)。

大多数处理都是以相同的方式进行的,并且仅取决于cv:Mat中保存的数据的类型(用于cv::Mat.at<type>()等函数以正确引用数据)。为此,我构建了一个基类ImageProcessor,它将包含公共实现、需要知道类型的函数的虚拟接口和Factory方法。我进一步构建了一个模板化的DerivedTypedProcessor<datatype>类,这样我就可以实现数据访问方法。

然而,每当我在Derived类中使用OpenCV模板化的访问函数时,我都会遇到一个奇怪的编译错误。以下是最小(非)工作示例:

#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>()的等效错误。如果我用short替换datatype,就会出现一个非常类似的错误(而不是我想要的功能;只是为了测试目的)。变量this->workingImage在函数内部通常是可见的(我可以在ImageProcessor内部使用我声明为protected的任何变量),如果我更改主体,函数调用将正常通过。

只有当我专门使用OpenCV中的任何模板访问函数(示例中的beginendat等)时,才会出现错误

更奇怪的是,如果我取消对GOAL: AVOIDING THIS标记的行的注释,它们会完美地编译和执行。但是,这不是一个选项,因为该结构的全部目的是避免这种情况,并通过使用模板化的Derived类来实现依赖于数据类型或特定于数据类型的函数。

注意:本示例中支持的功能和图像类型不是最终的。目前,只有两种类型的图像,但这在未来可能会改变。此外,处理功能有时会是相同的(除了需要指定不同的数据类型),有时它们会有一个共同的部分和依赖于数据/图像类型的部分(例如,预处理需要遍历所有元素,获得最小值和最大值(共同),然后对所有缺失值进行插值(对于我的CCD_ 15和CCD_。一些功能也将直接封装在基类中(如果它们不需要数据规范,例如想到图像的宽度/高度)。

有人知道如何帮助纠正代码或实现所需的功能吗?

对不起,大家,我似乎不知道如何搜索正确的问题。

在这个答案中提供了对一个较小示例的解释。显然,我需要用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;
}