检测到的所有移动物体中轮廓中找到面积最大的轮廓,并绘制这个轮廓的矩形框。
#include <opencv2/opencv.hpp>
#include <iostream>int main() {// 打开视频文件或摄像头cv::VideoCapture capture;capture.open("move3.mp4"); // 打开视频文件if (!capture.isOpened()) {std::cerr << "Error opening video stream or file" << std::endl;return -1;}// 读取第一帧作为背景模型cv::Mat background;capture >> background;if (background.empty()) {std::cerr << "Error reading background frame" << std::endl;return -1;}// 将背景转换为灰度图并进行高斯滤波以减少噪声cv::Mat backgroundGray;cv::cvtColor(background, backgroundGray, cv::COLOR_BGR2GRAY);cv::GaussianBlur(backgroundGray, backgroundGray, cv::Size(21, 21), 0);cv::Mat frame, grayFrame, diffFrame, thresholdFrame;while (true) {// 读取当前帧capture >> frame;if (frame.empty()) {break;}// 将当前帧转换为灰度图并进行高斯滤波cv::Mat grayFrame;cv::cvtColor(frame, grayFrame, cv::COLOR_BGR2GRAY);cv::GaussianBlur(grayFrame, grayFrame, cv::Size(21, 21), 0);// 计算当前帧与背景的差异cv::absdiff(backgroundGray, grayFrame, diffFrame);// 对差异图像进行阈值处理,将小的差异值设置为0,大的差异值设置为255cv::threshold(diffFrame, thresholdFrame, 25, 255, cv::THRESH_BINARY);// 使用形态学操作去除噪声cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));cv::morphologyEx(thresholdFrame, thresholdFrame, cv::MORPH_OPEN, kernel);// 找到轮廓std::vector<std::vector<cv::Point>> contours;cv::findContours(thresholdFrame, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);// 找到面积最大的轮廓double maxArea = 0;int maxAreaIndex = -1;for (size_t i = 0; i < contours.size(); ++i) {double area = cv::contourArea(contours[i]);if (area > maxArea) {maxArea = area;maxAreaIndex = i;}}// 在原始帧上绘制最大的矩形框if (maxAreaIndex != -1) {cv::Rect boundingRect = cv::boundingRect(contours[maxAreaIndex]);cv::rectangle(frame, boundingRect, cv::Scalar(0, 0, 255), 2);}// 显示结果cv::imshow("Frame", frame);cv::imshow("Threshold Frame", thresholdFrame);// 按下ESC键退出if (cv::waitKey(30) == 27) {break;}}// 释放资源并关闭窗口capture.release();cv::destroyAllWindows();return 0;
}
代码说明
-
背景初始化:
- 读取第一帧作为背景,并将其转换为灰度图,同时应用高斯滤波以减少噪声。
-
帧处理:
- 读取当前帧并将其转换为灰度图。
- 使用
cv::absdiff
计算当前帧与背景的差异。 - 应用阈值处理,将小的差异值设置为0,大的差异值设置为255。
- 使用形态学操作去除噪声。
-
轮廓检测:
- 使用
cv::findContours
找到所有运动物体的轮廓。 - 遍历所有轮廓,计算每个轮廓的面积,并找到面积最大的轮廓。
- 使用
-
绘制矩形框:
- 使用
cv::boundingRect
计算最大轮廓的边界矩形。 - 使用
cv::rectangle
在原始帧上绘制红色矩形框,标记面积最大的运动物体。
- 使用
-
结果显示:
- 显示原始帧和处理后的阈值帧。
注意事项
- 阈值调整:阈值可以根据实际场景进行调整,以提高检测的准确性。
- 性能优化:对于实时应用,可以考虑优化代码以提高处理速度。
- 背景更新:在实际应用中,背景可能会发生变化,因此可能需要定期更新背景模型。
通过以上修改,你的程序应该只会在检测到的运动物体中绘制面积最大的矩形框。