2011-02-08 8 views
1

OpenCVを大量に使用するC++アプリケーションを作成しています。残念ながら、私が使用したいOpenCVコードの一部は、APIによって公開されていません。特に、私が利用したいと思っているcascadedetect.cpp(以下引用)にLBPEvaluator :: Featureという構造体があります。私は単純に "#include cascadedetect.cpp"を使うことはできないことを知っています。リンカを複数定義されたシンボルと混同してしまうからです。コードをコピーして貼り付け、名前を自分のソースファイルの名前に変更するよりも洗練されたソリューションがあると思いますか? 第三者のAPIによって公開されていない第三者のC++関数およびクラスにアクセスするための一般的な戦略は何ですか?サードパーティのC++関数とクラスを公開する

事前に感謝します。私が使用しようとしている

特定コード:

class LBPEvaluator : public FeatureEvaluator 
{ 
public: 
    struct Feature 
    { 
     Feature(); 
     Feature(int x, int y, int _block_w, int _block_h ) : 
     rect(x, y, _block_w, _block_h) {} 

     int calc(int offset) const; 
     void updatePtrs(const Mat& sum); 
     bool read(const FileNode& node); 

     Rect rect; // weight and height for block 
     const int* p[16]; // fast 
    }; 

    LBPEvaluator(); 
    virtual ~LBPEvaluator(); 

    virtual bool read(const FileNode& node); 
    virtual Ptr<FeatureEvaluator> clone() const; 
    virtual int getFeatureType() const { return FeatureEvaluator::LBP; } 

    virtual bool setImage(const Mat& image, Size _origWinSize); 
    virtual bool setWindow(Point pt); 

    int operator()(int featureIdx) const 
    { return featuresPtr[featureIdx].calc(offset); } 
    virtual int calcCat(int featureIdx) const 
    { return (*this)(featureIdx); } 
private: 
    Size origWinSize; 
    Ptr<vector<Feature> > features; 
    Feature* featuresPtr; // optimization 
    Mat sum0, sum; 
    Rect normrect; 

    int offset; 
};  


inline LBPEvaluator::Feature :: Feature() 
{ 
    rect = Rect(); 
    for(int i = 0; i < 16; i++) 
     p[i] = 0; 
} 

inline int LBPEvaluator::Feature :: calc(int offset) const 
{ 
    int cval = CALC_SUM_(p[5], p[6], p[9], p[10], offset); 

    return (CALC_SUM_(p[0], p[1], p[4], p[5], offset) >= cval ? 128 : 0) | // 0 
      (CALC_SUM_(p[1], p[2], p[5], p[6], offset) >= cval ? 64 : 0) | // 1 
      (CALC_SUM_(p[2], p[3], p[6], p[7], offset) >= cval ? 32 : 0) | // 2 
      (CALC_SUM_(p[6], p[7], p[10], p[11], offset) >= cval ? 16 : 0) | // 5 
      (CALC_SUM_(p[10], p[11], p[14], p[15], offset) >= cval ? 8 : 0)| // 8 
      (CALC_SUM_(p[9], p[10], p[13], p[14], offset) >= cval ? 4 : 0)| // 7 
      (CALC_SUM_(p[8], p[9], p[12], p[13], offset) >= cval ? 2 : 0)| // 6 
      (CALC_SUM_(p[4], p[5], p[8], p[9], offset) >= cval ? 1 : 0); 
} 

inline void LBPEvaluator::Feature :: updatePtrs(const Mat& sum) 
{ 
    const int* ptr = (const int*)sum.data; 
    size_t step = sum.step/sizeof(ptr[0]); 
    Rect tr = rect; 
    CV_SUM_PTRS(p[0], p[1], p[4], p[5], ptr, tr, step); 
    tr.x += 2*rect.width; 
    CV_SUM_PTRS(p[2], p[3], p[6], p[7], ptr, tr, step); 
    tr.y += 2*rect.height; 
    CV_SUM_PTRS(p[10], p[11], p[14], p[15], ptr, tr, step); 
    tr.x -= 2*rect.width; 
    CV_SUM_PTRS(p[8], p[9], p[12], p[13], ptr, tr, step); 
} 

bool LBPEvaluator::Feature :: read(const FileNode& node) 
{ 
    FileNode rnode = node[CC_RECT]; 
    FileNodeIterator it = rnode.begin(); 
    it >> rect.x >> rect.y >> rect.width >> rect.height; 
    return true; 
} 

LBPEvaluator::LBPEvaluator() 
{ 
    features = new vector<Feature>(); 
} 
LBPEvaluator::~LBPEvaluator() 
{ 
} 

bool LBPEvaluator::read(const FileNode& node) 
{ 
    features->resize(node.size()); 
    featuresPtr = &(*features)[0]; 
    FileNodeIterator it = node.begin(), it_end = node.end(); 
    for(int i = 0; it != it_end; ++it, i++) 
    { 
     if(!featuresPtr[i].read(*it)) 
      return false; 
    } 
    return true; 
} 

Ptr<FeatureEvaluator> LBPEvaluator::clone() const 
{ 
    LBPEvaluator* ret = new LBPEvaluator; 
    ret->origWinSize = origWinSize; 
    ret->features = features; 
    ret->featuresPtr = &(*ret->features)[0]; 
    ret->sum0 = sum0, ret->sum = sum; 
    ret->normrect = normrect; 
    ret->offset = offset; 
    return ret; 
} 

bool LBPEvaluator::setImage(const Mat& image, Size _origWinSize) 
{ 
    int rn = image.rows+1, cn = image.cols+1; 
    origWinSize = _origWinSize; 

    if(image.cols < origWinSize.width || image.rows < origWinSize.height) 
     return false; 

    if(sum0.rows < rn || sum0.cols < cn) 
     sum0.create(rn, cn, CV_32S); 
    sum = Mat(rn, cn, CV_32S, sum0.data); 
    integral(image, sum); 

    size_t fi, nfeatures = features->size(); 

    for(fi = 0; fi < nfeatures; fi++) 
     featuresPtr[fi].updatePtrs(sum); 
    return true; 
} 

bool LBPEvaluator::setWindow(Point pt) 
{ 
    if(pt.x < 0 || pt.y < 0 || 
     pt.x + origWinSize.width >= sum.cols-2 || 
     pt.y + origWinSize.height >= sum.rows-2) 
     return false; 
    offset = pt.y * ((int)sum.step/sizeof(int)) + pt.x; 
    return true; 
} 

Ptr<FeatureEvaluator> FeatureEvaluator::create(int featureType) 
{ 
    return featureType == HAAR ? Ptr<FeatureEvaluator>(new HaarEvaluator) : 
     featureType == LBP ? Ptr<FeatureEvaluator>(new LBPEvaluator) : Ptr<FeatureEvaluator>(); 
} 
+0

Uh、その構造体はpublicです。 – Puppy

答えて

4

私の一般的な戦略は、彼らのパブリックインターフェイスを介して公開されていませんないアクセスサードパーティの機能および/またはクラスにあります。

公開されていないということは、リリースと次のリリースの間で変更できることを意味します。そのため、依存性を置くべきではありません。それがオープンソースコード(および/またはあなたがそれをコピーする権限を持っている)だと、あなたが本当にこの機能が必要、あなたは関連する部分を抽出し、個人的にそれを維持することができれば

EDIT
。これにより、元のコードが変更される可能性がなくなります。同じコードを複製して、DRY principleに違反することになりますが、これは許容されると思います。

0

一般的に、そうしないでください。うまくデバッグされたAPIの場合、何かが公開されていなければ、それはおそらく理由がありません。

私はいくつかの事例に出くわしました。 APIを変更するためにリポジトリに簡単にアクセスすることができなかった内部コードで常に。そのような場合、一般的には、必要なルーチンのプロファイルを、必要なソースファイルの最上部にできるだけ醜いように置くだけです。それはできるだけ早く公表されるように「固定」されるべきです。

プライベートメソッドを公開する必要があるAPIで問題が見つかった可能性があります。そのような場合は、上記と同等のことを行う必要があり、APIのメンテナに、メソッドを公開することについて話してください。それはまた、なぜこれが本当に悪い考えであるのかを伝えるチャンスを与えます(もしそうなら)。

関連する問題