Just My Life & My Work

好難翻video和frame,如果以通俗的字句來說,就是抓取影片中的影像!標題搞得我好像內地人似的XD~不過這樣看起來也比較專業,這篇就叫作擷取視訊影像 (Extract Video Frames)吧!如果有網友需要的話,大概打擷取video的frame也可以搜尋到我這篇文章。

以為用程式讀video會很難實做,但若是OpenCV挺身而出的話,只要呼叫幾個函式就能讀取影片檔啦~其實影片檔就是一連串影像檔的集合嘛~

我們知道一般video的frame一秒鐘有24張,這樣就會讓我們人眼以為它是連續的video,而不是單張的image,動畫即是將連續的影像兜成影片

/**
	Theme: Extract Video Frames
	compiler: Visual Studio 2010 with OpenCV 2.4 beta
	Date: 101/05/18
	Author: HappyMan
	Blog: https://cg2010studio.wordpress.com/
*/
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <vector>
#include <stdio.h>

using namespace cv;
using namespace std;

//hide the local functions in an anon namespace
namespace{
void help(char** av){
  cout << "\nThis program justs gets you started reading images from video\n"
    "Usage:\n./" << av[0] << " <video device number>\n"
	  << "# q, Q, esc -- quit\n"
      << "# space     -- save frame\n\n"
      << endl;
}

int process(VideoCapture& capture){
  std::vector<DataMatrixCode> codes;
  int n_save = 0;
  char filename[200];
  string window_name = "#video | q or esc to quit";
  cout << "#press space to save a picture. q or esc to quit" << endl;
  namedWindow(window_name, CV_WINDOW_AUTOSIZE | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED); //resizable window;
  Mat frame;
  int n_frame = 0;
  for (;;){
    n_frame++;
	cout<<"n_frame: "<<n_frame<<endl;
    capture >> frame;
    if (frame.empty())
      break;
    cv::Mat gray;
    cv::cvtColor(frame,gray,CV_RGB2GRAY);
    findDataMatrix(gray, codes);
    drawDataMatrixCodes(codes, frame);
    imshow(window_name, frame);

    char key = (char) waitKey(500);
	//delay N millis, usually long enough to display and capture input
    switch (key){
		case 'q':
		case 'Q':
		case 27: //escape key
		  return 0;
		case ' ': //Save an image
		  sprintf(filename, "frame%.3d.jpg", n_save++);
		  imwrite(filename, frame);
		  cout << "save: " << filename << endl;
		  break;
		default:
		  break;
    }
  }
  return 0;
}
}
int main(int ac, char** av){
  if (ac != 2){
    help(av);
    return 1;
  }
  std::string arg = av[1];
  VideoCapture capture(arg);
  //try to open string, this will attempt to open it as a video file
  if (!capture.isOpened()){
  //if this fails, try to open as a video camera, through the use of an integer param
    capture.open(atoi(arg.c_str()));
  }
  if (!capture.isOpened()){
    cerr << "Failed to open a video device or video file!\n" << endl;
    help(av);
    return 1;
  }
  return process(capture);
}

按照環境設定好進行編譯即可成功執行。接下來就透過命令提示字元到執行檔資料夾,以指令執行:

  • video_dmtx2.4.exe HappyMan.avi

waitkey函式中參數設定為500,表示每0.5秒擷取一次frame,這時候就可以按鍵操作:

  • q, Q, Esc:結束程式
  • space:儲存frame

我想應該就會有人拿來這程式,來擷取喜歡的電影畫面了吧:P

下圖是由OpenCV提供的sample video前半部份frame的截圖(點圖可放大)。

Comments on: "[OpenCV] 擷取視訊影像 (Extract Video Frames)" (13)

  1. 陳同學 的大頭貼

    您好,請問擷取影片的影像,可以用Dev C++來操作嗎?
    如果可以程式需要更改嗎?

  2. weiiboy 的大頭貼

    想請問一下…

    關於在std::vector codes; 這一行

    他說 Error 識別項"DataMatrixCode"未定義

    想請問一下這個是要用CvDataMatrixCode嗎??

    還有在findDataMatrix(gray, codes); 這一條

    他會說codes這邊有錯誤說是Error型別

    想請問您這個該如何解決呢??

回覆給HappyMan 取消回覆

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

標籤雲