Record
1、运动物体检测常用的方法:背景差法、帧差法、光流法;
2、背景差法使用原图像减去背景图像,得到前景图像,也就是运动目标;
3、帧差法根据相邻两帧或三帧图像,利用像素间的差异性,判断是否有运动目标;
4、背景差法与帧差法都进行图像减法,最常使用AbsDidd()
函数;
5、背景差法基本步骤:
6、帧差法基本步骤:
7、Else:
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.Util;
namespace lesson35
{
class Program
{
static void Main(string[] args)
{
图片背景差法检测运动物体
//Mat bgImg = CvInvoke.Imread("1.bmp");
//Mat fgImg = CvInvoke.Imread("55.bmp");
//CvInvoke.Imshow("bg", bgImg);
//CvInvoke.Imshow("fg", fgImg);
转换灰度图
//Mat gray1 = new Mat();
//Mat gray2 = new Mat();
//CvInvoke.CvtColor(bgImg, gray1, ColorConversion.Bgr2Gray);
//CvInvoke.CvtColor(fgImg, gray2, ColorConversion.Bgr2Gray);
图片做差
//Mat diff = new Mat();
//CvInvoke.AbsDiff(gray2, gray1, diff);
//CvInvoke.Imshow("diff", diff);
二值化
//CvInvoke.Threshold(diff, diff, 50, 255, ThresholdType.Binary);
//CvInvoke.Imshow("threshold", diff);
中值滤波或腐蚀去除噪点(中值滤波效果更好)
CvInvoke.MedianBlur(diff, diff, 3);
CvInvoke.Imshow("medianblur", diff);
//Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));
//CvInvoke.Erode(diff, diff, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
//CvInvoke.Imshow("erode", diff);
膨胀连通区域
//Mat element2 = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(11, 11), new Point(-1, -1));
//CvInvoke.Dilate(diff, diff, element2, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
//CvInvoke.Imshow("dilate", diff);
绘制最小外接矩形
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//CvInvoke.FindContours(diff, contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);
//for(int i = 0; i < contours.Size; i++)
//{
// Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);
// CvInvoke.Rectangle(fgImg, rect, new MCvScalar(0, 0, 255), 2);
//}
//CvInvoke.Imshow("result", fgImg);
//CvInvoke.WaitKey(0);
///视频背景差法检测运动物体
//VideoCapture cap = new VideoCapture("ball.avi");
//if (!cap.IsOpened)
//{
// Console.WriteLine("open the video failed..");
// return;
//}
//int count = 0;
//Mat bgImg = new Mat();
//Mat frame = new Mat();
//while (true)
//{
// cap.Read(frame);
// if (frame.IsEmpty)
// {
// Console.WriteLine("frame is empty...");
// break;
// }
// count++;
// if (1 == count)
// {
// bgImg = frame.Clone(); //取第一帧为背景
// }
// CvInvoke.Imshow("video", frame);
// Mat result = MoveDetect(bgImg, frame);
// CvInvoke.Imshow("move", result);
// if (CvInvoke.WaitKey(50) == 27)
// {
// break;
// }
//}
///图片帧差法检测运动物体
//Mat bgImg = CvInvoke.Imread("54.bmp");
//Mat fgImg = CvInvoke.Imread("55.bmp");
//CvInvoke.Imshow("bg", bgImg);
//CvInvoke.Imshow("fg", fgImg);
转换为灰度图
//Mat gray = new Mat();
//Mat gray2 = new Mat();
//CvInvoke.CvtColor(bgImg, gray, ColorConversion.Bgr2Gray);
//CvInvoke.CvtColor(fgImg, gray2, ColorConversion.Bgr2Gray);
做差
//Mat diff = new Mat();
//CvInvoke.AbsDiff(gray2, gray, diff);
//CvInvoke.Imshow("diff", diff);
二值化
//CvInvoke.Threshold(diff, diff, 45, 255, ThresholdType.Binary);
//CvInvoke.Imshow("threshold", diff);
//Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(1, 1), new Point(-1, -1));
//CvInvoke.Erode(diff, diff, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
//CvInvoke.Imshow("erode", diff);
膨胀连通区域
//Mat element2 = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(11, 11), new Point(-1, -1));
//CvInvoke.Dilate(diff, diff, element2, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
//CvInvoke.Imshow("dilate", diff);
绘制最小外接矩形
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//CvInvoke.FindContours(diff, contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);
//for (int i = 0; i < contours.Size; i++)
//{
// Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);
// CvInvoke.Rectangle(fgImg, rect, new MCvScalar(0, 0, 255), 2);
//}
//CvInvoke.Imshow("result", fgImg);
//CvInvoke.WaitKey(0);
///视频帧差法检测运动物体
VideoCapture cap = new VideoCapture("man.avi");
if(!cap.IsOpened)
{
Console.WriteLine("Open video failed..");
return;
}
int count = 0;
Mat bgImg = new Mat();
Mat frame = new Mat();
while(true)
{
cap.Read(frame);
if(frame.IsEmpty)
{
Console.WriteLine("frame is empty..");
break;
}
count++;
if (count == 1)
bgImg = frame.Clone();
Mat result = MoveDetect2(bgImg, frame);
CvInvoke.Imshow("move", result);
bgImg = frame.Clone(); //更新前一帧
if(CvInvoke.WaitKey(30)==27)
{
break;
}
}
}
static Mat MoveDetect2(Mat bgImg,Mat fgImg)
{
Mat result = fgImg.Clone();
Mat gray = new Mat();
Mat gray2 = new Mat();
CvInvoke.CvtColor(bgImg, gray, ColorConversion.Bgr2Gray);
CvInvoke.CvtColor(fgImg, gray2, ColorConversion.Bgr2Gray);
//做差
Mat diff = new Mat();
CvInvoke.AbsDiff(gray2, gray, diff);
CvInvoke.Imshow("diff", diff);
//二值化
CvInvoke.Threshold(diff, diff, 45, 255, ThresholdType.Binary);
CvInvoke.Imshow("threshold", diff);
//中值滤波
CvInvoke.MedianBlur(diff, diff, 5);
CvInvoke.Imshow("median blur", diff);
//膨胀
Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(9, 9), new Point(-1, -1));
CvInvoke.Dilate(diff, diff, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
CvInvoke.Imshow("dilate", diff);
//绘制轮廓矩形
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
CvInvoke.FindContours(diff, contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);
for (int i = 0; i < contours.Size; i++)
{
Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);
CvInvoke.Rectangle(result, rect, new MCvScalar(0, 0, 255), 2);
}
return result;
}
static Mat MoveDetect(Mat bgImg, Mat fgImg)
{
Mat result = fgImg.Clone();
Mat gray = new Mat();
Mat gray2 = new Mat();
CvInvoke.CvtColor(bgImg, gray, ColorConversion.Bgr2Gray);
CvInvoke.CvtColor(fgImg, gray2, ColorConversion.Bgr2Gray);
//做差
Mat diff = new Mat();
CvInvoke.AbsDiff(gray2, gray, diff);
CvInvoke.Imshow("diff", diff);
//二值化
CvInvoke.Threshold(diff, diff, 10, 255, ThresholdType.Binary);
CvInvoke.Imshow("threshold", diff);
//中值滤波
CvInvoke.MedianBlur(diff, diff, 5);
CvInvoke.Imshow("median blur", diff);
//膨胀
Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(9, 9), new Point(-1, -1));
CvInvoke.Dilate(diff, diff, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
CvInvoke.Imshow("dilate", diff);
//绘制轮廓矩形
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
CvInvoke.FindContours(diff, contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);
for(int i = 0; i < contours.Size; i++)
{
Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);
CvInvoke.Rectangle(result, rect, new MCvScalar(0, 0, 255), 2);
}
return result;
}
}
}
效果
1. 图片背景差法:
2. 视频背景差法检测运动物体: