OpenCV摄像头图像采集、运动目标跟踪与人脸识别系统

OpenCV摄像头图像采集、运动目标跟踪与人脸识别系统

基于OpenCV的系统,实现了摄像头图像采集、运动目标跟踪和人脸识别功能。

#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <iostream>
#include <vector>
#include <map>
#include <deque>
#include <ctime>
#include <sstream>
#include <fstream>

using namespace cv;
using namespace cv::face;
using namespace std;

// 运动目标跟踪类
class MotionTracker {
public:
    MotionTracker() : trackerType("KCF") {}
    
    void initTracker(const Rect2d& roi, Mat& frame) {
        if (tracker) delete tracker;
        
        if (trackerType == "BOOSTING") tracker = TrackerBoosting::create();
        else if (trackerType == "MIL") tracker = TrackerMIL::create();
        else if (trackerType == "KCF") tracker = TrackerKCF::create();
        else if (trackerType == "TLD") tracker = TrackerTLD::create();
        else if (trackerType == "MEDIANFLOW") tracker = TrackerMedianFlow::create();
        else if (trackerType == "GOTURN") tracker = TrackerGOTURN::create();
        else if (trackerType == "MOSSE") tracker = TrackerMOSSE::create();
        else if (trackerType == "CSRT") tracker = TrackerCSRT::create();
        
        tracker->init(frame, roi);
    }
    
    bool updateTracker(Mat& frame, Rect2d& roi) {
        return tracker->update(frame, roi);
    }
    
    void setTrackerType(const string& type) {
        trackerType = type;
    }
    
private:
    Ptr<Tracker> tracker;
    string trackerType;
};

// 人脸识别系统类
class FaceRecognitionSystem {
public:
    FaceRecognitionSystem(const string& cascadePath, const string& recognizerPath = "") 
        : faceDetector(cascadePath), ready(false) {
        
        if (!recognizerPath.empty()) {
            model = LBPHFaceRecognizer::create();
            model->read(recognizerPath);
            ready = true;
        }
    }
    
    vector<Rect> detectFaces(Mat& frame) {
        Mat gray;
        cvtColor(frame, gray, COLOR_BGR2GRAY);
        equalizeHist(gray, gray);
        
        vector<Rect> faces;
        faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(100, 100));
        return faces;
    }
    
    void trainRecognizer(const vector<Mat>& images, const vector<int>& labels) {
        model = LBPHFaceRecognizer::create();
        model->train(images, labels);
        ready = true;
    }
    
    int recognizeFace(Mat& faceROI) {
        if (!ready) return -1;
        
        Mat gray;
        if (faceROI.channels() == 3) {
            cvtColor(faceROI, gray, COLOR_BGR2GRAY);
        } else {
            gray = faceROI.clone();
        }
        
        equalizeHist(gray, gray);
        int predictedLabel = -1;
        double confidence = 0.0;
        model->predict(gray, predictedLabel, confidence);
        
        // 置信度阈值,低于此值认为是未知人脸
        if (confidence > 80.0) return -1;
        
        return predictedLabel;
    }
    
    void saveModel(const string& path) {
        if (ready) model->write(path);
    }
    
private:
    CascadeClassifier faceDetector;
    Ptr<LBPHFaceRecognizer> model;
    bool ready;
};

// 运动检测类
class MotionDetector {
public:
    MotionDetector(float threshold = 30.0, int history = 500, float varThreshold = 16.0) 
        : historySize(history), varThreshold(varThreshold), threshold(threshold) {
        
        pMOG2 = createBackgroundSubtractorMOG2(historySize, varThreshold, true);
        pMOG2->setDetectShadows(false);
    }
    
    Mat detectMotion(Mat& frame) {
        Mat fgMask;
        pMOG2->apply(frame, fgMask);
        
        // 二值化
        threshold(fgMask, fgMask, threshold, 255, THRESH_BINARY);
        
        // 形态学操作去除噪声
        Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
        morphologyEx(fgMask, fgMask, MORPH_OPEN, kernel);
        morphologyEx(fgMask, fgMask, MORPH_CLOSE, kernel);
        
        return fgMask;
    }
    
private:
    Ptr<BackgroundSubtractorMOG2> pMOG2;
    int historySize;
    float varThreshold;
    float threshold;
};

// 主应用程序类
class SurveillanceApp {
public:
    SurveillanceApp(const string& faceCascadePath, const string& faceRecognizerPath = "") 
        : capture(0), motionDetector(30.0, 500, 16.0), faceSystem(faceCascadePath, faceRecognizerPath),
          trackingActive(false), recording(false), frameCount(0), fps(0), startTime(clock()) {
        
        if (!capture.isOpened()) {
            cerr << "ERROR: Could not open camera" << endl;
            exit(1);
        }
        
        // 初始化跟踪器
        motionTracker.setTrackerType("KCF");
        
        // 创建窗口
        namedWindow("Surveillance System", WINDOW_NORMAL);
        resizeWindow("Surveillance System", 1280, 720);
        
        // 创建控制面板
        createControlPanel();
        
        // 初始化变量
        prevFrame = Mat::zeros(480, 640, CV_8UC3);
    }
    
    void run() {
        while (true) {
            // 读取帧
            capture >> frame;
            if (frame.empty()) break;
            
            // 更新FPS
            updateFPS();
            
            // 处理帧
            processFrame();
            
            // 显示结果
            displayResults();
            
            // 处理键盘输入
            handleKeyPress();
        }
        
        // 清理
        if (recording) {
            videoWriter.release();
        }
        capture.release();
        destroyAllWindows();
    }
    
private:
    void processFrame() {
        // 运动检测
        Mat motionMask = motionDetector.detectMotion(frame);
        
        // 运动目标检测
        vector<Rect> motionROIs;
        if (trackingActive) {
            // 更新跟踪器
            Rect2d trackedROI;
            if (motionTracker.updateTracker(frame, trackedROI)) {
                motionROIs.push_back(Rect(trackedROI));
            } else {
                trackingActive = false;
            }
        } else {
            // 检测新运动目标
            detectMotionROIs(motionMask, motionROIs);
        }
        
        // 人脸检测
        vector<Rect> faces = faceSystem.detectFaces(frame);
        vector<int> faceLabels;
        vector<string> faceNames;
        
        // 人脸识别
        for (const Rect& face : faces) {
            Mat faceROI = frame(face);
            int label = faceSystem.recognizeFace(faceROI);
            faceLabels.push_back(label);
            
            if (label == -1) {
                faceNames.push_back("Unknown");
            } else {
                ostringstream oss;
                oss << "Person " << label;
                faceNames.push_back(oss.str());
            }
        }
        
        // 更新跟踪目标
        if (!trackingActive && !motionROIs.empty()) {
            // 选择最大的运动目标
            auto maxIt = max_element(motionROIs.begin(), motionROIs.end(), 
                [](const Rect& a, const Rect& b) { return a.area() < b.area(); });
            motionTracker.initTracker(*maxIt, frame);
            trackingActive = true;
        }
        
        // 存储处理结果
        processedFrame = frame.clone();
        currentMotionMask = motionMask;
        currentMotionROIs = motionROIs;
        currentFaces = faces;
        currentFaceLabels = faceLabels;
        currentFaceNames = faceNames;
    }
    
    void detectMotionROIs(Mat& motionMask, vector<Rect>& rois) {
        // 查找轮廓
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
        findContours(motionMask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
        
        // 过滤小区域
        for (const auto& contour : contours) {
            double area = contourArea(contour);
            if (area > 500) { // 最小面积阈值
                rois.push_back(boundingRect(contour));
            }
        }
    }
    
    void displayResults() {
        Mat display = processedFrame.clone();
        
        // 绘制运动目标
        for (const Rect& roi : currentMotionROIs) {
            rectangle(display, roi, Scalar(0, 0, 255), 2);
            putText(display, "Moving Object", Point(roi.x, roi.y - 5), 
                    FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);
        }
        
        // 绘制人脸
        for (size_t i = 0; i < currentFaces.size(); i++) {
            rectangle(display, currentFaces[i], Scalar(0, 255, 0), 2);
            putText(display, currentFaceNames[i], 
                    Point(currentFaces[i].x, currentFaces[i].y - 5), 
                    FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1);
        }
        
        // 显示FPS
        putText(display, format("FPS: %.2f", fps), Point(10, 30), 
                FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 255, 0), 2);
        
        // 显示状态
        string status = "Status: ";
        status += trackingActive ? "Tracking" : "Searching";
        putText(display, status, Point(10, 60), 
                FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 255, 255), 2);
        
        // 显示录制状态
        if (recording) {
            putText(display, "RECORDING", Point(display.cols - 150, 30), 
                    FONT_HERSHEY_SIMPLEX, 0.7, Scalar(0, 0, 255), 2);
        }
        
        // 显示控制面板
        displayControlPanel(display);
        
        // 显示结果
        imshow("Surveillance System", display);
        
        // 录制视频
        if (recording) {
            videoWriter.write(display);
        }
    }
    
    void createControlPanel() {
        // 创建控制面板窗口
        namedWindow("Control Panel", WINDOW_NORMAL);
        resizeWindow("Control Panel", 400, 300);
        
        // 创建按钮
        createButton("Start Tracking", Point(20, 30), [&]() { 
            if (!currentMotionROIs.empty()) {
                motionTracker.initTracker(currentMotionROIs[0], frame);
                trackingActive = true;
            }
        });
        
        createButton("Stop Tracking", Point(20, 70), [&]() { 
            trackingActive = false;
        });
        
        createButton("Start Recording", Point(20, 110), [&]() { 
            startRecording();
        });
        
        createButton("Stop Recording", Point(20, 150), [&]() { 
            stopRecording();
        });
        
        createButton("Save Snapshot", Point(20, 190), [&]() { 
            saveSnapshot();
        });
        
        createButton("Exit", Point(20, 230), [&]() { 
            running = false;
        });
    }
    
    void createButton(const string& text, Point pos, function<void()> action) {
        // 在实际实现中,这里会创建按钮并绑定事件
        // 为简化,我们只存储按钮信息
        buttons.push_back({text, pos, action});
    }
    
    void displayControlPanel(Mat& display) {
        // 在实际实现中,这里会绘制控制面板
        // 为简化,我们只显示一个简单的状态栏
        rectangle(display, Point(0, display.rows - 100), Point(display.cols, display.rows), 
                 Scalar(50, 50, 50), FILLED);
        
        putText(display, "Controls: [S] Start Tracking, [T] Stop Tracking, [R] Record, [P] Snapshot, [Q] Quit", 
                Point(10, display.rows - 70), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255), 1);
    }
    
    void startRecording() {
        if (recording) return;
        
        ostringstream oss;
        time_t now = time(0);
        tm* ltm = localtime(&now);
        oss << "recording_" 
            << (ltm->tm_year + 1900) << "-" 
            << (ltm->tm_mon + 1) << "-" 
            << ltm->tm_mday << "_" 
            << ltm->tm_hour << "-" 
            << ltm->tm_min << "-" 
            << ltm->tm_sec << ".avi";
        
        int fourcc = VideoWriter::fourcc('M', 'J', 'P', 'G');
        videoWriter.open(oss.str(), fourcc, 20.0, Size(frame.cols, frame.rows), true);
        
        if (videoWriter.isOpened()) {
            recording = true;
            cout << "Started recording: " << oss.str() << endl;
        } else {
            cerr << "Failed to start recording" << endl;
        }
    }
    
    void stopRecording() {
        if (recording) {
            videoWriter.release();
            recording = false;
            cout << "Recording stopped" << endl;
        }
    }
    
    void saveSnapshot() {
        ostringstream oss;
        time_t now = time(0);
        tm* ltm = localtime(&now);
        oss << "snapshot_" 
            << (ltm->tm_year + 1900) << "-" 
            << (ltm->tm_mon + 1) << "-" 
            << ltm->tm_mday << "_" 
            << ltm->tm_hour << "-" 
            << ltm->tm_min << "-" 
            << ltm->tm_sec << ".jpg";
        
        imwrite(oss.str(), processedFrame);
        cout << "Snapshot saved: " << oss.str() << endl;
    }
    
    void updateFPS() {
        frameCount++;
        clock_t now = clock();
        double elapsed = (double)(now - startTime) / CLOCKS_PER_SEC;
        
        if (elapsed > 1.0) {
            fps = frameCount / elapsed;
            frameCount = 0;
            startTime = now;
        }
    }
    
    void handleKeyPress() {
        char key = (char)waitKey(1);
        switch (key) {
            case 'q':
            case 27: // ESC
                running = false;
                break;
            case 's':
                if (!currentMotionROIs.empty()) {
                    motionTracker.initTracker(currentMotionROIs[0], frame);
                    trackingActive = true;
                }
                break;
            case 't':
                trackingActive = false;
                break;
            case 'r':
                if (recording) stopRecording();
                else startRecording();
                break;
            case 'p':
                saveSnapshot();
                break;
            case ' ':
                // 空格键切换跟踪/搜索模式
                trackingActive = !trackingActive;
                if (trackingActive && !currentMotionROIs.empty()) {
                    motionTracker.initTracker(currentMotionROIs[0], frame);
                }
                break;
        }
    }
    
    // 成员变量
    VideoCapture capture;
    Mat frame, prevFrame, processedFrame, currentMotionMask;
    vector<Rect> currentMotionROIs;
    vector<Rect> currentFaces;
    vector<int> currentFaceLabels;
    vector<string> currentFaceNames;
    MotionDetector motionDetector;
    MotionTracker motionTracker;
    FaceRecognitionSystem faceSystem;
    bool trackingActive;
    bool recording;
    int frameCount;
    double fps;
    clock_t startTime;
    bool running;
    VideoWriter videoWriter;
    
    // 控制面板相关
    struct Button { string text; Point pos; function<void()> action; };
    vector<Button> buttons;
};

int main(int argc, char** argv) {
    // 加载人脸检测器和识别器
    string faceCascadePath = "haarcascade_frontalface_default.xml";
    string faceRecognizerPath = ""; // 如果有预训练模型,可以指定路径
    
    // 检查命令行参数
    if (argc > 1) {
        faceCascadePath = argv[1];
    }
    if (argc > 2) {
        faceRecognizerPath = argv[2];
    }
    
    // 创建并运行应用
    SurveillanceApp app(faceCascadePath, faceRecognizerPath);
    app.run();
    
    return 0;
}

系统功能与特点

核心功能

  1. 实时视频采集:从摄像头捕获实时视频流
  2. 运动目标检测:使用背景减除算法检测运动物体
  3. 目标跟踪:集成多种跟踪算法(KCF、MIL、CSRT等)
  4. 人脸检测:使用Haar级联分类器检测人脸
  5. 人脸识别:使用LBPH算法进行人脸识别
  6. 视频录制:支持实时录制视频
  7. 快照功能:保存当前帧为图像文件
  8. 性能监控:实时显示FPS和处理状态

系统特点

  1. 多算法集成:支持多种目标跟踪算法
  2. 模块化设计:各功能模块解耦,便于扩展
  3. 实时处理:优化处理流程,确保实时性能
  4. 用户友好界面:直观的控制面板和状态显示
  5. 灵活配置:支持命令行参数配置
  6. 数据持久化:支持模型保存和加载

技术实现细节

1. 运动目标检测

使用MOG2背景减除算法:

Ptr<BackgroundSubtractorMOG2> pMOG2 = createBackgroundSubtractorMOG2(500, 16.0, true);
pMOG2->apply(frame, fgMask);

2. 目标跟踪

支持多种跟踪算法:

// 创建KCF跟踪器
Ptr<Tracker> tracker = TrackerKCF::create();
tracker->init(frame, roi);
bool success = tracker->update(frame, roi);

3. 人脸检测

使用Haar级联分类器:

CascadeClassifier faceDetector;
faceDetector.load("haarcascade_frontalface_default.xml");
faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(100, 100));

4. 人脸识别

使用LBPH算法:

Ptr<LBPHFaceRecognizer> model = LBPHFaceRecognizer::create();
model->train(images, labels);
int label = model->predict(faceROI);

参考代码 OPENCV基于摄像头图像采集运动目标跟踪及人脸识别技术 www.youwenfan.com/contentcns/122471.html

系统优化建议

  1. 性能优化

    // 使用GPU加速
    cv::cuda::GpuMat d_frame, d_gray;
    d_frame.upload(frame);
    cv::cuda::cvtColor(d_frame, d_gray, COLOR_BGR2GRAY);
    
  2. 多目标跟踪

    // 使用SORT或DeepSORT算法
    vector<STrack> tracks = sort.update(detections);
    
  3. 深度学习集成

    // 使用DNN模块进行人脸检测
    Net net = readNetFromTensorflow("opencv_face_detector_uint8.pb", 
                                   "opencv_face_detector.pbtxt");
    
  4. 光照归一化

    // 使用CLAHE增强对比度
    Ptr<CLAHE> clahe = createCLAHE(2.0, Size(8, 8));
    clahe->apply(gray, enhancedGray);
    
  5. 阴影处理

    // 在HSV空间处理阴影
    Mat hsv;
    cvtColor(frame, hsv, COLOR_BGR2HSV);
    vector<Mat> channels;
    split(hsv, channels);
    // 使用亮度通道进行阴影检测
    

使用说明

系统要求

编译与运行

# 安装依赖
sudo apt-get install libopencv-dev

# 编译命令
g++ -std=c++11 surveillance_system.cpp -o surveillance_system `pkg-config --cflags --libs opencv4`

# 运行程序
./surveillance_system

控制按键

参数调整

  1. 运动检测灵敏度

    MotionDetector motionDetector(30.0, 500, 16.0); // 阈值, 历史长度, 方差阈值
    
  2. 跟踪算法选择

    motionTracker.setTrackerType("CSRT"); // 可选: BOOSTING, MIL, KCF, TLD, MEDIANFLOW, GOTURN, MOSSE, CSRT
    
  3. 人脸检测参数

    faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(100, 100));
    // 参数: 缩放因子, 邻近数, 标志, 最小尺寸
    

扩展功能

  1. 多摄像头支持

    vector<VideoCapture> captures;
    for (int i = 0; i < numCameras; i++) {
        captures.push_back(VideoCapture(i));
    }
    
  2. 运动历史增强

    Ptr<MotionHistory> mh = createMotionHistory(/* 参数 */);
    mh->update(motionMask);
    
  3. 行为分析

    // 分析目标运动模式
    enum Behavior { STATIONARY, MOVING, APPROACHING, LEAVING };
    Behavior analyzeBehavior(const vector<Point>& trajectory);
    
  4. 云台控制

    // 根据目标位置控制摄像头
    void controlPTZ(int pan, int tilt, int zoom);
    
  5. 报警系统

    // 检测到异常时触发报警
    void triggerAlarm(const string& reason);
    

实际部署建议

  1. 硬件选择

    • 高分辨率摄像头(1080p或更高)
    • 专用GPU(用于深度学习模型)
    • 充足的内存和存储空间
  2. 环境适应

    • 室内:使用广角镜头
    • 室外:使用变焦镜头和防护罩
    • 低光照:添加红外照明
  3. 隐私保护

    • 匿名化处理敏感数据
    • 符合GDPR等隐私法规
    • 提供数据访问控制
  4. 系统监控

    • 实现心跳机制
    • 资源使用监控
    • 自动故障恢复
  5. 用户界面

    • 开发Web管理界面
    • 提供移动端应用
    • 实现多语言支持

专注于matlab/simulink,电子电路,编程