0

この質問に対する私のシステム設計について否定的なコメントがいくつかあったので(そのようなシステムの実装に関して)、私が問題を提示すれば、より良い提案が得られることを願っています。

ビデオ フレームの機能マッチングに使用するモジュラー アプリケーションを設計しようとしています (たとえば、Sivic、Zisserman によるこの記事の「製品」のように、映画やビデオの非常に近いフレームでのマッチング)。

アイデアは、さまざまな特徴検出アルゴリズムとさまざまな照合手順を簡単に切り替えることができるようにすることです。さらに、私の調査によると、基本的なマッチング手順はわずかしかなく、新しいマッチング方法は主に悪い一致 (同じ記事の空間的一貫性など) に対する追加のプルーニング手順に焦点を当てていると理解しています。すべてのプルーニング手順では、最初のマッチングを実行する必要があります。次に、マッチングによって結合されたベース イメージとクエリ イメージから抽出された特徴に対して追加の作業を行い、不適切な一致を拒否します。


私がデザインに持っていたアイデアは次のとおりです。

  • 基本インターフェースを実装するfeatureDetector
  • すべての具体的な特徴検出アルゴリズムは、インターフェイスから継承しfeatureDetectorます (例: siftDetector)
  • 基本インターフェースを実装するfeatureMatcher
  • すべての具体的なマッチング メソッドはfeatureMatcherインターフェイスから継承します (例:class bruteForceMatcherまたは のような OpenCV マッチャーのラッパーcvMatcher)
  • との選択を可能にする戦略パターンを実装する基本インターフェースをimageMatcher実装するfeatureDetectorfeatureMatcher
  • 一致するすべてのプルーニング プロシージャに対して、基本一致インターフェイスを継承するDecoratorインターフェイスを実装します。class matcherDecorator : public imageMatcher
  • 追加のプルーニング/フィルタリング手順はそれぞれ、matcherDecoratorインターフェース (例: ) を実装し、(装飾されるコンポーネントを表す) (唯一の) 引数としてspatialConsistencyFilterコンストラクターのみを含みます。imageMatcher*

この質問で指摘された問題は、機能の検出と照合プロセスの特定の結果から生じ、設計のデコレータ部分に関係しています。それぞれが、両方の画像 (ベースとクエリ)から抽出された特徴と、抽出された特徴間の一致imageMatcherを保持する必要があります。機能の内部表現は、 のパブリック アクセス機能を介してユーザーに提供される機能記述子とは少し異なります。imageMatcher

class imageMatcher{
    private: // or protected:
        ...
        ...
        std::vector <internalFeatureDescriptor> feats[2];
            // no more than 500 - 1000 features can be expected

        std::vector <std::pair <int, int> > matches;
            // size is the same order of magnitude as the number of features
        ...
    public:
        std::vector <userFriendlyFeatures> getFeatures(int baseOrQuery);
        const std::vector <std::pair<int, int> > &getMatches();
        ...
};

ここで、特徴ベクトル (および一致ベクトル) は非常に「重い」ため、それらを使用するときに、ネストされたデコレーター (フィルター) のそれぞれにそれらをコピーしたくありません。ベクターには問題はありません。これmatchesは、デコレーターが参照にアクセスできるようにし、データをコピーする必要がないユーザー向けのパブリック インターフェイスを提供するためです。feats一方、ベクトルはそのようなインターフェイスを提供せず、それらのアクセス機能では、コピーするだけでなく、フィーチャの内部表現を再計算する必要があります。これにより、デコレーターが内部スーパークラスのポインターのプライベート (または保護された) 変数にアクセスする必要が生じます。

私は、プライバシーの制約に違反することなく、必要なベクトルへの自己アクセスを許可することができました (私は実装上、何も悪いことはしていないと思います)。Decoratorパターンのアイデア。


とはいえ、コードをリファクタリングする方法についての提案、現在の実装に関するコメント、およびアプリケーションの設計に関するその他のあらゆることに興味があります。

4

1 に答える 1

1

デコレーター パターンの代わりに、フィルターを関数/ファンクターとして実装することもできます。

1: 各フィルターのインターフェイス/署名を定義します。たとえばmatchResult、署名をフィルタリングする場合は、次のようになります。

std::function<void (std::vector <std::pair <int, int> >& )>

(注: および で機能するフィルタが必要な場合がありfeatsますmatches)

2: 以下を使用してフィルターを実装します。

  • 継承/仮想関数 (デコレーターに似ています)
  • C++ ファンクターとして
  • 無料機能として

imageMatcher3:登録済みフィルターをストローするために、メンバー変数をクラスに追加します。

imageMatcher4:フィルターを登録するためのメンバー関数をクラスに追加します

5:getMatches()登録された各フィルターを に適用するように、メンバー関数を実装しますmatches。メンバーへの参照を渡すと、matches各フィルターが適用されるたびに変更されます。

例、ファンクター ベース アプローチが選択されたと仮定した場合

利便性 typedef

typdef std::vector <std::pair <int, int> > match_result;

フィルタのシグネチャは次のとおりです。

typedef std::function< void (match_result& )> match_filter_type;

「imageMatcher」クラスは次のようになります。

class imageMatcher{
    private: // or protected:
        ...
        ...
        match_result matches;
        // size is the same order of magnitude as the number of features

        std::vector< match_filter_type > match_filters;
    ...
    public:
        imageMatcher& registerMatchFilter( match_filter_type filter )
        {
            match_filters.push_back( filter );
            return *this;
        }

        const std::vector <std::pair<int, int> > &getFilteredMatches()
        {
          // c++11 could be replaced with older style for loop
          for( auto& filt: match_filters)  
          {
            // note matches will be modified (see note below)
            filt( matches );
          }
          return matches;
        }
   };

フィルタは次のようになります。

void DoSomeFiltering( match_result& matches )
{
    // apply the filter modifying matches
}

2 番目のフィルターは次のようになります。

struct ComplexFilter
{
   ComplexFilter( params... );  

   void operator()( match_result& matches );
};

フィルタは次のように登録されます。

myImageMatcher.registerMatchFilter( ComplexFilter( args... ) );

// call chaining
myImageMatcher.registerMatchFilter( AnotherFilter( args... ) )
              .registerMatchFilter( OneMoreFilter( args... ) )
              .registerMatchFilter( FilterXXX( args... ) );

注:getFilteredMatchesフィルターは、登録されたのと同じ順序で適用されます。各フィルターは を直接変更しmatchesます。これでよろしいですか? そうでない場合はgetFilteredMatches、コピーを作成matchesしてから、フィルターをコピーに適用できます。次に、コピーが値で返されます (コピーは 1 つだけであることに注意してください。返されたベクトルは、古い c++03 コンパイラでも最適化されます)。

無料の関数/ファンクターを使用するよりも継承を好むと判断するかもしれません。その場合、match_filtersメンバー変数は基本クラス オブジェクトのベクトルになります。

class MatchFilterBase;
std::vector< std::shared_ptr<MatchFilterBase> >  match_filters;

継承アプローチは現在のdecorator pattern実装に近く、実行する必要があるリファクタリングの量を減らすことができます。

デコレータ パターンを使用して装飾対象のオブジェクトの内部コンテンツを直接変更するのは自然に感じられないため、保護されたデータやプライベート データにアクセスするには回避策が必要になる可能性があります。

于 2012-04-04T14:23:53.523 に答える