1. 程式人生 > >OpenCV|圖片與視訊的相互轉換(C++&Python)

OpenCV|圖片與視訊的相互轉換(C++&Python)

前言

在學習opencv的過程中,終會遇到需要把視訊轉換成圖片處理,或者把處理後的圖片儲存為視訊格式的時候。這篇文章中就來看一下如何進行圖片和視訊之間的相互轉換。

視訊轉圖片

對於這種情況大家應該很熟悉了。因為學習opencv的時候肯定開啟過攝像頭,比如開啟攝像頭檢測個人臉或者笑臉之類的。在這個過程中,實際就是把攝像頭拍攝到的視訊轉換為一幀一幀的圖片連續地進行處理。

我們知道,對於開啟視訊和攝像頭,opencv提供了VideoCapture類,可以方便地通過流操作符>>與Mat類進行互動。這種情況比較常見,我們直接看例子。 ---------------------   

#include<opencv2\opencv.hpp>
using namespace cv;

int main()
{
    //開啟預設攝像頭
    VideoCapture cap(0); 
    if (!cap.isOpened())
    {
        return -1;
    }

    Mat frame;

    // 按Q鍵退出時,鍵盤需要調為英文模式
    while(waitKey(30) != 'q')
    {
        // 通過流操作符把視訊轉化為一幀幀圖片
        cap >> frame;
        // Do something here !
        imshow("video", frame);
    }
    return 0;
}

如果是要開啟視訊檔案而不是攝像頭,只需要像下面這樣:

VideoCapture cap("E:\\我的視訊\\視訊.mp4");

而視訊轉成圖片也就是那麼簡單的一句cap >> frame;

圖片轉視訊

視訊轉圖片只需要流操作符簡單的一句程式碼就能實現,那麼圖片轉視訊呢?是不是也是這麼簡單?

答案是肯定的。也是隻需要用一句這麼簡單的程式碼,而且只需要把流操作符的方向反過來就行了。這時候用到的就是opencv提供的VideoWriter類。VideoCapture和VideoWriter,顧名思義,他倆一個是抓取視訊的,一個是寫入視訊的。

VideoWriter建構函式如下所示:

VideoWriter(const string& filename, int fourcc, double fps, Size frameSize, bool isColor=true)

各引數含義如下:

filename: 輸出視訊檔案的名稱 fourcc:4-character code of codec的縮寫,四個字元用來表示壓縮幀的編解碼。 fps:幀率,我猜是frame per second的縮寫。 frameSize:每幀圖片的大小 isColor: 如果非零,編碼器將希望得到彩色幀並進行編碼;否則,是灰度幀(只有在Windows下支援這個標誌) 第二個引數,OpenCV提供的格式是未經過壓縮的,目前支援的格式如下:  

CV_FOURCC(‘P’, ‘I’, ‘M’, ‘1’) = MPEG-1 codec
CV_FOURCC(‘M’, ‘J’, ‘P’, ‘G’) = motion-jpeg codec
CV_FOURCC(‘M’, ‘P’, ‘4’, ‘2’) = MPEG-4.2 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘3’) = MPEG-4.3 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘X’) = MPEG-4 codec
CV_FOURCC(‘U’, ‘2’, ‘6’, ‘3’) = H263 codec
CV_FOURCC(‘I’, ‘2’, ‘6’, ‘3’) = H263I codec
CV_FOURCC(‘F’, ‘L’, ‘V’, ‘1’) = FLV1 codec

是用一個例子來看:

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int main()
{
    // 構造一個VideoWriter
    VideoWriter video("test.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25.0, Size(640, 480));
    // 從一個資料夾下讀取多張jpg圖片
    String pattern = "G:\\temp_picture\\*.jpg";
    vector<String> fn;

    glob(pattern, fn, false);

    size_t count = fn.size();
    for (size_t i = 0; i < count; i++)
    {
        Mat image = imread(fn[i]);
        // 這個大小與VideoWriter建構函式中的大小一致。
        resize(image, image, Size(640, 480));
        // 流操作符,把圖片傳入視訊
        video << image;
    }
    cout << "處理完畢!" << endl;
    // 處理完之後會在得到一個名為test.avi的視訊檔案。
}

Python程式碼

最後還是給出Python版本的示例程式碼:

import cv2
import numpy 

cap = cv2.VideoCapture(0)

while cv2.waitKey(30)!=ord('q'):
    retval, image = cap.read()
    cv2.imshow("video",image)

圖片轉視訊

# encoding: UTF-8
import glob as gb
import cv2

img_path = gb.glob("G:\\temp_picture\\*.jpg") 
videoWriter = cv2.VideoWriter('test.mp4', cv2.VideoWriter_fourcc(*'MJPG'), 25, (640,480))

for path in img_path:
    img  = cv2.imread(path) 
    img = cv2.resize(img,(640,480))
    videoWriter.write(img)