opencv::将两幅图像合并后,在同一个窗口显示;并将合并的图像流保存成视频文件

本文介绍了一个使用ViBe算法与OpenCV库进行背景消除的示例程序。该程序能够从视频输入中实时检测并标记出运动目标,通过调整参数如最小面积、最大面积比和长宽比,来过滤掉不合理的运动区域。代码详细展示了如何初始化ViBe模型,进行图像分割和更新,并应用中值滤波和轮廓检测以提高运动目标检测的准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
 * @file main-opencv.cpp
 * @date July 2014 
 * @brief An exemplative main file for the use of ViBe and OpenCV
 */
//#include <opencv2\core\core.hpp>
#include "vibe-background-sequential.h"

using namespace cv;
using namespace std;

const int minArea = 2;    // 舍去面积极小的方框
const double maxAreaRatio = 0.1;   // 舍去面积极大的方框
const double boxRatio = 0.1;   // 舍去长宽比严重失衡的方框

/**
 * Displays instructions on how to use this program.
 */
void help()
{
    cout
    << "--------------------------------------------------------------------------" << endl
    << "This program shows how to use ViBe with OpenCV                            " << endl
    << "Usage:"                                                                     << endl
    << "./main-opencv <video filename>"                                             << endl
    << "for example: ./main-opencv video.avi"                                       << endl
    << "--------------------------------------------------------------------------" << endl
    << endl;
}

void processVideo(char* videoFilename);

void contour(const Mat &mor, Mat &img);


/**
 * Main program. It shows how to use the grayscale version (C1R) and the RGB version (C3R). 
 */
int main(int argc, char* argv[])
{
  /* Print help information. */
  help();

  /* Check for the input parameter correctness. */
 /* if (argc != 2) {
    cerr <<"Incorrect input" << endl;
    cerr <<"exiting..." << endl;
    return EXIT_FAILURE;
  }

  /* Create GUI windows. */
  //namedWindow("Frame");
  //namedWindow("Segmentation by ViBe");

processVideo("framelink_yd.avi");  //读取 framelink_yd.avi 视频进行处理
  /* Destroy GUI windows. */
  destroyAllWindows();
  return EXIT_SUCCESS;
}

/**
 * Processes the video. The code of ViBe is included here. 
 *
 * @param videoFilename  The name of the input video file. 
 */
void processVideo(char* videoFilename)
{
   VideoCapture capture(videoFilename);     /* Create the capture object. */
  if (!capture.isOpened()) {
    cerr << "Unable to open video file: " << videoFilename<< endl;    /* Error in opening the video input. */
    exit(EXIT_FAILURE);
  }

  clock_t start, finish;
  double total;
  start=clock();

  /* Variables. */
  static int frameNumber = 1;  /* The current frame number */
  int lastCount = 0; 
  int probFactor = gradient_Factor;   /*概率因子,用梯度因子初始化概率因子*/
  Mat frame,frame1;                  /* Current frame. */
  Mat segmentationMap;        /* Will contain the segmentation map. This is the binary output map. */
  int keyboard = 0;           /* Input from keyboard. Used to stop the program. Enter 'q' to quit. */
  char fileName[200] = { 0 };
  int sampleCounts[10] = {0};
  int speSamples[10] = {0};
  vibeModel_Sequential_t *model = NULL;      /* Model used by ViBe. */

  int heig = 512;
  int widt = 1340;
  Mat res = Mat::zeros(heig, widt, CV_8UC3); //res为三通道像素帧,用来保存最后合并的图像

  /* 创建保存视频的文件名并打开 */
  const string Name = "res.avi";
  VideoWriter writer;
  Size sz(widt, heig);
  writer.open(Name, CV_FOURCC('M', 'J', 'P', 'G'), 70, sz, true);


  while ((char)keyboard != 'q' && (char)keyboard != 27 ) {    /* Read input data. ESC or 'q' for quitting. */ 
    if (!capture.read(frame1)) {                              /* Read the current frame. */
      cerr << "Unable to read next frame." << endl;
      cerr << "Exiting..." << endl;
      break;// exit(EXIT_FAILURE);
    }

    /* Applying ViBe.
     * If you want to use the grayscale version of ViBe (which is much faster!):
     * (1) remplace C3R by C1R in this file.
     * (2) uncomment the next line (cvtColor).
     */
    cvtColor(frame1, frame, CV_BGR2GRAY); //将三通道图像帧转换为单通道
    if ( frameNumber==1 ) {
      segmentationMap = Mat(frame.rows, frame.cols, CV_8UC1);
      model = (vibeModel_Sequential_t*)libvibeModel_Sequential_New();
      libvibeModel_Sequential_AllocInit_8u_C1R(model, frame.data, frame.cols, frame.rows);
      class_samples(model,frame.data, sampleCounts,speSamples,frame.cols, frame.rows);         
    }                                                                                         

    /* ViBe: Segmentation and updating. */
    libvibeModel_Sequential_Segmentation_8u_C1R(model, frame.data, segmentationMap.data);
    libvibeModel_Sequential_Update_8u_C1R(model, frame.data, segmentationMap.data, &probFactor,frameNumber);
   
    medianBlur(segmentationMap, segmentationMap, 3);    /* 3x3 median filtering */
    contour(segmentationMap, frame1);  //在原图上框出动目标,至此图像处理完毕

    //sprintf(fileName, "results55_2/%06d.jpg",frameNumber);
    //imwrite(fileName, frame1);

    Mat segmentationMap1; //新定义一个帧变量,不能 cvtColor(segmentationMap, segmentationMap, CV_GRAY2BGR),因为 segmentationMap 为单通道帧;
    cvtColor(segmentationMap, segmentationMap1, CV_GRAY2BGR); //将单通道帧图像 segmentationMap 转化为三通道segmentationMap1,因为 res 帧为三通道帧图像
                                                             // segmentationMap1要合并在 res 中;
    /* Shows the current frame and the segmentation map. */
    //imshow("Frame", frame1);
    //imshow("Segmentation by ViBe", segmentationMap);

    /* 将 segmentationMap1 和 frame1 合并成一帧存放在 res 中*/
    segmentationMap1.copyTo(res(Rect(0, 0, 640, 512)));
    frame1.copyTo(res(Rect(700, 0, 640, 512)));
    imshow("res", res); //显示合并后的图像

    /* 将 res 写入打开的视频文件中 */
    writer << res; //将合并图像写入,连续的图像帧保存为视频文件;

    ++frameNumber;  
    keyboard = waitKey(1);      /* Gets the input from the keyboard. */
  }

  finish=clock();
  total=(double)(finish-start);
  cout<<total<<endl;
  cout<<frameNumber<<endl;
  capture.release();           /* Delete capture object. */
  libvibeModel_Sequential_Free(model);         /* Frees the model. */
}

  /* 框出运动目标 */
void contour(const Mat &mor, Mat &img)
{
    int img_size = img.cols * img.rows;
    Mat tmp = (mor == 255);
    // Each detected contour is stored as a vector of points
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;   // containing information about the image topology
    findContours(tmp, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    for (size_t k = 0; k < contours.size(); k++) {
        Rect rect = boundingRect(contours[k]);
        double whratio = double(rect.width)  / double(rect.height);
        double hwratio = double(rect.height) / double(rect.width);
        double ratio = min(hwratio, whratio);
        double area = rect.area();
      //框出符合条件的轮廓,舍去: 面积很小的, 面积很大的, 长宽比严重失调的
        if (area > minArea && area < img_size*maxAreaRatio && ratio > boxRatio) {
            int w = rect.width;
            int h = rect.height;

            if(rect.width < 20)
                rect.width = 20;
                /*
                if(rect.width < 6)
                    rect.width = 2*rect.width;
                else
                    rect.width = rect.width + rect.width/2;
                */
            if(rect.height < 20)
                rect.height = 20;
                /*
                if(rect.height < 6)
                    rect.height = 2*rect.height;
                else
                    rect.height = rect.height + rect.height/2;
                */
            int w_add = (rect.width - w)/2;
            int h_add = (rect.height - h)/2;
            rect.x = rect.x - h_add;
            rect.y = rect.y - w_add;

            rectangle(img, rect, Scalar(0,0,255));
        }
  
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值