设置运动检测的指定区域

时间:2019-01-07 03:08:02

标签: c# emgucv

我需要指定将要进行运动检测的区域。我要做的是计算通过某个区域的车辆数量。下面是我的代码:

private static void ProcessFrame(Mat backgroundFrame, int threshold, int erodeIterations, int dilateIterations)
{
    // Find difference between background (first) frame and current frame
    CvInvoke.AbsDiff(backgroundFrame, rawFrame, diffFrame);

    // Apply binary threshold to grayscale image (white pixel will mark difference)
    CvInvoke.CvtColor(diffFrame, grayscaleDiffFrame, ColorConversion.Bgr2Gray);
    CvInvoke.Threshold(grayscaleDiffFrame, binaryDiffFrame, threshold, 255, ThresholdType.Binary);

    // Remove noise with opening operation (erosion followed by dilation)
    CvInvoke.Erode(binaryDiffFrame, denoisedDiffFrame, null, new Point(-1, -1), erodeIterations, BorderType.Default, new MCvScalar(1));
    CvInvoke.Dilate(denoisedDiffFrame, denoisedDiffFrame, null, new Point(-1, -1), dilateIterations, BorderType.Default, new MCvScalar(1));

    rawFrame.CopyTo(finalFrame);
    //Rectangle rec = new Rectangle(100, 100, 100, 100);
    //finalFrame = crop_color_frame(rawFrame, rec);
    var img = crop_color_frame(denoisedDiffFrame, rec);
    DetectObject(denoisedDiffFrame, finalFrame);
}

static int vnum = 0;
private static void DetectObject(Mat detectionFrame, Mat displayFrame)
{
    using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
    {
        // Build list of contours
        CvInvoke.FindContours(detectionFrame, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

        // Selecting largest contour
        if (contours.Size > 0)
        {
            double maxArea = 0;
            int chosen = 0;
            for (int i = 0; i < contours.Size; i++)
            {
                VectorOfPoint contour = contours[i];

                double area = CvInvoke.ContourArea(contour);

                if (area > maxArea)
                {
                    maxArea = area;
                    chosen = i;
                }

            }

            // Draw on a frame
            MarkDetectedObject(displayFrame, contours[chosen], maxArea, contours.Size, maxArea);
        }
    }
}



private static void MarkDetectedObject(Mat frame, VectorOfPoint contour, double area, double contourSize, double maxArea)
        {
            // Getting minimal rectangle which contains the contour
            Rectangle box = CvInvoke.BoundingRectangle(contour);

            // Drawing contour and box around it
            CvInvoke.Polylines(frame, contour, true, drawingColor);
            CvInvoke.Rectangle(frame, box, drawingColor);

            // Write information next to marked object
            Point center = new Point(box.X + box.Width / 2, box.Y + box.Height / 2);
            Point center2 = new Point(box.Width, box.Height);

            var info = new string[] {
                $"Area: {area}",
                $"Position: {center.X}, {center.Y}"
            };
            Console.WriteLine($"X: {center.X} | Y: {center.Y} | Area: {area} | Count: {vnum} | Status: {vehicleState} | contour: {contour.Size}");



            switch (vehicleState)
            {
                case VehicleState.Entering:

                    if(_startCount)
                    {
                        //if(((maxArea > 15000 && maxArea <= 20000) && center.Y <= 120) || ((maxArea >= 5000 && maxArea < 10000) && center.Y >= 150))
                        if(center.Y >= 100 && maxArea > 20000)
                        {
                            CountVehicle();
                            vehicleState = VehicleState.Exiting;
                            _startCount = false;
                        }
                    }
                    break;
                case VehicleState.Exiting:
                    if (!_startCount)
                    {
                        //if(maxArea < 12000 && center.Y <= 120)
                        if(center.Y <= 130 && center.X <= 100 && maxArea <= 15000)
                        {
                            vehicleState = VehicleState.Entering;
                            _startCount = true;
                        }
                    }
                    break;
            }

            WriteMultilineText(frame, info, new Point(box.Right + 5, center.Y));
        }

目前,此代码可用于检测车辆,但我仅使用

  

如果(center.Y> = 100 && maxArea> 20000)条件开始对车辆进行计数

该方法的问题是,正在监视框架中的所有运动。这就是为什么我只需要设置一个特定区域的原因。

您能告诉我如何做吗?

1 个答案:

答案 0 :(得分:2)

您可以为输入图像设置ROI

squares[2]

下面是我在图像中绘制ROI的图像,您可以通过更改此行public static Mat crop_roi(Mat input_img) { Image<Gray, byte> img = input_img.ToImage<Gray, byte>(); double w = input_img.Width; double h = input_img.Height; Rectangle r = new Rectangle((int)(w * 0.2), (int)(h * 0.4), (int)(w * 0.6), (int)(h * 0.6)); Image<Gray, byte> output = img.Copy(r); return output.Mat; } //USE private static void DetectObject(Mat detectionFrame, Mat displayFrame) { using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { //set roi to the frame Mat roi = new Mat() roi = set_roi(detectionFrame); // Build list of contours CvInvoke.FindContours(roi , contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); // Selecting largest contour ... MarkDetectedObject(roi , contours[chosen], maxArea, contours.Size, maxArea); } 的参数来调整ROI

enter image description here