Download opencv_face_detector_uint8/demo.cpp from opencv/opencv_contribution: direct link, hf CLI and curl.
- Browser
- Download file 5.18 kB
-
https://huggingface.co/opencv/opencv_contribution/resolve/refs%2Fpr%2F13/opencv_face_detector_uint8/demo.cpp
- Command line
-
hf download hf://opencv/opencv_contribution@refs/pr/13/opencv_face_detector_uint8/demo.cpp
-
curl -L -o demo.cpp https://huggingface.co/opencv/opencv_contribution/resolve/refs%2Fpr%2F13/opencv_face_detector_uint8/demo.cpp
5.18 kB
| using namespace cv; | |
| static std::string argVal(int argc, char** argv, const std::string& key, const std::string& def) | |
| { | |
| for (int i = 1; i + 1 < argc; ++i) | |
| if (key == argv[i]) return argv[i + 1]; | |
| return def; | |
| } | |
| struct Layer { float mn, mx; std::vector<int> ars; int step, fm; }; | |
| int main(int argc, char** argv) | |
| { | |
| std::string model = argVal(argc, argv, "--model", "opencv_face_detector_uint8_2026jul.onnx"); | |
| std::string image = argVal(argc, argv, "--image", "example_outputs/input_image.png"); | |
| std::string output = argVal(argc, argv, "--output", "example_outputs/output_image.png"); | |
| float thr = std::stof(argVal(argc, argv, "--conf", "0.4")); | |
| const int sz = 300; | |
| Mat img = imread(image); | |
| if (img.empty()) | |
| { | |
| std::cerr << "could not read image: " << image << std::endl; | |
| return 1; | |
| } | |
| Mat inp; | |
| resize(img, inp, Size(sz, sz)); | |
| inp.convertTo(inp, CV_32F); | |
| subtract(inp, Scalar(104, 177, 123), inp); | |
| if (!inp.isContinuous()) inp = inp.clone(); | |
| int blobShape[] = {1, sz, sz, 3}; | |
| Mat blob(4, blobShape, CV_32F, inp.data); | |
| dnn::Net net = dnn::readNetFromONNX(model); | |
| net.setInput(blob); | |
| std::vector<Mat> outs; | |
| net.forward(outs, net.getUnconnectedOutLayersNames()); | |
| const float* loc = nullptr; | |
| const float* conf = nullptr; | |
| for (size_t i = 0; i < outs.size(); ++i) | |
| { | |
| const Mat& o = outs[i]; | |
| size_t tot = o.total(); | |
| const float* p = (const float*)o.data; | |
| if (tot == 35568) loc = p; | |
| else if (tot == 17784) conf = p; | |
| } | |
| std::vector<Layer> layers = { | |
| {30, 60, {2}, 8, 38}, | |
| {60, 111, {2, 3}, 16, 19}, | |
| {111, 162, {2, 3}, 32, 10}, | |
| {162, 213, {2, 3}, 64, 5}, | |
| {213, 264, {2}, 100, 5}, | |
| {264, 315, {2}, 300, 5}, | |
| }; | |
| std::vector<Vec4f> priors; | |
| for (const Layer& L : layers) | |
| { | |
| std::vector<float> ratios = {1.0f}; | |
| for (int a : L.ars) { ratios.push_back((float)a); ratios.push_back(1.0f / a); } | |
| for (int y = 0; y < L.fm; ++y) | |
| for (int x = 0; x < L.fm; ++x) | |
| { | |
| float cx = (x + 0.5f) * L.step; | |
| float cy = (y + 0.5f) * L.step; | |
| std::vector<Vec2f> boxes = {{L.mn, L.mn}, {std::sqrt(L.mn * L.mx), std::sqrt(L.mn * L.mx)}}; | |
| for (size_t k = 1; k < ratios.size(); ++k) | |
| { | |
| float a = ratios[k]; | |
| boxes.push_back({L.mn * std::sqrt(a), L.mn / std::sqrt(a)}); | |
| } | |
| for (const Vec2f& b : boxes) | |
| priors.push_back({cx, cy, b[0], b[1]}); | |
| } | |
| } | |
| const float var[4] = {0.1f, 0.1f, 0.2f, 0.2f}; | |
| int n = (int)priors.size(); | |
| std::vector<Rect2f> boxes; | |
| std::vector<float> scores; | |
| for (int i = 0; i < n; ++i) | |
| { | |
| float c0 = conf[i * 2], c1 = conf[i * 2 + 1]; | |
| float m = std::max(c0, c1); | |
| float e0 = std::exp(c0 - m), e1 = std::exp(c1 - m); | |
| float s = e1 / (e0 + e1); | |
| if (s <= thr) continue; | |
| float pcx = priors[i][0] / sz, pcy = priors[i][1] / sz; | |
| float pw = priors[i][2] / sz, ph = priors[i][3] / sz; | |
| float cx = pcx + loc[i * 4] * var[0] * pw; | |
| float cy = pcy + loc[i * 4 + 1] * var[1] * ph; | |
| float bw = pw * std::exp(loc[i * 4 + 2] * var[2]); | |
| float bh = ph * std::exp(loc[i * 4 + 3] * var[3]); | |
| boxes.push_back(Rect2f(cx - bw / 2, cy - bh / 2, bw, bh)); | |
| scores.push_back(s); | |
| } | |
| std::vector<int> order(scores.size()); | |
| for (size_t i = 0; i < order.size(); ++i) order[i] = (int)i; | |
| std::sort(order.begin(), order.end(), [&](int a, int b){ return scores[a] > scores[b]; }); | |
| std::vector<char> removed(order.size(), 0); | |
| std::vector<int> pick; | |
| for (size_t oi = 0; oi < order.size(); ++oi) | |
| { | |
| if (removed[oi]) continue; | |
| int i = order[oi]; | |
| pick.push_back(i); | |
| for (size_t oj = oi + 1; oj < order.size(); ++oj) | |
| { | |
| if (removed[oj]) continue; | |
| int j = order[oj]; | |
| const Rect2f& a = boxes[i]; | |
| const Rect2f& b = boxes[j]; | |
| float xx1 = std::max(a.x, b.x), yy1 = std::max(a.y, b.y); | |
| float xx2 = std::min(a.x + a.width, b.x + b.width); | |
| float yy2 = std::min(a.y + a.height, b.y + b.height); | |
| float inter = std::max(0.f, xx2 - xx1) * std::max(0.f, yy2 - yy1); | |
| float iou = inter / (a.area() + b.area() - inter + 1e-9f); | |
| if (iou > 0.3f) removed[oj] = 1; | |
| } | |
| } | |
| int W = img.cols, H = img.rows; | |
| for (int i : pick) | |
| { | |
| const Rect2f& b = boxes[i]; | |
| rectangle(img, Point(int(b.x * W), int(b.y * H)), | |
| Point(int((b.x + b.width) * W), int((b.y + b.height) * H)), Scalar(0, 255, 0), 2); | |
| } | |
| imwrite(output, img); | |
| std::cout << "opencv_face_detector_uint8 " << pick.size() << " faces" << std::endl; | |
| return 0; | |
| } | |