基于Opencv 的移动目标检测
实现流程:
(1)利用capture函数读取视频文件,利用capture.read(frame)从视频文件当中读取出来每一帧图像frame。
(2)利用cvtColor(frame, edges, CV_BGR2GRAY)函数,将每一帧图像转化为灰度图,便于之后进行二值化处理。
(3)利用GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5)函数,对得到的灰度图进行高斯模糊,以减少图像中的干扰噪声。
(4)遍历高斯模糊后图像的每一个灰度值,对灰度值进行限制并进行二值化处理。以此减小背景对检测目标的干扰。
(5)分别调用erode(edges, edges, ele)函数和dilate(edges, edges, ele)函数,通过设定不同的参数值,对图像进行腐蚀与膨胀操作。
(6)通过findContours函数,对图像轮廓进行检测。之后遍历每一个轮廓,通过boundingRect函数,找出轮廓最小外界矩形。最后对矩形框的大小进行限制,减少检测的错误率。
(7)将得到的矩形框标注在视频中的每一帧原图像上面,并进行输出。
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat edges, dstImage, ele;
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
VideoCapture capture("F:/Project_C++/video_detection/1.avi"); //打开视频文件
if (!capture.isOpened())
cout << "fail to open!" << endl;
long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
cout << "整个视频共" << totalFrameNumber << "帧" << endl;
long currentFrame = 0;
while (true)
{
Mat frame;
if (!capture.read(frame)) //读取每一帧
{
cout << "读取视频失败" << endl;
return -1;
}
currentFrame++; //帧计数
cout << "正在读取第" << currentFrame << "帧" << endl;
cvtColor(frame, edges, CV_BGR2GRAY); //转化为灰度图
GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5); //把edges里面的图像做高斯模糊
for (int i = 0; i<edges.rows; i++) //阈值二值化
for (int j = 0; j<edges.cols; j++)
if ((edges.at<unsigned char>(i, j) < 50) && (edges.at<unsigned char>(i, j) > 40))
edges.at<unsigned char>(i, j) = 255;
else edges.at<unsigned char>(i, j) = 0;
ele = getStructuringElement(MORPH_RECT, Size(3, 3)); //腐蚀操作
erode(edges, edges, ele);
ele = getStructuringElement(MORPH_RECT, Size(40, 60)); //膨胀操作
dilate(edges, edges, ele);
//imshow("读取视频", edges);
findContours(edges, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); //检测出轮廓
for (int index = 0; index >= 0; index = hierarchy[index][0])
{
//drawContours(edges, contours, index, Scalar(255, 255, 255), FILLED, 8, hierarchy);
Rect rect = boundingRect(contours[index]); //找出轮廓最小外界矩形
cout << "矩形框" << rect.width << endl;
if((rect.width > 180) && (rect.width < 400) && (rect.height < 600) && (rect.height > 400)) //限定矩形框的大小
rectangle(frame, rect, Scalar(0, 0, 255), 3); //在原图像上画出矩形
imshow("读取视频", frame); //显示每一帧
}
waitKey(30);
}
capture.release();
return 0;
}