我正在编写一个大量使用OpenCV的C ++应用程序。不幸的是,我想要使用的一些OpenCV代码尚未被其API公开。特别是,我想使用cascadedetect.cpp(下面引用)中的struct LBPEvaluator :: Feature。我知道我不能简单地“#include cascadedetect.cpp”,因为它会使链接器与多重定义的符号混淆。我假设有一个更优雅的解决方案,而不是复制,粘贴和重命名代码到我的一个源文件中? 访问第三方API未公开的第三方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 :(得分:4)
我的一般策略是不访问未通过公共界面公开的第三方功能和/或类。
它们不是公共的这一事实意味着它们可以在发布版本和下一版本之间进行更改,因此您不应该依赖它。
修改强>
如果它是开源代码(和/或您有权复制它)并且您确实需要此功能,则可以提取相关部分并对其进行个性化维护。这可以使您免受原始代码可能发生变化的影响。您将使用相同的代码重复,违反DRY principle,但我想这是可以容忍的。
答案 1 :(得分:0)
一般来说,你不应该。对于经过良好调试的API,如果没有暴露某些东西,可能有一个很好的理由,为什么它不是。
我遇到了一些必须要做的事情。始终在内部代码中,我无法轻松访问存储库以更改API。在这些情况下,通常我只需将所需例程的配置文件放在需要它的源文件的顶部,尽可能难看。然后它应该“固定”,以便尽早公开。
我想您可能在API中发现了私有方法需要公开的问题。如果是这种情况,你真的应该做上面的等价,并与API的维护者讨论如何公开该方法。这也会让他们有机会告诉你为什么这是一个非常糟糕的主意(如果是的话)。