相邻帧差检测:优点是运算快速,实时性高,缺点是无法应对光照的突变,物体间一般具有空洞。
三帧差检测:在一定程度上优化了运动物体双边,粗轮廓的现象,相比之下,三帧差法比相邻帧差法更适用于物体移动速度较快的情况。
cpp
#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;
}