1.基本步骤
- 灰度处理
- 帧差处理
- 二值化处理
- 图像降噪
- 提取关键点
- 绘制识别框
2. 实现
代码
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
void MoveObjDetect(cv::Mat& frontFrame, cv::Mat& afterFrame, std::vector<cv::Rect>& detectResult)
{
cv::Mat diff;
//1 灰度处理 目的 RGB三通道转灰度单通道 压缩到原图片三分之一大小
Mat frontGray, afterGray;
cv::cvtColor(frontFrame, frontGray, CV_RGB2GRAY);
cv::cvtColor(afterFrame, afterGray, CV_RGB2GRAY);
//imshow("frontGray",frontGray);
//imshow("afterGray",afterGray);
//2 帧差处理 目的 找到帧与帧之间的差异(正在运动的物体)
cv::absdiff(frontGray, afterGray, diff);
//imshow("diff",diff);
//3 二值化处理 目的 将灰度图继续识别转换为黑白分明的图像
cv::threshold(diff, diff, 25, 255, CV_THRESH_BINARY);
//imshow("threshold",diff);
//4 图像降噪
//4-1 腐蚀处理 目的 去除白色噪点
Mat element = cv::getStructuringElement(MORPH_RECT, Size(1, 1));//小于3*3方块的白色噪点都会被腐蚀
cv::erode(diff, diff, element);
imshow("erode",diff);
//4-2 膨胀 目的 把白色区域变大
Mat element2 = cv::getStructuringElement(MORPH_RECT, Size(20, 20));
cv::dilate(diff, diff, element2);
//imshow("dilate",diff);
//5 提取关键点
//5-1 查找特征点
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(diff, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
//5-2 提取关键点
//5-3 确定下四个点来用于框选目标物体
int num = contours.size();
for (int i = 0; i < num; i++)
{
vector<cv::Point> c_poly(contours[i].size());
cv::approxPolyDP(Mat(contours[i]), c_poly, 3, true);
//多边拟合
cv::Rect rect;
rect = cv::boundingRect(Mat(c_poly));
detectResult.push_back(rect);
}
}
int main()
{
cv::VideoCapture capture("rtsp://192.168.6.27/0/0/0");
cv::Mat img;
int rate = capture.get(CV_CAP_PROP_FPS);
int delay = 1000 / rate;
cv::Mat lastFrame;
cv::namedWindow("img", WINDOW_NORMAL);
while (true) {
bool ret = capture.read(img);
if (!ret) {
std::cout << "read video failed" << std::endl;
break;
}
//动目标检测
if (lastFrame.empty()) lastFrame = img.clone();
std::vector<cv::Rect> detectResult;
MoveObjDetect(lastFrame, img, detectResult);
lastFrame = img.clone();
//绘制识别框
for (auto& rect : detectResult)
{
//绘制矩形
cv::rectangle(img, cv::Point(rect.x, rect.y), cv::Point(rect.x + rect.width,
(rect.y + rect.height)), cv::Scalar(0, 255, 0), 2);
}
cv::imshow("img", img);
cv::waitKey(delay);
if (!capture.grab())
{
break;
}
}
capture.release();
return 0;
}