2011-10-29 3 views
0
나 자신에 의해 디지털 영상 처리를 공부하고 누군가가 polymorphism이 경우에 적용하거나해야하는지 여부를 언급 할 수 있다면 정말 감사 드리겠습니다

에 대한 다형성 더 나은 수준의 디자인이 있는지.사례 연구 : 이미지 처리

기본적으로 2D 필터/커널은 non-separable 또는 separable 일 수 있습니다. 중요한 커널 연산은 convolution이며이를 계산하는 방법은 필터 유형에 따라 다릅니다. 심지어 CSeparableKernel2D 클래스가 두 개인 회원을 가질 수

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; 
}; 

참고 : CKernel1D<T> m_X, m_Y. CKernel1D<T> 클래스는 자체 myConvolution 메소드를 가질 수 있습니다. 즉, myConvolutionRows, myConvolutionCols입니다.

또한 일반적으로 주어진 이미지에 filters (분리 가능/분리 불가능) 세트를 적용하고 싶습니다. 즉, 입력 이미지가 주어진 filter 인 경우를 나타냅니다. 따라서 filter type에 따라 해당 myConvolution 메서드를 호출해야합니다.

(1) STH을 할 수있는 깨끗한 방법으로해야한다. 처럼?

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. 

내가 할 수있는 유일한 방법은 다형성을 사용하는 것입니다. 맞습니까?

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 메타 od는 kernel 유형에 따라 호출됩니다. 어떻게 그런 조작을 할 수 있습니까? 나는 sth를 읽었다. Virtual Friend Function Idiom에 대해, 그런 경우에 해당 관용구를 적용하는 것이 합리적이라고 생각하십니까?

모든 의견 & 제안은 정말 환영합니다 ;-) 난 정말 당신이 디자인에 대해 어떻게 생각하십니까 듣고 싶어요? 이러한 기능을 설계하는 더 좋은 방법이 있습니까? 이미지 분석 이후

답변

0

전산 많은 힘을 필요로 좋은 공연 importants입니다. 다형성은 훌륭한 물건이지만, 물론 런타임 추상화 레이어를 추가하므로 정적으로 링크 된 코드보다 느립니다.

당신이 템플릿을 사용하여 컴파일 시간 추상화 계층을 사용하지 않는 이유는 이미 템플릿을 사용하고 있기 때문에? 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; 
} 

차세대 컴파일러는 :) 아주 잘 오버 헤드를이 코드를 최적화 할 수 있습니다 당신은 0이됩니다, 릴리즈 모드로 컴파일합니다.

당연히 다형성을 사용할 수 있다면 한 번만 호출해야한다면 내부 함수 작성자를 천 번 호출해야하는 경우에는 당연한 것입니다. 두 기술을 모두 혼합하여 내부 루프에서 높은 성능을 얻을 수 있으며 동시에 높은 수준에서 사용하기 쉽습니다.

+0

감사합니다. 정적으로 링크 된 코드를 사용한 적이 한번도 없었습니다. 또한, 제 경우에는'NegateTransformer'와 같은 클래스는 예를 들어 특정 커널 타입에 대응할 것입니다, 그렇죠? 'Transform' 메쏘드는 전체 그림을 보는'convolution'과'ArrayTransformer'가 될 것이고'Kernel2D '이 될 것입니다, 맞습니까? – Tin

+0

@ 마크, 다형 함수는 '커널 컨볼 루션'당 한 번만 호출됩니다. 'implementation'에서, 픽셀을 처리하기위한 중첩 루프가 있습니다. – Tin