Skip to content

Instantly share code, notes, and snippets.

@liberize
Last active March 15, 2019 15:27
Show Gist options
  • Save liberize/6672f53abfa871ba520c28d37365a939 to your computer and use it in GitHub Desktop.
Save liberize/6672f53abfa871ba520c28d37365a939 to your computer and use it in GitHub Desktop.
pico full angle detection
namespace {
const int MAX_DETS = 5;
const float SCALE_FACTOR = 1.1f;
const float STRIDE_FACTOR = 0.1f;
const float QUALITY_THRESH = 10.0f;
const float ANGLE_STEP = 45.0f;
}
struct PicoObject {
float row;
float col;
float size;
float quality;
};
void PicoFaceDetector::DoDetect(const Image &img, const cv::Rect2f &roi, std::vector<Face> &faces,
int minSize, int maxSize)
{
if (cascade_ == NULL) {
return;
}
cv::Mat gray = cvext::empty(roi) ? img.gray : cvext::roi(img.gray, roi);
if (maxSize == 0) {
maxSize = std::min(gray.cols, gray.rows);
}
const int NUM_ANGLES = 360.0f / ANGLE_STEP;
PicoObject rcsq[NUM_ANGLES * MAX_DETS] = {0};
int ndets[NUM_ANGLES] = {0};
cvext::parallel_for(0, NUM_ANGLES, [&](int r) {
ndets[r] = find_objects((float *)&rcsq[r * MAX_DETS], MAX_DETS, cascade_, r * ANGLE_STEP / 360.0f,
gray.data, gray.rows, gray.cols, (int)gray.step[0],
SCALE_FACTOR, STRIDE_FACTOR, minSize, maxSize);
});
int total = ndets[0];
int idx[NUM_ANGLES * MAX_DETS] = {0};
for (int i = 1; i < NUM_ANGLES; i++) {
for (int j = 0; j < ndets[i]; j++, total++) {
rcsq[total] = rcsq[i * MAX_DETS + j];
idx[total] = i;
}
}
float qs[NUM_ANGLES * MAX_DETS] = {0};
for (int i = 0; i < total; i++) {
qs[i] = rcsq[i].quality;
}
int cc[NUM_ANGLES * MAX_DETS] = {0};
int remain = cluster_detections((float *)rcsq, total, cc);
for (int i = 0; i < remain; i++) {
if (rcsq[i].quality < QUALITY_THRESH) {
continue;
}
float sumqs[NUM_ANGLES] = {0};
for (int j = 0; j < total; j++) {
if (cc[j] == i + 1) {
sumqs[idx[j]] += qs[j];
}
}
float maxqs = 0, angle = 0;
for (int j = 0; j < NUM_ANGLES; j++) {
if (sumqs[j] > maxqs) {
maxqs = sumqs[j];
angle = j * ANGLE_STEP;
}
}
cv::Point2f center(rcsq[i].col + roi.x, rcsq[i].row + roi.y);
// face rect is a little too up, fix it by move center point down
cvext::move(center, rcsq[i].size / 10, angle);
cv::Rect2f rect(center.x - rcsq[i].size / 2, center.y - rcsq[i].size / 2, rcsq[i].size, rcsq[i].size);
faces.emplace_back(img, rect);
faces.back().pose.roll = angle;
faces.back().score = rcsq[i].quality;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment