我正在自己学习数字图像处理,如果有人可以评论是否应该为这种情况应用polymorphism
或是否有更好的课程设计,我将非常感激。
基本上,2D过滤器/内核可以是:non-separable
或separable
。一个重要的内核操作是convolution
,计算它的方式取决于过滤器类型。
template < typename T >
class CKernel2D{
public:
//....
virtual CMatrix<T> myConvolution(const CMatrix<T> & input) = 0;
//....
};
template < typename T >
class CNonSeparableKernel : public CKernel2D<T> {
public:
//....
CMatrix<T> myConvolution(const CMatrix<T> & input );
void initNonSeparableFilter1( double, int );
//....
private:
CMatrix<T> m_Kernel;
};
template < typename T >
class CSeparableKernel2D : public CKernel2D<T>{
public:
//....
CMatrix<T> myConvolution(const CMatrix<T> & input );
void initSeparableFilter1( double, double );
//....
private:
std::vector<T> m_KernelX;
std::vector<T> m_KernelY;
};
请注意,即使CSeparableKernel2D
类也可能有两个私有成员:CKernel1D<T> m_X, m_Y
。 CKernel1D<T>
类可以有自己的myConvolution
方法,即myConvolutionRows
,myConvolutionCols
。
此外,通常,我们希望将一组filters
(可分离/不可分离)应用到给定图像上,即将输入图像与给定filter
进行卷积。因此,根据filter type
,应调用相应的myConvolution
方法。
(1)这应该是最干净的方法。样的?
CNonSeparableKernel<float> myNonSepFilter1;
myNonSepFilter1.initNonSeparableFilter1(3.0, 1);
CNonSeparableKernel<float> mySepFilter1;
mySepFilter1.initSeparableFilter1(0.5, 0.5);
std::vector<CKernel2D<float> > m_vFilterbank;
m_vFilterbank.push_back(myNonSepFilter1); // Would like to assign a non-sep filter.
m_vFilterbank.push_back(mySepFilter1); // Would like to assign a sep filter.
在我看来,唯一的方法是使用polimorphism,对吗?
CKernel2D<float> * pKernel2d = NULL;
pKernel2d = &mySepFilter1; m_vFilterbank.push_back(*pKernel2d);
pKernel2d = &myNonSepFilter1; m_vFilterbank.push_back(*pKernel2d);
(2)现在假设我们的filterbank
已经填充了两种类型的内核,要在输入图像上应用卷积,它就足够了:
outputSeparable1 = m_vFilterbank.at(0).myConvolution(input);
outputNonSeparable1 = m_vFilterbank.at(1).myConvolution(input);
(3)现在想象一下,我希望有一个朋友convolution
函数和以下原型:
friend CMatrix<T> convolution(const CKernel2D<T> &, const CImage<T> &);
再次,我希望根据myConvolution
类型调用正确的kernel
方法。我怎么能实现这样的操作?我读了......关于Virtual Friend Function Idiom
,你认为,将这个成语用于这种情况是否有意义?
所有评论&amp;建议真的很受欢迎;-)我真的很想听听你对这个设计有什么看法?有没有更好的方法来设计这些功能?
答案 0 :(得分:0)
由于图像分析需要大量的计算能力,因此良好的性能非常重要。 每个人都知道多态性是一个很好的东西,但当然它增加了一个运行时抽象层,因此,它比静态链接代码慢。
由于您已经在使用模板,为什么不使用模板使用编译时抽象层?与STL一样,您可以将算法包装在类中并通过模板参数传递它们。
我在这里发布一个简单的例子来说明原理。
template <typename T, typename FUNCTOR>
class ArrayTransformer
{
public:
static void Transform(T* array, int count)
{
for (int i = 0; i < count; ++i)
FUNCTOR::Transform(array[i]);
}
template <int N>
static void Transform(T (&array)[N])
{
for (int i = 0; i < N; ++i)
FUNCTOR::Transform(array[i]);
}
};
template <typename T>
class NegateTransformer
{
public:
static void Transform(T& value)
{
value = -value;
}
};
int main()
{
int array[] = { 1, 2, 3, 4, 5, 6 };
ArrayTransformer<int, NegateTransformer<int> >::Transform(array);
....
return 0;
}
新一代编译器可以很好地优化这些代码:)如果您使用的是良好的编译器并且在发布模式下编译,则开销将为零。
当然,如果你必须多次调用内部函子,这是有道理的,如果你只能在只使用多态时调用它。 您还可以混合使用这两种技术,以在内循环中获得高性能,同时在更高级别上轻松实现可用性。