现在位置: 首页 > OpenCV 教程 > 正文

C++ OpenCV 项目实战

OpenCV 项目实战是将理论知识应用于实际问题的过程。

通过项目实战,可以巩固 OpenCV 的使用技能,并解决现实中的计算机视觉问题。

以下是常见的 OpenCV 项目类型:

  1. 图像处理类项目:如图像滤镜、图像修复、图像增强等。

  2. 目标检测与跟踪类项目:如人脸检测、车牌识别、运动目标跟踪等。

  3. 深度学习类项目:如图像分类、目标检测、语义分割等。

  4. 视频处理类项目:如视频分析、实时视频处理、视频特效等。


简单项目

图像滤镜应用

图像滤镜是图像处理中的基础操作之一,通过应用不同的滤镜,可以改变图像的外观和风格。

OpenCV 提供了丰富的函数来实现各种图像滤镜效果。

灰度滤镜

灰度滤镜是将彩色图像转换为灰度图像的过程。灰度图像只有一个通道,每个像素的值表示亮度。

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("input.jpg");
    cv::Mat grayImage;
    cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
    cv::imwrite("gray_output.jpg", grayImage);
    return 0;
}

高斯模糊

高斯模糊是一种常用的模糊滤镜,它可以有效地去除图像中的噪声。

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("input.jpg");
    cv::Mat blurredImage;
    cv::GaussianBlur(image, blurredImage, cv::Size(15, 15), 0);
    cv::imwrite("blurred_output.jpg", blurredImage);
    return 0;
}

以下实例实现一个图像滤镜应用,支持多种滤镜效果(如灰度化、模糊、边缘检测等)。

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // 读取图像
    Mat image = imread("image.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 灰度化
    Mat gray;
    cvtColor(image, gray, COLOR_BGR2GRAY);

    // 高斯模糊
    Mat blurred;
    GaussianBlur(image, blurred, Size(15, 15), 0);

    // 边缘检测
    Mat edges;
    Canny(image, edges, 100, 200);

    // 显示结果
    imshow("Original Image", image);
    imshow("Gray Image", gray);
    imshow("Blurred Image", blurred);
    imshow("Edges", edges);

    // 保存结果
    imwrite("gray_image.jpg", gray);
    imwrite("blurred_image.jpg", blurred);
    imwrite("edges.jpg", edges);

    waitKey(0);
    return 0;
}

实时人脸检测

实时人脸检测是计算机视觉中的一个重要应用。

OpenCV 提供了预训练的 Haar 级联分类器,可以用于检测图像或视频中的人脸。

实现步骤:

  1. 加载 Haar 级联分类器模型。

  2. 打开摄像头或视频文件。

  3. 对每一帧进行人脸检测。

  4. 绘制检测结果并显示。

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // 加载 Haar 级联分类器
    CascadeClassifier faceCascade;
    if (!faceCascade.load("haarcascade_frontalface_default.xml")) {
        cout << "错误:无法加载 Haar 级联分类器!" << endl;
        return -1;
    }

    // 打开摄像头
    VideoCapture cap(0);
    if (!cap.isOpened()) {
        cout << "错误:无法打开摄像头!" << endl;
        return -1;
    }

    // 实时检测人脸
    Mat frame;
    while (true) {
        cap >> frame;
        if (frame.empty()) break;

        // 转换为灰度图像
        Mat gray;
        cvtColor(frame, gray, COLOR_BGR2GRAY);

        // 检测人脸
        vector<Rect> faces;
        faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, Size(30, 30));

        // 绘制检测结果
        for (const auto& face : faces) {
            rectangle(frame, face, Scalar(0, 255, 0), 2);
        }

        // 显示结果
        imshow("Face Detection", frame);

        // 按下 ESC 键退出
        if (waitKey(30) == 27) break;
    }

    // 释放资源
    cap.release();
    destroyAllWindows();

    return 0;
}

车牌识别

车牌识别是智能交通系统中的关键技术之一。

OpenCV 可以用于车牌检测和字符识别。

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("car.jpg");
    cv::Mat grayImage;
    cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);

    cv::CascadeClassifier plateCascade;
    plateCascade.load("haarcascade_russian_plate_number.xml");

    std::vector<cv::Rect> plates;
    plateCascade.detectMultiScale(grayImage, plates, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));

    for (const auto& plate : plates) {
        cv::rectangle(image, plate, cv::Scalar(0, 255, 0), 2);
    }

    cv::imwrite("plate_output.jpg", image);
    return 0;
}

复杂项目

基于 OpenCV 的 AR 应用

增强现实(AR)是一种将虚拟信息叠加到现实世界中的技术。

OpenCV 可以用于实现简单的 AR 应用,例如在图像上叠加虚拟物体。

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat image = cv::imread("background.jpg");
    cv::Mat overlay = cv::imread("overlay.png", cv::IMREAD_UNCHANGED);

    cv::resize(overlay, overlay, cv::Size(100, 100));

    cv::Mat roi = image(cv::Rect(50, 50, overlay.cols, overlay.rows));
    overlay.copyTo(roi, overlay);

    cv::imwrite("ar_output.jpg", image);
    return 0;
}

视频监控与运动检测

视频监控与运动检测是安全监控系统中的重要功能。OpenCV 可以用于检测视频中的运动物体。

实例

#include <opencv2/opencv.hpp>

int main() {
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        std::cerr << "Error opening video stream" << std::endl;
        return -1;
    }

    cv::Mat frame, prevFrame, diffFrame;
    cap >> prevFrame;
    cv::cvtColor(prevFrame, prevFrame, cv::COLOR_BGR2GRAY);

    while (true) {
        cap >> frame;
        if (frame.empty()) break;

        cv::Mat grayFrame;
        cv::cvtColor(frame, grayFrame, cv::COLOR_BGR2GRAY);

        cv::absdiff(grayFrame, prevFrame, diffFrame);
        cv::threshold(diffFrame, diffFrame, 30, 255, cv::THRESH_BINARY);

        cv::imshow("Motion Detection", diffFrame);
        if (cv::waitKey(1) == 27) break; // ESC key to exit

        prevFrame = grayFrame.clone();
    }

    cap.release();
    cv::destroyAllWindows();
    return 0;
}

多目标跟踪

多目标跟踪是计算机视觉中的一个复杂问题,涉及在视频中同时跟踪多个目标。OpenCV 提供了多种跟踪算法,例如 KCF、MIL 和 CSRT。

实例

#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>

int main() {
    cv::VideoCapture cap("video.mp4");
    if (!cap.isOpened()) {
        std::cerr << "Error opening video stream" << std::endl;
        return -1;
    }

    cv::Ptr<cv::MultiTracker> multiTracker = cv::MultiTracker::create();

    cv::Mat frame;
    cap >> frame;

    std::vector<cv::Rect> bboxes;
    cv::selectROIs("Tracking", frame, bboxes);

    for (const auto& bbox : bboxes) {
        multiTracker->add(cv::TrackerKCF::create(), frame, bbox);
    }

    while (true) {
        cap >> frame;
        if (frame.empty()) break;

        multiTracker->update(frame);

        for (const auto& bbox : multiTracker->getObjects()) {
            cv::rectangle(frame, bbox, cv::Scalar(255, 0, 0), 2);
        }

        cv::imshow("Multi-Object Tracking", frame);
        if (cv::waitKey(1) == 27) break; // ESC key to exit
    }

    cap.release();
    cv::destroyAllWindows();
    return 0;
}

深度学习类项目:目标检测(YOLO)

使用 YOLO 模型实现目标检测。

实现步骤:

  1. 加载 YOLO 模型和配置文件。

  2. 加载类别标签。

  3. 对输入图像进行预处理。

  4. 运行模型并解析检测结果。

  5. 绘制检测框并显示结果。

实例

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>

using namespace cv;
using namespace dnn;
using namespace std;

int main() {
    // 加载 YOLO 模型
    Net net = readNet("yolov3.weights", "yolov3.cfg");
    if (net.empty()) {
        cout << "错误:无法加载 YOLO 模型!" << endl;
        return -1;
    }

    // 加载类别标签
    ifstream classNamesFile("coco.names");
    vector<string> classNames;
    string className;
    while (getline(classNamesFile, className)) {
        classNames.push_back(className);
    }

    // 加载图像
    Mat image = imread("image.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 预处理图像
    Mat blob = blobFromImage(image, 1 / 255.0, Size(416, 416), Scalar(0, 0, 0), true, false);
    net.setInput(blob);

    // 前向传播
    vector<Mat> outs;
    net.forward(outs, net.getUnconnectedOutLayersNames());

    // 解析检测结果
    float confThreshold = 0.5; // 置信度阈值
    vector<int> classIds;
    vector<float> confidences;
    vector<Rect> boxes;
    for (const auto& output : outs) {
        for (int i = 0; i < output.rows; i++) {
            Mat scores = output.row(i).colRange(5, output.cols);
            Point classIdPoint;
            double confidence;
            minMaxLoc(scores, nullptr, &confidence, nullptr, &classIdPoint);
            if (confidence > confThreshold) {
                int centerX = static_cast<int>(output.at<float>(i, 0) * image.cols);
                int centerY = static_cast<int>(output.at<float>(i, 1) * image.rows);
                int width = static_cast<int>(output.at<float>(i, 2) * image.cols);
                int height = static_cast<int>(output.at<float>(i, 3) * image.rows);
                int left = centerX - width / 2;
                int top = centerY - height / 2;

                classIds.push_back(classIdPoint.x);
                confidences.push_back(static_cast<float>(confidence));
                boxes.push_back(Rect(left, top, width, height));
            }
        }
    }

    // 非极大值抑制
    float nmsThreshold = 0.4; // NMS 阈值
    vector<int> indices;
    NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);

    // 绘制检测结果
    for (int idx : indices) {
        Rect box = boxes[idx];
        rectangle(image, box, Scalar(0, 255, 0), 2);
        string label = format("%s: %.2f", classNames[classIds[idx]].c_str(), confidences[idx]);
        putText(image, label, Point(box.x, box.y - 10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2);
    }

    // 显示结果
    imshow("Object Detection", image);
    waitKey(0);

    return 0;
}

视频处理类项目:实时视频特效

实现一个实时视频特效应用,支持多种特效(如边缘检测、模糊、颜色反转等)。

实现步骤:

  1. 打开摄像头或视频文件。

  2. 对每一帧应用特效。

  3. 显示处理后的视频。

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    // 打开摄像头
    VideoCapture cap(0);
    if (!cap.isOpened()) {
        cout << "错误:无法打开摄像头!" << endl;
        return -1;
    }

    // 实时处理视频帧
    Mat frame, edges;
    while (true) {
        cap >> frame;
        if (frame.empty()) break;

        // 边缘检测
        Canny(frame, edges, 100, 200);

        // 显示结果
        imshow("Original Frame", frame);
        imshow("Edges", edges);

        // 按下 ESC 键退出
        if (waitKey(30) == 27) break;
    }

    // 释放资源
    cap.release();
    destroyAllWindows();

    return 0;
}