Real-Time Facial Recognition System for Secure Access Control,C++

👤 Sharing: AI
```cpp
#include <iostream>
#include <opencv2/opencv.hpp> // Include OpenCV headers

using namespace std;
using namespace cv;

// Function to detect faces in a given frame using Haar cascades
vector<Rect> detectFaces(const Mat& frame, CascadeClassifier& faceCascade) {
    Mat grayFrame;
    cvtColor(frame, grayFrame, COLOR_BGR2GRAY); // Convert frame to grayscale

    vector<Rect> faces;
    faceCascade.detectMultiScale(grayFrame, faces, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(30, 30)); // Detect faces using Haar cascades

    return faces;
}

// Function to train a face recognizer with images and labels
Ptr<face::FaceRecognizer> trainRecognizer(const vector<Mat>& images, const vector<int>& labels) {
    if (images.empty() || labels.empty() || images.size() != labels.size()) {
        cerr << "Error: Invalid training data." << endl;
        return nullptr;
    }

    Ptr<face::FaceRecognizer> recognizer = face::LBPHFaceRecognizer::create(); // Create a LBPH face recognizer
    recognizer->train(images, labels); // Train the recognizer

    return recognizer;
}

int main() {
    // 1. Load Haar Cascade Classifier
    CascadeClassifier faceCascade;
    if (!faceCascade.load("haarcascade_frontalface_default.xml")) { // Replace with your Haar cascade XML file
        cerr << "Error loading face cascade." << endl;
        return -1;
    }

    // 2. Prepare Training Data (Replace with your actual data)
    vector<Mat> trainingImages;
    vector<int> trainingLabels;

    // Sample training data (replace with your own images and labels)
    // Assumes you have images named person1_1.jpg, person1_2.jpg, person2_1.jpg, etc. in the "training_data" folder
    for (int personId = 1; personId <= 2; ++personId) {
        for (int imageNum = 1; imageNum <= 2; ++imageNum) {
            string filename = "training_data/person" + to_string(personId) + "_" + to_string(imageNum) + ".jpg";
            Mat img = imread(filename, IMREAD_GRAYSCALE);  // Load in grayscale
            if (!img.empty()) {
                trainingImages.push_back(img);
                trainingLabels.push_back(personId); // Each person has a unique ID
            } else {
                cerr << "Error: Could not read image " << filename << endl;
            }
        }
    }

    // 3. Train the Face Recognizer
    Ptr<face::FaceRecognizer> faceRecognizer = trainRecognizer(trainingImages, trainingLabels);
    if (!faceRecognizer) {
        return -1;
    }

    // Optionally save the trained model (for later use)
    faceRecognizer->save("trained_model.yml");


    // 4. Open the Camera
    VideoCapture camera(0); // Use default camera (camera index 0)
    if (!camera.isOpened()) {
        cerr << "Error opening camera." << endl;
        return -1;
    }

    // 5. Real-time Face Recognition Loop
    Mat frame;
    string windowName = "Real-Time Facial Recognition";
    namedWindow(windowName, WINDOW_NORMAL); // Allow window resizing

    while (true) {
        camera >> frame; // Read a frame from the camera

        if (frame.empty()) {
            cerr << "Error: Empty frame received." << endl;
            break;
        }

        // Detect faces in the frame
        vector<Rect> faces = detectFaces(frame, faceCascade);

        // Recognize each detected face
        for (const auto& face : faces) {
            // Extract the face region
            Mat faceROI = frame(face);
            Mat grayFaceROI;
            cvtColor(faceROI, grayFaceROI, COLOR_BGR2GRAY);

            // Resize the face region to match the training images
            resize(grayFaceROI, grayFaceROI, Size(trainingImages[0].cols, trainingImages[0].rows));


            // Predict the label of the face
            int predictedLabel = -1;
            double confidence = 0.0; // Confidence of the prediction
            faceRecognizer->predict(grayFaceROI, predictedLabel, confidence);

            // Draw a rectangle around the face
            rectangle(frame, face, Scalar(0, 255, 0), 2);

            // Display the predicted label and confidence
            string labelText;
            if (predictedLabel != -1 && confidence < 100) { // You can adjust the confidence threshold
                labelText = "Person " + to_string(predictedLabel) + " (Confidence: " + to_string(confidence) + ")";
            } else {
                labelText = "Unknown";
            }

            putText(frame, labelText, Point(face.x, face.y - 10), FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 255, 0), 2); // Display label
        }

        // Display the resulting frame
        imshow(windowName, frame);

        // Check for user input (press 'q' to quit)
        char key = (char)waitKey(1);
        if (key == 'q') {
            break;
        }
    }

    // Release the camera and destroy the window
    camera.release();
    destroyAllWindows();

    return 0;
}
```

**Explanation:**

1.  **Include Headers:**
    *   `iostream`: For input/output operations (e.g., `cout`, `cerr`).
    *   `opencv2/opencv.hpp`:  This includes all the necessary OpenCV headers for image processing, face detection, and face recognition.  You'll need to install the OpenCV library.

2.  **Namespaces:**
    *   `using namespace std;`:  Avoids having to write `std::` before standard C++ elements.
    *   `using namespace cv;`:  Avoids having to write `cv::` before OpenCV elements.

3.  **`detectFaces` Function:**
    *   **Input:**  A `Mat` object representing a frame from the camera and a `CascadeClassifier` object.
    *   **Grayscale Conversion:** Converts the input frame to grayscale using `cvtColor(frame, grayFrame, COLOR_BGR2GRAY)`.  Haar cascades work best on grayscale images.
    *   **Face Detection:**  Uses `faceCascade.detectMultiScale(grayFrame, faces, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(30, 30))`.  This is the core face detection step.  Let's break down the parameters:
        *   `grayFrame`: The grayscale image to search for faces.
        *   `faces`:  A `vector<Rect>` that will store the bounding rectangles of the detected faces.
        *   `1.1`:  The scale factor.  How much the image size is reduced at each image scale.  Larger values speed up the detection but may miss some faces.
        *   `3`: The minimum number of neighbors a face rectangle should have to be considered a valid detection.  Higher values reduce false positives but may miss some faces.
        *   `0 | CASCADE_SCALE_IMAGE`:  Flags. `CASCADE_SCALE_IMAGE` means the image will be scaled down during detection.
        *   `Size(30, 30)`: The minimum possible object size. Objects smaller than that are ignored.  Adjust this based on the expected size of faces in your images.
    *   **Return Value:** Returns a `vector<Rect>` containing the bounding rectangles of the detected faces.

4.  **`trainRecognizer` Function:**
    *   **Input:** A `vector<Mat>` of training images (grayscale) and a `vector<int>` of corresponding labels (person IDs).
    *   **Error Handling:**  Checks if the training data is valid (not empty, same size vectors).
    *   **Recognizer Creation:** Creates a Local Binary Patterns Histograms (LBPH) face recognizer using `face::LBPHFaceRecognizer::create()`. LBPH is a simple and relatively fast face recognition algorithm.  Other algorithms (e.g., Eigenfaces, Fisherfaces) are available but may require more processing power or training data.
    *   **Training:** Trains the recognizer using `recognizer->train(images, labels)`. This learns the features associated with each person ID.
    *   **Return Value:**  Returns a `Ptr<face::FaceRecognizer>` (a smart pointer to the trained recognizer).

5.  **`main` Function:**
    *   **Load Haar Cascade:**
        *   Creates a `CascadeClassifier` object.
        *   Loads the Haar cascade XML file using `faceCascade.load("haarcascade_frontalface_default.xml")`.  **Important:** You *must* download a Haar cascade XML file.  These files contain the pre-trained data for detecting specific objects (in this case, faces).  A common source for these files is the OpenCV GitHub repository (look for `haarcascade_frontalface_default.xml`).  Make sure the path to the XML file is correct.
        *   Handles the error case if the cascade file cannot be loaded.
    *   **Prepare Training Data:**
        *   Creates `vector<Mat>` to store training images and `vector<int>` to store labels.
        *   **Crucially, this section is where you need to replace the placeholder code with your actual training data.**  The example code assumes you have a folder named "training\_data" with images named like "person1\_1.jpg", "person1\_2.jpg", "person2\_1.jpg", etc.  Load your images in a loop and add them to the `trainingImages` vector.  Assign a unique integer label to each person and add it to the `trainingLabels` vector. **All training images should be grayscale and ideally roughly the same size.**
    *   **Train the Face Recognizer:**
        *   Calls the `trainRecognizer` function to train the recognizer.
        *   Handles the error case if the training fails.
        *   **Save the Trained Model (Optional):**  `faceRecognizer->save("trained_model.yml");`  This line saves the trained model to a file.  This is very useful because you don't have to retrain the recognizer every time you run the program.  You can load the trained model later using `face::FaceRecognizer::load("trained_model.yml");`.  **Very important if you have a lot of training data.**
    *   **Open the Camera:**
        *   Creates a `VideoCapture` object to access the camera.  `VideoCapture camera(0);` opens the default camera (camera index 0).  If you have multiple cameras, you may need to change the index.
        *   Handles the error case if the camera cannot be opened.
    *   **Real-time Face Recognition Loop:**
        *   Creates a `Mat` object to store each frame from the camera.
        *   Creates a window to display the video feed.  `namedWindow(windowName, WINDOW_NORMAL);` allows you to resize the window.
        *   **`while (true)` loop:**  The main loop that continuously captures frames from the camera, detects faces, recognizes them, and displays the results.
            *   `camera >> frame;`: Reads a frame from the camera.
            *   Error handling if the frame is empty.
            *   `detectFaces(frame, faceCascade)`:  Calls the `detectFaces` function to detect faces in the current frame.
            *   **Face Recognition:**
                *   Iterates through each detected face (each `Rect` in the `faces` vector).
                *   `Mat faceROI = frame(face);`: Extracts the Region of Interest (ROI) corresponding to the detected face.  This is the part of the image containing the face.
                *   `cvtColor(faceROI, grayFaceROI, COLOR_BGR2GRAY);`: Converts the face ROI to grayscale.
                *   `resize(grayFaceROI, grayFaceROI, Size(trainingImages[0].cols, trainingImages[0].rows));`: **Very important:** Resizes the face ROI to the same size as the training images.  The face recognizer expects the input to be the same size as the images it was trained on.  Using the size of the first training image.
                *   `faceRecognizer->predict(grayFaceROI, predictedLabel, confidence);`:  Predicts the label of the face using the trained recognizer.  `predictedLabel` will contain the predicted person ID, and `confidence` will contain a measure of how confident the recognizer is in its prediction.
                *   `rectangle(frame, face, Scalar(0, 255, 0), 2);`: Draws a green rectangle around the detected face.
                *   **Display Label:**
                    *   Creates a `labelText` string to display the predicted label.
                    *   Checks if the predicted label is not -1 (meaning a face was recognized) *and* if the confidence is above a certain threshold (e.g., `confidence < 100`).  You'll need to experiment with the confidence threshold to find a value that works well for your setup.  Higher confidence thresholds will reduce false positives but may also cause the recognizer to miss some faces.
                    *   `putText(frame, labelText, Point(face.x, face.y - 10), FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 255, 0), 2);`:  Draws the `labelText` above the face rectangle.
            *   `imshow(windowName, frame);`:  Displays the resulting frame in the window.
            *   **Check for User Input:**
                *   `char key = (char)waitKey(1);`: Waits for 1 millisecond for a key press.
                *   `if (key == 'q')`: If the user presses 'q', the loop breaks, and the program exits.
        *   **Cleanup:** Releases the camera and destroys all windows.

**How to Compile and Run:**

1.  **Install OpenCV:**  You need to have the OpenCV library installed. The installation process varies depending on your operating system.  See the OpenCV documentation for instructions:  [https://opencv.org/](https://opencv.org/)

2.  **Download Haar Cascade XML:** Download the `haarcascade_frontalface_default.xml` file (or another appropriate Haar cascade) from the OpenCV GitHub repository (usually found in the `data/haarcascades` folder).  Place it in the same directory as your C++ code, or specify the correct path in the `faceCascade.load()` function.

3.  **Create a "training\_data" folder:**  Create a folder named "training\_data" in the same directory as your code.  Place your training images in this folder, named according to the pattern described in the code (e.g., "person1\_1.jpg", "person1\_2.jpg", etc.).

4.  **Compile:**  Use a C++ compiler (like g++) to compile the code.  You'll need to link the OpenCV libraries.  The exact command will depend on your system and how you installed OpenCV.  Here's an example g++ command:

    ```bash
    g++ -o facial_recognition facial_recognition.cpp `pkg-config --cflags --libs opencv4`
    ```

    *   Make sure you have `pkg-config` installed. If `opencv4` doesn't work, try `opencv`.

5.  **Run:** Execute the compiled program:

    ```bash
    ./facial_recognition
    ```

**Important Considerations and Improvements:**

*   **Training Data:** The quality and quantity of your training data are critical.  More training images per person will generally improve accuracy.  Make sure your training images are well-lit, frontal views of the faces.
*   **Lighting:** The performance of face recognition systems can be significantly affected by lighting conditions.  Try to control the lighting in your environment as much as possible.
*   **Haar Cascade Selection:** The `haarcascade_frontalface_default.xml` file is a good starting point, but you might need to experiment with other Haar cascades to find one that works best for your specific application and face profiles.  Consider using cascades trained for profile faces or other variations if your application requires it.
*   **Confidence Threshold:**  Adjust the confidence threshold in the `if (predictedLabel != -1 && confidence < 100)` condition to find a good balance between accuracy and false positives.
*   **Face Alignment:**  Consider implementing face alignment techniques to normalize the orientation and size of the faces before training and recognition.  This can significantly improve accuracy.  You can use OpenCV's `cv::estimateAffine2D` to align faces.
*   **More Robust Algorithms:**  Explore more advanced face recognition algorithms, such as deep learning-based methods (e.g., FaceNet, ArcFace), which generally offer much higher accuracy but require more computational resources and larger training datasets.  These algorithms are typically implemented using frameworks like TensorFlow or PyTorch.
*   **Thread Safety:** If you are developing a multi-threaded application, ensure that your OpenCV operations are thread-safe.
*   **Error Handling:** Add more robust error handling to handle various scenarios, such as camera disconnection, file errors, and invalid input data.
*   **User Interface:**  Consider adding a graphical user interface (GUI) to make the application more user-friendly.  Libraries like Qt or wxWidgets can be used to create GUIs.

This comprehensive explanation should give you a good understanding of how the code works and how to adapt it to your specific requirements. Remember to replace the placeholder training data with your own images and labels! Good luck!
👁️ Viewed: 3

Comments