我正在制作一个应用程序,它可以使用 OpenCV 为我处理一些图像。它应该允许处理不同类型的图像(类型由用户指定)。
大多数处理都是以相同的方式完成的,只取决于 cv:Mat
中保存的数据类型。 (用于 cv::Mat.at<type>()
等函数以正确引用数据)。为此,我构建了一个基类 ImageProcessor
其中将包含通用实现、需要知道类型的函数的虚拟接口(interface)以及工厂方法。我进一步构建了一个模板化的 Derived TypedProcessor<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>()
的等效错误.如果我替换 datatype
会出现一个非常相似的错误与 short
(不是我想要的功能;仅用于测试目的)。变量 this->workingImage
正常情况下在函数内部可见(并且我可以在 protected
中使用我声明为 ImageProcessor
的任何变量),并且如果我更改主体,函数调用将正常通过。
仅当我专门使用 OpenCV 中的任何模板化访问函数时才会出现错误(示例中的 begin
和 end
,at
等...)。
更好奇的是,如果我取消注释 GOAL: AVOIDING THIS
标记的行,它们可以完美地编译和执行。但是,这不是一个选项,因为此结构的全部意义在于避免这种情况,并通过使用模板化派生类来实现依赖于数据类型或特定于数据类型的功能。
注意:此示例中支持的功能和图像类型不是最终的。目前,只有两种类型的图像,但将来可能会改变。此外,处理函数有时是相同的(除了需要指定不同的数据类型),有时它们会有共同的部分和依赖于数据/图像类型的部分(例如,预处理需要遍历所有元素,得到最小值和最大值(常见),然后插入所有缺失值(我的 float
和 short
图像采用不同的方法)。一些功能也将直接封装在基类中(如果它们不需要数据规范,例如想到获取图像的宽度/高度)。
有人知道如何帮助更正代码或实现所需的功能吗?
最佳答案
呃,对不起大家,我好像只是不知道如何搜索正确的问题。
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;
}
关于c++ - OpenCV 模板化代码在派生类中产生编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37707179/