티스토리 뷰
[openCV] C++로 Background Subtraction 간단히 구현한 코드
심심한기린 2016. 12. 29. 18:36(배경사진 - 첫 프레임 또는 함수를 통해 구해주어야한다.)
(데이터 처리 후 영상 - 뒤에 이 영상을 가공하여 사람 수 등을 계산할 예정)
전체적인 원리는
먼저 아무도 다니지 않을 때의 영상 사진(background image)를 구하고 현재 촬영되는 영상에서 background image를 뺍니다.
문제는 빛이 반사되는 등등 노이즈가 낄 수 밖에 없는데 이를 잘 처리해서 사람들을 정상적으로 감
지 할 수 있도록 것이 핵심입니다.
1. 배경사진을 구합니다.
영상의 첫 프레임에 사람이 없다면 그 프레임을 사용하면 되고
아니라면 별도로 구해야하는데 accumulate, accumulateSquare, accumulateProduct, accumulateWeighted 함수를 통해 구합니다. 이 함수들은 src영상을 dst에 누적 기능을 가지고 있습니다.
2. gray scale로 바꿔준 후 노이즈 제거를 위해 미디안 필터를 한 번 씌워줍니다.
3. threshold를 통해서 특정 값을 넘은 픽셀들만 따로 구합니다.
3. morphological operation을 통해서 또렷하게 하는데 침식 후에 팽창 순으로 해주면 아직 걸러지지 않은 노이즈를 걸러 줄 수 있습니다.
/**/ #include <iostream> #include <opencv/cv.hpp> using namespace cv; using namespace std; static char* INPUT = "Input img"; static char* RESULT = "Result img"; static char* BG = "Background img"; static int FRAME_DELAY = 10; void bgSub(Mat& src) { cvtColor(src, src, CV_RGB2GRAY); medianBlur(src, src, 7); threshold(src, src, 50, 255, THRESH_BINARY); Mat element = getStructuringElement(MORPH_RECT, Size(7, 7)); morphologyEx(src, src, CV_MOP_CLOSE, element); morphologyEx(src, src, CV_MOP_OPEN, element); } int main() { VideoCapture cap("background.mp4"); Mat frame, inrange_out; cap.read(frame); Mat background = frame.clone(); imshow(BG, background); while (cap.read(frame)) { imshow(INPUT, frame); //diff Mat diff; absdiff(frame, background, diff); imshow("sub", diff); bgSub(diff); imshow(RESULT, diff); waitKey(FRAME_DELAY); } //end destroyAllWindows(); return 0; } /**/ |
(4. findContour 함수 등을 통해서 돌아다니는 사람의 수를 세어줄 수 있습니다.)
(원래 값들을 조정하며 찾아야 사람들이 잘 나오는데, 시간을 많이 못 들였네요, 다른 재밋는게 많아서 미뤄두고만 있습니다.
영상처리를 더 깔끔하게 하고 사람 수 세고 오래 머문 사람 녹화하는 것 까지 수정 한 번 하겠습니다.)