Author: Swallow Incubate

  • Face Anti-Spoofing Design Checklist: 12 Items to Review Before Production

    When you build face recognition into a business system and only check whether the face matches, it can be defeated with a printed photo. This article turns the anti-spoofing points you should review before running face recognition in production into a checklist that keeps gaps out of your design and procurement.

    If you cannot check off an item, follow the linked article or the explanation under it for the background.


    What is face spoofing — and what do you need to detect to stop it?

    Face spoofing is an attempt by someone other than the enrolled user to pass face recognition by showing the camera a photo, a screen, or a video of the user’s face. The technical term is presentation attack (see Types of Presentation Attacks on Face Recognition).

    Face recognition decides whether a face belongs to the same person as the enrolled one, so a photo still matches as long as the user’s face is in it (see our experiment). To stop spoofing, you therefore add a separate component that decides whether what is in front of the camera is a live person or a fake: liveness detection (PAD).

    Three approaches to liveness detection

    Approach How it works Burden on the user Watch out for
    Active (challenge-response) Asks the user to blink, turn their head, or speak, and checks the response High (the user must follow instructions) If it only checks that something moved, a replayed video can reproduce the motion
    Dedicated sensors Uses depth or infrared cameras to check 3D shape or material Low Requires special hardware; cannot be added to existing standard cameras
    Passive, single frame A trained model decides live or fake from one ordinary camera image None (just take the picture) Accuracy depends on the model; check APCER / BPCER together with the test conditions

    Whichever approach you choose, the rule is to decide based on the attacks you expect in your use case and on numbers (APCER / BPCER) — not on the words “it blocks attacks.” The 12 items below make sure that decision is made without gaps during design and procurement.


    A. Define your threat model

    ☐ 1. Have you written down who gains — and how much — if impersonation succeeds?
    The right level of defense depends on the use case: time-and-attendance and account opening need very different lines of defense. Start by putting your system’s attacker motive into words. → Types of Presentation Attacks

    ☐ 2. Have you decided which attack types to defend against?
    Print, display, video replay, 3D mask, deepfake — defending against everything means over-investing. Treat print and display attacks (which anyone can carry out today) as the minimum. → Attack cost vs. likelihood

    ☐ 3. Have you considered injection attacks, not just attacks shown to the camera?
    For high-value systems such as financial services, also assume attacks that bypass the camera and inject video directly. These are covered by channel and device protection, not by liveness detection alone.


    B. Add liveness detection as a separate component

    ☐ 4. Have you designed face matching and liveness detection as separate functions?
    Face matching answers “whose face is this?”; liveness detection answers “live person or fake?” They are different technologies. A matching face does not mean a live person. → Why face recognition is fooled by a photo

    ☐ 5. Do you know how your chosen liveness approach can be defeated?
    Blink challenges, motion challenges and depth cameras each have a weak point — video replay, injection, and 3D masks respectively. Choose an approach with its limits in mind.

    ☐ 6. Have you decided between asking users to perform actions and a passive (no-action) check?
    Challenge-response hurts the user experience and puts a burden on older users and users with disabilities. A passive, single-frame check works without asking the user to do anything.


    C. Evaluate accuracy with numbers

    ☐ 7. Have you checked APCER and BPCER as a pair, together with the test conditions?
    A single number, or a number without its conditions, cannot be evaluated. Always read it together with the presentation attack instruments (PAIs) used — print, screen, mask and so on — and the sample counts. → APCER and BPCER explained

    ☐ 8. Have you distinguished an internal evaluation based on ISO metrics from independent third-party testing?
    “An internal evaluation using the metrics defined in ISO/IEC 30107-3” and testing by an independent accredited lab (for example, ISO/IEC 30107-3 PAD conformance testing, or FIDO Biometric Component Certification) mean different things. Check how the vendor’s product page phrases it.

    ☐ 9. Have you measured it in your own operating environment (camera, lighting, distance)?
    Published figures reflect the vendor’s test conditions. Results change with your actual cameras, lighting and capture distance. Validate in your own environment before you deploy.


    D. Fit your operating environment

    ☐ 10. Is sending face images to an external service allowed in your environment?
    If you use a cloud API, check where images are processed, whether they are stored, and whether a Data Processing Agreement (DPA) is available. Some environments do not allow face images to leave the premises at all. Face images may also be regulated as biometric data in your jurisdiction (for example under GDPR in the EU or BIPA in Illinois), so involve your privacy or legal team early.

    ☐ 11. Does the round trip fit your latency budget — and have you decided what happens on a timeout?
    Measure the end-to-end response time from your own network, not just the vendor’s stated target. Decide in advance whether a failed or timed-out check blocks the user (fail closed) or is retried.

    ☐ 12. Do you send the whole camera frame, not a face crop?
    Cues such as paper edges, screen bezels, reflections and the background around the face are part of what a single-frame model looks at. Cropping the image down to the face rectangle before sending it throws those cues away. Also check image brightness and resolution in your real capture conditions. → Example: our API’s image guidelines


    Index: background articles for this checklist

    Topic Article
    Face recognition is fooled by a photo (experiment) We Built Face Recognition with OpenCV — and a Printed Photo Got Right Through
    Attack types, threat levels and accuracy metrics Types of Presentation Attacks on Face Recognition — and Which Ones Are Realistic Threats

    Summary

    • Anti-spoofing starts where “does the face match?” ends. Design in four stages without gaps: threat model → liveness approach → accuracy evaluation → operating environment.
    • The minimum line is rejecting print and display attacks. This is required whatever the use case.
    • Read accuracy as APCER and BPCER, as a pair, with test conditions — and measure in your own environment.
    • Whether images may leave your environment, how much latency you can afford, and how you capture the image decide whether a deployment succeeds just as much as accuracy does.
  • Types of Presentation Attacks on Face Recognition — and Which Ones Are Realistic Threats

    In our previous experiment, we confirmed that plain face recognition can be defeated with a printed photo. So what other kinds of spoofing attacks are there, and how realistic is each one?

    When you design a face recognition system, the starting point is not “block every attack.” It is deciding which attacks your system needs to withstand, given what it is used for. This article organizes the attack types to help you make that call.


    Terminology: presentation attacks and PAD

    An attack that impersonates someone by presenting a fake — a photo, a screen, a mask — to the camera is called a presentation attack. The technology that detects it is PAD (Presentation Attack Detection), also known as liveness detection. This terminology follows the framework used in ISO/IEC 30107, the international standard series on biometric presentation attack detection.

    Attacks that bypass the camera and inject fake data directly into the system (injection attacks) are a separate class of threat, and they are where deepfakes are most often used. This article focuses on attacks that are shown to the camera.

    Presentation attack: "show" a fake to the camera     -> covered by PAD (liveness detection)
    Injection attack:    bypass the camera, inject data   -> covered by channel and device protection
    

    Five types of attack

    1. Print attack

    The attacker holds a printed photo of the target’s face up to the camera. This is the oldest and cheapest attack: all it takes is a printer. The photo itself is often published by the target on social media, so it is easy to obtain. As our experiment showed, face recognition without liveness detection cannot stop it.

    2. Display attack (still image)

    The attacker shows a photo of the face on a smartphone or tablet screen. No printing is required, so it can be done on the spot. Moiré patterns and screen reflections are possible clues, but spotting them is not the face recognition model’s job — so plain face recognition lets it through as well.

    3. Replay attack (video)

    The attacker plays a video of the target’s face on a screen. Unlike a still image, the video contains blinking and head movement, which can defeat simple challenge-based liveness checks such as “blink and you are real.” Video material, too, can be obtained when the target has published it.

    4. 3D mask attack

    The attacker wears a three-dimensional mask modeled on the target’s face. Because a mask has real depth, it can fool some depth-based defenses. However, a convincing mask requires significant cost and the target’s 3D face shape, so the attack cost is roughly an order of magnitude higher. It is only worth it against high-value targets.

    5. Deepfakes

    The attacker uses AI-generated or AI-manipulated face images and video. A deepfake can be shown on a screen as a presentation attack, or fed through a virtual camera as an injection attack. The latter needs system-wide defenses, not liveness detection alone. Generation costs are falling every year, making this the fastest-moving area of the threat landscape.


    Attack cost vs. likelihood

    Attack Attack cost How easy the material is to obtain Likelihood (our view)
    1. Print Very low Often available on social media High — defend against first
    2. Display (still image) Very low Same as above High — same as above
    3. Replay (video) Low Possible if public video exists Medium
    4. 3D mask High (fabrication, 3D shape data) Difficult Low — limited to high-value targets
    5. Deepfake (shown on a screen) Medium to low (falling) Can be generated from photos Medium — increasing

    The key point: the size of a threat is set by how easy the attack is to carry out, not by how sophisticated it is. The attacks to worry about most are not elaborate 3D masks, but types 1 and 2 — which anyone can carry out today.


    How far to defend depends on the use case

    Every defense you add costs money and adds friction for users. The deciding question is: if impersonation succeeds, who gains, and how much?

    Example use case Motive for impersonation Where to draw the line (one way to think about it)
    Time and attendance Buddy punching (clocking in for someone else) 1 and 2 are a must; covering 3 makes it robust
    Door access and facility management Unauthorized entry 1, 2 and 3 are a must; consider 4 depending on what is protected
    Logins to clinical and business systems Misuse of privileges 1, 2 and 3 are a must
    eKYC / remote identity verification and account opening Direct financial gain Assume 1 through 5, plus defenses against injection attacks

    Try writing down, for your own system, what would happen if a printed photo got through. The level of defense you need usually becomes clear.


    Measure the effect with accuracy metrics

    When you evaluate liveness detection, look for numbers, not the words “it blocks attacks.” The field has its own accuracy metrics, defined in ISO/IEC 30107-3:

    • APCER (Attack Presentation Classification Error Rate) — the share of attack samples wrongly accepted as live. Lower means stronger against attacks.
    • BPCER (Bona Fide Presentation Classification Error Rate) — the share of genuine live faces wrongly rejected as attacks. Lower means better usability.

    The two are a trade-off, so looking at only one of them tells you little. They also need to be read together with the test conditions — which attack samples were used, and how many.


    Summary

    • Presentation attacks are easiest to reason about as five types: print, display, video replay, 3D mask, and deepfake.
    • The size of a threat is driven by how easy it is to carry out, not how sophisticated it is. The top priorities are print and display attacks, which anyone can carry out today.
    • How far to defend depends on the use case. Work backward from who gains, and how much, if impersonation succeeds.
    • Evaluate defenses with numbers such as APCER and BPCER, together with their test conditions — not with the words “it blocks attacks.”

    To check item by item how far your system should go → Face Anti-Spoofing Design Checklist: 12 Items to Review Before Production

  • We Built Face Recognition with OpenCV — and a Printed Photo Got Right Through (C++)

    Suppose you have built a face recognition pipeline using nothing but OpenCV’s FaceDetectorYN and FaceRecognizerSF classes, with the YuNet (face detection) and SFace (face recognition) models from the OpenCV Zoo. The enrolled user is accepted, other people are rejected, and everything works as expected.

    Now, what happens if the thing in front of the camera is not the enrolled user, but a printed photo of the enrolled user’s face?

    Short answer: it gets through. With an ordinary color printout, the cosine similarity clears the match threshold. Holding up a smartphone that shows the same photo works just as well.

    We have measured this behavior many times while developing and evaluating our liveness detection technology at Swallow Incubate. The code below is a single file: download the two ONNX models from the OpenCV Zoo (face_detection_yunet_2023mar.onnx and face_recognition_sface_2021dec.onnx), and you can reproduce it with your own face. We used OpenCV 4.x (the 2023mar YuNet model requires OpenCV 4.8 or later).


    The experiment

    We create a feature vector from an enrollment image, then keep matching whatever face appears in the camera feed against it.

    Case What is in front of the camera
    1 The enrolled person (live)
    2 A printed photo of the enrolled person’s face
    3 A smartphone screen showing the enrolled person’s face

    Code (C++)

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    int main()
    {
        auto detector = cv::FaceDetectorYN::create(
            "face_detection_yunet_2023mar.onnx", "", cv::Size(320, 320));
        auto recognizer = cv::FaceRecognizerSF::create(
            "face_recognition_sface_2021dec.onnx", "");
    
        // Build a feature vector from the enrollment image (a frontal photo of the user)
        cv::Mat enroll = cv::imread("enroll.jpg");
        if (enroll.empty()) {
            std::cerr << "Cannot read enroll.jpg" << std::endl;
            return -1;
        }
        detector->setInputSize(enroll.size());
        cv::Mat facesEnroll;
        detector->detect(enroll, facesEnroll);
        if (facesEnroll.rows < 1) {
            std::cerr << "No face found in the enrollment image" << std::endl;
            return -1;
        }
        cv::Mat alignedE, featEnroll;
        recognizer->alignCrop(enroll, facesEnroll.row(0), alignedE);
        recognizer->feature(alignedE, featEnroll);
        featEnroll = featEnroll.clone();
    
        // Keep matching "whatever" is in front of the camera
        cv::VideoCapture cap(0);
        if (!cap.isOpened()) {
            std::cerr << "Cannot open the camera" << std::endl;
            return -1;
        }
        cv::Mat frame;
        while (cap.read(frame)) {
            detector->setInputSize(frame.size());
            cv::Mat faces;
            detector->detect(frame, faces);
            if (faces.rows > 0) {
                cv::Mat aligned, feat;
                recognizer->alignCrop(frame, faces.row(0), aligned);
                recognizer->feature(aligned, feat);
                double score = recognizer->match(featEnroll, feat,
                                                 cv::FaceRecognizerSF::DisType::FR_COSINE);
                bool same = score >= 0.363;
                cv::Rect box(cv::Point((int)faces.at<float>(0, 0), (int)faces.at<float>(0, 1)),
                             cv::Size((int)faces.at<float>(0, 2), (int)faces.at<float>(0, 3)));
                cv::Scalar color = same ? cv::Scalar(0, 255, 0) : cv::Scalar(0, 0, 255);
                cv::rectangle(frame, box, color, 2);
                cv::putText(frame, same ? "MATCH" : "NO MATCH", cv::Point(20, 40),
                            cv::FONT_HERSHEY_SIMPLEX, 1.0, color, 2);
            }
            cv::imshow("face auth", frame);
            if (cv::waitKey(1) == 'q') break;
        }
        return 0;
    }
    

    The threshold of 0.363 is the default cosine-similarity threshold used in OpenCV’s face_detect sample (the sample’s L2-norm equivalent is 1.128).


    Results

    Case Result
    1. Enrolled person (live) MATCH (as expected)
    2. Printed photo MATCH — the score clears the 0.363 threshold
    3. Photo on a smartphone screen MATCH — same as above

    In cases 2 and 3, simply holding the paper or the phone where the face would be produces the green MATCH box. The halftone texture of the print, and the reflections and moiré on the phone screen, do not stop YuNet from detecting the face, and SFace extracts the enrolled person’s features without complaint.


    Why does it get through? It is not a bug — the model answers a different question

    This is neither an implementation mistake nor a flaw in the model.

    Face recognition answers one question: “Is this the same person as the one enrolled?” A printed photo and a phone screen both carry the enrolled person’s facial features, intact. So SFace correctly answers “yes, this is the same person’s face.” The system works exactly as designed — and authentication is defeated anyway.

    “Is the enrolled person actually present, right now?” is a completely different question. The technology that answers it is called liveness detection, or PAD (Presentation Attack Detection), and it requires its own dedicated classifier.

    Face recognition:   "Whose face is this?"     -> a photo of the user still matches (correct behavior)
    Liveness detection: "Live person or a fake?"  -> tells photos, screens, and masks apart (a separate technology)
    

    Is this a realistic threat?

    You might wonder whether anyone would really print a photo to defeat face recognition. But consider this: the attack material — a photo of the user’s face — is often published by the users themselves on social media and the web. The only tools needed are a printer or a phone. Print and screen attacks are therefore the cheapest attacks there are.

    That is why putting plain face recognition in front of any system where impersonation pays off — time and attendance, door access, identity verification — is risky. We break down the types of attacks, and how much defense each use case needs, in the next article:

    → Types of Presentation Attacks on Face Recognition — and Which Ones Are Realistic Threats

    Before you ship face recognition to production, see Face Anti-Spoofing Design Checklist: 12 Items to Review Before Production


    Summary

    • Face recognition built with OpenCV (YuNet + SFace) can be defeated with a printed photo or a smartphone screen showing the enrolled user. Anyone can reproduce this with the code above.
    • It is not a bug. Face recognition answers “whose face is this?” — it never claimed to answer “is the person actually here?”
    • If you use face recognition for authentication, you need liveness detection (PAD) as a separate component.
    • Photos of faces are easy to obtain from public sources. Print and screen attacks are the lowest-cost attacks and should be the first ones you defend against.