相邻帧差检测:优点是运算快速,实时性高,缺点是无法应对光照的突变,物体间一般具有空洞。
三帧差检测:在一定程度上优化了运动物体双边,粗轮廓的现象,相比之下,三帧差法比相邻帧差法更适用于物体移动速度较快的情况。
#include <opencv2/opencv.hpp>/*** @brief diff2_detec 相邻帧差运动目标检测* @param gray_pre 输入:前一帧图像(gray)* @param gray_now 输入:当前帧图像(gray)* @return 输出:图像是否为全黑,全黑返回false,非全黑返回true*/
bool diff2_detection(cv::Mat gray_pre, cv::Mat gray_now)
{cv::Mat diff;cv::absdiff(gray_pre, gray_now, diff);threshold(diff, diff, 0, 255, cv::THRESH_OTSU); //自适应阈值化// 形态学操作cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(8, 8));cv::morphologyEx(diff, diff, cv::MORPH_OPEN, kernel);// 显示结果cv::imshow("Output", diff);cv::waitKey(100);if(mean(diff).val[0] > 0.01) // 计算差分图像灰度平均值{return true;}else{return false;}
}/*** @brief diff3_detec 三帧差运动目标检测* @param gray_pre 输入:前一帧图像(gray)* @param gray_now 输入:当前帧图像(gray)* @param gray_next 输入:后一帧图像(gray)* @return 输出:图像是否为全黑,全黑返回false,非全黑返回true*/
bool diff3_detection(cv::Mat gray_pre, cv::Mat gray_now, cv::Mat gray_next)
{cv::Mat diff_pre, diff_next, diff;// 计算帧差cv::absdiff(gray_pre, gray_now, diff_pre);cv::absdiff(gray_now, gray_next, diff_next);threshold(diff_pre, diff_pre, 0, 255, cv::THRESH_OTSU); //自适应阈值化threshold(diff_next, diff_next, 0, 255, cv::THRESH_OTSU); //自适应阈值化// 形态学操作cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(8, 8));cv::morphologyEx(diff_pre, diff_pre, cv::MORPH_OPEN, kernel);cv::morphologyEx(diff_next, diff_next, cv::MORPH_OPEN, kernel);cv::bitwise_and(diff_pre, diff_next, diff);//与操作// 显示结果cv::imshow("Output", diff);cv::waitKey(100);if(mean(diff).val[0] > 0.01) // 计算差分图像灰度平均值{return true;}else{return false;}
}int main()
{// 打开视频文件cv::VideoCapture cap("video.mp4");if (!cap.isOpened()){std::cout << "无法打开视频文件" << std::endl;return -1;}cv::Mat frame_pre, frame_now, frame_next;cv::Mat gray_pre, gray_now, gray_next;// 读取前三帧图像cap >> frame_pre;cv::cvtColor(frame_pre, gray_pre, cv::COLOR_BGR2GRAY);cap >> frame_now;cv::cvtColor(frame_now, gray_now, cv::COLOR_BGR2GRAY);cap >> frame_next;cv::cvtColor(frame_next, gray_next, cv::COLOR_BGR2GRAY);while (true){diff2_detection(gray_pre, gray_now);diff3_detection(gray_pre, gray_now, gray_next);// 更新帧gray_pre = gray_now.clone();gray_now = gray_next.clone();cap >> frame_next;if (frame_next.empty()) {break;}cv::cvtColor(frame_next, gray_next, cv::COLOR_BGR2GRAY);}// 释放资源cap.release();cv::destroyAllWindows();return 0;
}