Background Subtraction - OpenCV(C++)
Updated:
Background Subtraction 해보기
Visual Studio 2017을 사용하였습니다.
Background Subtractor 이론에 대한 내용보다는 코딩 관련에 집중하여 포스팅하겠습니다.
1. Background Subtractor?
정의
- Static cameras 사용에서 foreground mask를 generate할 때 사용하는 기술
- Foreground mask
- 장면에서 움직이는 물체에 속하는 픽셀을 포함하는 2진 이미지
- Current frame과 background model 사이의 차를 구하여
Step
- Background Initialization
- Background Update
코드
#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
using namespace std;
const char* params
// { 인수 이름 | default value | 설명 }, default value는 인수를 입력하지 않았을 때 인수값 됨.
= "{ help h | | Print usage }"
"{ input | vtest.avi | Path to a video or a sequence of image }"
"{ algo | MOG2 | Background subtraction method (KNN, MOG2) }";
int main(int argc, char* argv[])
{
cv::CommandLineParser parser(argc, argv, params);
parser.about("This program shows how to use background subtraction methods provided by "
" OpenCV. You can process both videos and images.\n"); // help 메시지를 출력할 때 보이는 초반부의 설명 메시지를 설정할 수 있음
if (parser.has("help"))
{// has는 help인수가 입력되었는지 알기 위해 사용하는 함수. has("help") or has("h") or has("?")의 반환값이 true인 것을 확인하면 됨
//print help information
parser.printMessage(); // 각 인수에 대한 설명을 자동으로 생성하여 출력하는 method. 각 인수별로 지정한 설명들과 default value가 설명에 포함됨
}
//create Background Subtractor objects
cv::Ptr<cv::BackgroundSubtractor> pBackSub;
if (parser.get<cv::String>("algo") == "MOG2")// 입력된 인수 중에서 Type값을 추출할 때 사용됨.
// Path to a video or a sequence of image가 먼저 실행되고 없으면 vtest.avi 실행
pBackSub = cv::createBackgroundSubtractorMOG2();// Creates MOG2 Background Subtractor.
else
pBackSub = cv::createBackgroundSubtractorKNN(); // Creates KNN Background Subtractor.
//cv::VideoCapture capture(0);
cv::VideoCapture capture("REC3.mp4");
if (!capture.isOpened()) {
//error in opening the video input
cerr << "Unable to open: " << parser.get<cv::String>("input") << endl; // 입력된 인수 중에서 Type값을 추출할 때 사용됨.
// Path to a video or a sequence of image가 먼저 실행되고 없으면 vtest.avi 실행
return 0;
}
cv::Mat frame, fgMask, result; // 현재, MASK, MASK_COLOR
cv::Mat fgMask_M;
cv::Mat frame1[3];
while (true) {
capture.read(frame);
if (frame.empty())
break;
//update the background model
pBackSub->apply(frame, fgMask);// apply : Computes a foreground mask.
// morphology (실행 결과 노이즈가 많아 morphology 수행)
cv::Mat mask = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(1, 1));
cv::morphologyEx(fgMask, fgMask, cv::MORPH_OPEN, mask);
threshold(fgMask, fgMask_M, 0, 1, cv::THRESH_BINARY); // 0보다 크면 1로 변경
split(frame, frame1); // 각 채널로 split
for (int i = 0; i < 3; i++)
cv::multiply(frame1[i], fgMask_M, frame1[i]); // 각 채널에 마스크를 씌움
merge(frame1, 3, result); // 3 채널 하나로 merge
//show the current frame and the fg masks
imshow("Frame", frame);
imshow("FG Mask", fgMask);
imshow("Result", result);
//get the input from the keyboard
int key = cv::waitKey(10);
if (key == 27)
break;
}
return 0;
}
Leave a comment