improve cpu version of SoftCascade:

- remove division
 - remove cvRound
 - cache feature area
This commit is contained in:
marina.kolpakova 2012-10-06 16:58:48 +04:00
parent 2d2c46e717
commit 2914f24521

View File

@ -126,6 +126,7 @@ struct Feature
{
int channel;
cv::Rect rect;
float rarea;
static const char * const SC_F_CHANNEL;
static const char * const SC_F_RECT;
@ -136,6 +137,9 @@ struct Feature
cv::FileNode rn = fn[SC_F_RECT];
cv::FileNodeIterator r_it = rn.end();
rect = cv::Rect(*(--r_it), *(--r_it), *(--r_it), *(--r_it));
// 1 / area
rarea = 1.f / ((rect.width - rect.x) * (rect.height - rect.y));
}
};
@ -192,10 +196,13 @@ struct Level
float origScale;
float relScale;
float shrScale; // used for marking detection
int scaleshift;
cv::Size workRect;
cv::Size objSize;
enum { R_SHIFT = 1 << 15 };
float scaling[2];
Level(const Octave& oct, const float scale, const int shrinkage, const int w, const int h)
@ -203,8 +210,9 @@ struct Level
workRect(cv::Size(cvRound(w / (float)shrinkage),cvRound(h / (float)shrinkage))),
objSize(cv::Size(cvRound(oct.size.width * relScale), cvRound(oct.size.height * relScale)))
{
scaling[0] = CascadeIntrinsics::getFor(0, relScale);
scaling[1] = CascadeIntrinsics::getFor(9, relScale);
scaling[0] = CascadeIntrinsics::getFor(0, relScale) / (relScale * relScale);
scaling[1] = CascadeIntrinsics::getFor(9, relScale) / (relScale * relScale);
scaleshift = relScale * (1 << 16);
}
void markDetection(const int x, const int y, float confidence, std::vector<Object>& detections) const
@ -214,6 +222,25 @@ struct Level
detections.push_back(Object(rect, confidence));
}
float rescale(cv::Rect& scaledRect, const float threshold, int idx) const
{
// rescale
// scaledRect.x = cvRound(relScale * scaledRect.x);
// scaledRect.y = cvRound(relScale * scaledRect.y);
// scaledRect.width = cvRound(relScale * scaledRect.width);
// scaledRect.height = cvRound(relScale * scaledRect.height);
scaledRect.x = (scaleshift * scaledRect.x + R_SHIFT) >> 16;
scaledRect.y = (scaleshift * scaledRect.y + R_SHIFT) >> 16;
scaledRect.width = (scaleshift * scaledRect.width + R_SHIFT) >> 16;
scaledRect.height = (scaleshift * scaledRect.height + R_SHIFT) >> 16;
float sarea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
// compensation areas rounding
return (threshold * scaling[idx] * sarea);
}
};
template< typename T>
@ -416,41 +443,6 @@ struct cv::SoftCascade::Filds
typedef std::vector<Octave>::iterator octIt_t;
float rescale(const Feature& feature, const float scaling, const float relScale,
cv::Rect& scaledRect, const float threshold) const
{
scaledRect = feature.rect;
dprintf("feature %d box %d %d %d %d\n", feature.channel, scaledRect.x, scaledRect.y,
scaledRect.width, scaledRect.height);
dprintf("rescale: %d %f %f\n",feature.channel, relScale, scaling);
float farea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
// rescale
scaledRect.x = cvRound(relScale * scaledRect.x);
scaledRect.y = cvRound(relScale * scaledRect.y);
scaledRect.width = cvRound(relScale * scaledRect.width);
scaledRect.height = cvRound(relScale * scaledRect.height);
dprintf("feature %d box %d %d %d %d\n", feature.channel, scaledRect.x, scaledRect.y,
scaledRect.width, scaledRect.height);
float sarea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
const float expected_new_area = farea * relScale * relScale;
float approx = sarea / expected_new_area;
dprintf(" rel areas %f %f\n", expected_new_area, sarea);
// compensation areas rounding
float rootThreshold = threshold * approx * scaling;
dprintf("approximation %f %f -> %f %f\n", approx, threshold, rootThreshold, scaling);
return rootThreshold;
}
void detectAt(const Level& level, const int dx, const int dy, const ChannelStorage& storage,
std::vector<Object>& detections) const
{
@ -477,10 +469,9 @@ struct cv::SoftCascade::Filds
// work with root node
const Node& node = nodes[nId];
const Feature& feature = features[node.feature];
cv::Rect scaledRect;
float threshold = rescale(feature, level.scaling[(int)(feature.channel > 6)],
level.relScale, scaledRect, node.threshold);
cv::Rect scaledRect(feature.rect);
float threshold = level.rescale(scaledRect, node.threshold,(int)(feature.channel > 6)) * feature.rarea;
float sum = storage.get(dx, dy, feature.channel, scaledRect);
@ -494,10 +485,10 @@ struct cv::SoftCascade::Filds
const Node& leaf = nodes[nId + next];
const Feature& fLeaf = features[leaf.feature];
threshold = rescale(fLeaf, level.scaling[(int)(fLeaf.channel > 6)],
level.relScale, scaledRect, leaf.threshold);
sum = storage.get(dx, dy, fLeaf.channel, scaledRect);
scaledRect = fLeaf.rect;
threshold = level.rescale(scaledRect, leaf.threshold, (int)(fLeaf.channel > 6)) * fLeaf.rarea;
sum = storage.get(dx, dy, fLeaf.channel, scaledRect);
int lShift = (next - 1) * 2 + ((sum >= threshold) ? 1 : 0);
float impact = leaves[(st * 4) + lShift];