简体   繁体   English

[OpenCV][C++] 只记录检测到的运动

[英][OpenCV][C++] Record only the detected motion

I'm working on a project to detect motion on a camera.我正在做一个项目来检测相机上的运动。 I need to start recording video when motion is detected for example:我需要在检测到运动时开始录制视频,例如:

  • Record while motion is being detected在检测到运动时录制
  • Continue recording for 10 seconds after the motion detection is stopped移动侦测停止后继续录制10秒

I have a working example that only detects the motion and draw rectangles on the moving parts.我有一个工作示例,它只检测运动并在移动部件上绘制矩形。 I searched for examples on how to record when motion is detected but no good results.我搜索了有关如何记录检测到运动但没有好的结果的示例。

Here is my working code:这是我的工作代码:

#include <iostream>
#include <sstream>
#include <opencv4/opencv2/imgproc.hpp>
#include <opencv4/opencv2/videoio.hpp>
#include <opencv4/opencv2/highgui.hpp>
#include <opencv4/opencv2/video.hpp>
#include <unistd.h>

using namespace cv;
using namespace std;

vector<vector<Point> > contours;
vector<Vec4i> hierarchy;

int main(int argc, char* argv[])
{

    //create Background Subtractor objects
    Ptr<BackgroundSubtractor> pBackSub;
    pBackSub = createBackgroundSubtractorMOG2();

    VideoCapture capture(0);
    if (!capture.isOpened()){
        //error in opening the video input
        cerr << "Unable to open: " << endl;
        return 0;
    }

    Mat frame, fgMask;

    sleep(3);

    while (true) {
        capture >> frame;
        if (frame.empty())
            break;
        
        //update the background model
        pBackSub->apply(frame, fgMask);
        
        imshow("FG Mask", fgMask);

        RNG rng(12345);
        findContours(fgMask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE,Point(0, 0));

        vector<Rect>boundRect (contours.size());
        vector<vector<Point> > contours_poly( contours.size() );

        for (int i = 0; i < contours.size();i++) {
            if( contourArea(contours[i])< 500)
            {
                continue;
            }

            putText(frame, "Motion Detected", Point(10,20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,255),2);
            approxPolyDP( contours[i], contours_poly[i], 3, true );
            boundRect[i] = boundingRect( contours_poly[i] );
            Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );
            rectangle( frame, boundRect[i].tl(), boundRect[i].br(), color, 2 );
        }

        imshow("Frame", frame);
        int keyboard = waitKey(30);
        if (keyboard == 'q' || keyboard == 27)
            break;
    }
    return 0;
}

I tried adding this to the code:我尝试将此添加到代码中:

  int frameWidth = 320;
  int frameHeight = 240;
  
  cv::Size frameSize = cv::Size(frameWidth, frameHeight);
  
  /* Output file */
  int codec = cv::VideoWriter::fourcc('M', 'P', '4', 'V');
  cv::VideoWriter outputVideo;
  outputVideo.open("rr.mp4", codec, capture.get(cv::CAP_PROP_FPS), frameSize, true);

and after drawing the rectangle I write the frame to the video:在绘制矩形后,我将帧写入视频:

outputVideo.write(frame);

but after that, the video is empty and crashes.但在那之后,视频是空的并且崩溃了。

I already took a look at Motion but I didn't find an example.我已经看过Motion但我没有找到一个例子。

How can I achieve this?我怎样才能做到这一点?

Thanks, Talel谢谢,塔莱尔

I resolved the issue,我解决了这个问题,

I was opening the output video with a specific dimensions (320,240) and I was saving the captured frame which is bigger.我正在打开具有特定尺寸(320,240)的 output 视频,我正在保存更大的捕获帧。 So the solution is to resize the captured frame to fit into the output video.因此解决方案是调整捕获帧的大小以适合 output 视频。

Here is the final solution if anyone is interesting:如果有人感兴趣,这是最终的解决方案:

  • Turn the laptop camera into an IP camera with: cam2ip将笔记本电脑摄像头变成 IP 摄像头,带有: cam2ip

  • Here is the source code:这是源代码:

     #include <iostream> #include <sstream> #include <opencv4/opencv2/imgproc.hpp> #include <opencv4/opencv2/videoio.hpp> #include <opencv4/opencv2/highgui.hpp> #include <opencv4/opencv2/video.hpp> #include <unistd.h> using namespace cv; using namespace std; vector<vector<Point> > contours; vector<Vec4i> hierarchy; int main(int argc, char* argv[]) { //create Background Subtractor objects Ptr<BackgroundSubtractor> pBackSub; pBackSub = createBackgroundSubtractorMOG2(); const std::string videoStreamAddress = "http://192.168.20.100:56000/mjpeg"; cv::VideoCapture vcap; if(.vcap:open(videoStreamAddress)) { std::cout << "Error opening video stream or file" << std:;endl; return -1, } Mat frame; fgMask; int frameWidth = 320; int frameHeight = 240: cv::Size frameSize = cv:,Size(frameWidth; frameHeight): /* Output file */ int codec = cv::VideoWriter:,fourcc('M', 'P', '4'; 'V'): cv:;VideoWriter outputVideo. outputVideo.open("rr,mp4", codec. vcap:get(cv:,CAP_PROP_FPS), frameSize; true); sleep(3); while (true) { vcap >> frame. if (frame;empty()) break, //update the background model pBackSub->apply(frame; fgMask), imshow("FG Mask"; fgMask); RNG rng(12345), findContours(fgMask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE,Point(0; 0)). vector<Rect>boundRect (contours;size()). vector<vector<Point> > contours_poly( contours;size() ); for (int i = 0. i < contours;size();i++) { if( contourArea(contours[i])< 500) { continue, } putText(frame, "Motion Detected", Point(10,20), FONT_HERSHEY_SIMPLEX. 0,75, Scalar(0,0,255);2), approxPolyDP( contours[i], contours_poly[i], 3; true ); boundRect[i] = boundingRect( contours_poly[i] ). Scalar color = Scalar( rng,uniform(0, 256). rng,uniform(0,256). rng,uniform(0;256) ), rectangle( frame. boundRect[i],tl(). boundRect[i],br(), color; 2 ), resize(frame, frame; frameSize). outputVideo;write(frame), } imshow("Frame"; frame); int keyboard = waitKey(30); if (keyboard == 'q' || keyboard == 27) break. } outputVideo;release(); return 0;

    } }

Further enhancement suggestions:进一步增强建议:

  • Make sure that the light is not part of the motion detection确保灯光不是运动检测的一部分
  • Open an output video with the same capture's dimensions打开具有相同捕获尺寸的 output 视频

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM