【OpenCV】視頻/圖像背景減除方法

  背景減除法(Background subtraction)常用於通過靜態攝像頭生成一個前景掩碼,即場景中移動物體的二進制圖像。


代碼示例

#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/video.hpp"

#include <iostream>
#include <sstream>

using namespace std;
using namespace cv;

Mat frame;                              // 當前幀
Mat fgMaskMOG2;                         // 前景模板,通過MOG2方法生成
Ptr<BackgroundSubtractor> pMOG2;        // MOG2 背景消除
char keyboard;                          // 按鍵響應
const char* filename;

void processVideo(const char* videoFilename);
void processImages(const char* firstFrameFilename);

int main()
{
    pMOG2 = createBackgroundSubtractorMOG2();                      // MOG2方法,背景消除

    char video_or_image;
    string s;
    cout << "Pless choose Video or Image: ( V / I )\t";
    cin >> video_or_image ;

    if (video_or_image == 'V' || video_or_image == 'v')             // 視頻
    {
        cout << "\n\nPlease input the address of the video:\t";
        cin >> s;
        filename = s.c_str();

        namedWindow("Frame");
        namedWindow("FG Mask MOG2");

        processVideo(filename);
    }
    else if (video_or_image == 'I' || video_or_image == 'i')        // 圖像
    {
        cout << "\n\nPlease input the address of the images:\t";
        cin >> s;
        filename = s.c_str();

        namedWindow("Frame");
        namedWindow("FG Mask MOG2");

        processImages(filename);
    }
    else
    {
        cerr << "Wrong Input !" << endl;
        return EXIT_FAILURE;
    }

    destroyAllWindows();
    return EXIT_SUCCESS;
}

void processVideo(const char* videoFilename)
{
    VideoCapture capture(videoFilename);                            // 捕獲視頻
    if (!capture.isOpened()) { exit(EXIT_FAILURE); }

    keyboard = 0;
    while (keyboard != 'q'&&keyboard != 27)
    {
        if (!capture.read(frame)) { exit(EXIT_FAILURE); }           // 讀取當前幀

        pMOG2->apply(frame, fgMaskMOG2);                            // 獲取前景掩模

        stringstream ss;
        ss << capture.get(CAP_PROP_POS_FRAMES);                     // 獲取當前幀數

        string frameNumberString = ss.str();
        rectangle(frame, cv::Point(10, 2), cv::Point(100, 20), cv::Scalar(255, 255, 255), -1);
        putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
            FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));

        imshow("Frame", frame);
        imshow("FG Mask MOG2", fgMaskMOG2);
        keyboard = (char)waitKey(30);
    }

    capture.release();
}

void processImages(const char* fistFrameFilename) 
{
    frame = imread(fistFrameFilename);
    if (frame.empty()) { exit(EXIT_FAILURE); }

    string fn(fistFrameFilename);
    keyboard = 0;
    while (keyboard != 'q' && keyboard != 27) 
    {
        pMOG2->apply(frame, fgMaskMOG2);                    // 獲取前景掩模

        size_t index = fn.find_last_of("/");
        if (index == string::npos)                          // 如果'/'不存在則搜尋'\\'
            index = fn.find_last_of("\\");
        size_t index2 = fn.find_last_of(".");

        string prefix = fn.substr(0, index + 1);            // 圖像路徑前部分,前爲起始位置,後爲長度
        string suffix = fn.substr(index2);                  // 圖像路徑後部分,圖像格式
        string frameNumberString = fn.substr(index + 1, index2 - index - 1);

        istringstream iss(frameNumberString);
        int frameNumber = 0;
        iss >> frameNumber;

        rectangle(frame, cv::Point(10, 2), cv::Point(100, 20),
            cv::Scalar(255, 255, 255), -1);
        putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
            FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));

        imshow("Frame", frame);
        imshow("FG Mask MOG 2", fgMaskMOG2);

        keyboard = (char)waitKey(30);

        ostringstream oss;
        oss << (frameNumber + 1);
        string nextFrameNumberString = oss.str();
        string nextFrameFilename = prefix + nextFrameNumberString + suffix;

        frame = imread(nextFrameFilename);
        if (frame.empty()) 
            exit(EXIT_FAILURE);

        fn.assign(nextFrameFilename);                       // 更新圖片路徑
    }
}

運行結果

發佈了99 篇原創文章 · 獲贊 210 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章