2013-02-01 76 views
2

我正在嘗試編寫一個程序,將4個視頻合併爲一個視頻,並將它們排列成一個2x2網格。下面是相關代碼:在opencv和Qt中合併視頻

void CombineVideoApp::on_GoButton_clicked() 
{ 
    std::string Video1Name = Video1Path.toUtf8().constData(); 
    std::string Video2Name = Video2Path.toUtf8().constData(); 
    std::string Video3Name = Video3Path.toUtf8().constData(); 
    std::string Video4Name = Video4Path.toUtf8().constData(); 

    int VideoWidth = 640; 
    int VideoHeight = 360; 

    cv::Mat Video1Frame, Video2Frame, Video3Frame, Video4Frame; // Creating Mat objects to store the captured frames 
    cv::Mat Video1Shrunk, Video2Shrunk, Video3Shrunk, Video4Shrunk; //Creating Mat objects to store the shrunk frames 
    cv::Mat FullCombinedVideo(VideoWidth,VideoHeight, Video1Shrunk.type()); //Creating Mat object to store the combined video 
    cv::Mat CombinedVideoTop(VideoWidth, VideoHeight/2, Video1Shrunk.type()); 
    cv::Mat CombinedVideoBottom(VideoWidth, VideoHeight/2, Video1Shrunk.type()); 


    cv::VideoCapture Video1(Video1Name); 
    cv::VideoCapture Video2(Video2Name); 
    cv::VideoCapture Video3(Video3Name); 
    cv::VideoCapture Video4(Video4Name); 



    double Video1FrameCount = Video1.get(CV_CAP_PROP_FRAME_COUNT); 
    double Video2FrameCount = Video2.get(CV_CAP_PROP_FRAME_COUNT); 
    double Video3FrameCount = Video3.get(CV_CAP_PROP_FRAME_COUNT); 
    double Video4FrameCount = Video4.get(CV_CAP_PROP_FRAME_COUNT); 

    double CombinedFrameTopCount = min(Video1FrameCount, Video2FrameCount); 
    double CombinedFrameBottomCount = min(Video3FrameCount, Video4FrameCount); 
    double CombinedFrameCount = min(CombinedFrameBottomCount, CombinedFrameTopCount); 

    Video1.set(CV_CAP_PROP_FRAME_COUNT, CombinedFrameCount); 
    Video2.set(CV_CAP_PROP_FRAME_COUNT, CombinedFrameCount); 
    Video3.set(CV_CAP_PROP_FRAME_COUNT, CombinedFrameCount); 
    Video4.set(CV_CAP_PROP_FRAME_COUNT, CombinedFrameCount); 


    for(;;) 
    { 
     Video1 >> Video1Frame; 
     Video2 >> Video2Frame; 
     Video3 >> Video3Frame; 
     Video4 >> Video4Frame; 

     cv::resize(Video1Frame, Video1Shrunk, Size((VideoWidth/2), (VideoHeight/2))); 
     cv::resize(Video2Frame, Video2Shrunk, Size((VideoWidth/2), (VideoHeight/2))); 
     cv::resize(Video3Frame, Video3Shrunk, Size((VideoWidth/2), (VideoHeight/2))); 
     cv::resize(Video4Frame, Video4Shrunk, Size((VideoWidth/2), (VideoHeight/2))); 

     Video1Shrunk.copyTo(CombinedVideoTop(Rect(0,0,Video1Shrunk.cols,Video1Shrunk.rows))); 
     Video2Shrunk.copyTo(CombinedVideoTop(Rect(Video1Shrunk.cols,0,Video2Shrunk.cols,Video2Shrunk.rows))); 
     Video3Shrunk.copyTo(CombinedVideoBottom(Rect(0,0,Video3Shrunk.cols,Video3Shrunk.rows))); 
     Video4Shrunk.copyTo(CombinedVideoBottom(Rect(Video3Shrunk.cols,0,Video4Shrunk.cols,Video4Shrunk.rows))); 

     CombinedVideoTop.copyTo(FullCombinedVideo(Rect(0,0,CombinedVideoTop.cols, CombinedVideoTop.rows))); 
     CombinedVideoBottom.copyTo(FullCombinedVideo(Rect(0,CombinedVideoTop.rows, CombinedVideoBottom.cols,CombinedVideoBottom.rows))); 


     std::string FinalFilePath = CombinedVideo.toUtf8().constData(); 
     cv::VideoWriter CombinedWriter(FinalFilePath, CV_FOURCC('D', 'I', 'V', 'X'),10,cvSize(FullCombinedVideo.cols, FullCombinedVideo.rows)); 

     CombinedWriter << FullCombinedVideo; 

    } 


} 

程序沒有問題,編譯,但是當我真正嘗試運行它,我得到以下錯誤:

OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in Mat, file /tmp/OpenCV-2.4.3/modules/core/src/matrix.cpp, line 322 
Qt has caught an exception thrown from an event handler. Throwing 
exceptions from an event handler is not supported in Qt. You must 
reimplement QApplication::notify() and catch all exceptions there. 

The program has unexpectedly finished. 

誰能告訴我的問題是在這裏什麼?我完全難倒了。 我試圖打開的視頻文件是.avi格式,我使用的是QtCreator,OpenCV 2.4.3,並在OSX Snow Leopard上運行它。

感謝

+0

您是否試圖在同一個窗口中顯示4個視頻,或者您是否嘗試用其他人創建新的視頻文件? – karlphillip

+0

我試圖用它裏面的4個視頻創建一個新的視頻文件。 – JM92

+0

你應該趕上例外,btw –

回答

2

將幀寫入視頻文件很容易,並且有幾個示例around here

棘手的部分是組裝4個幀到一個單一的一個,所以以下代碼演示如何做到這一點,它考慮到,所有的幀可以具有任意大小:

// Load 4 images from the disk 
cv::Mat img1 = cv::imread("test1.jpg"); 
cv::Mat img2 = cv::imread("test2.jpg"); 
cv::Mat img3 = cv::imread("test3.jpg"); 
cv::Mat img4 = cv::imread("test4.jpg"); 

// Make sure they have been loaded successfully 
if (img1.empty() || img2.empty() || img3.empty() || img4.empty()) 
{ 
    std::cout << "!!! Failed to load one of the images\n"; 
    return -1; 
} 

/* Make sure they are compatible: same type, depth and # channels */ 

if ((img1.type() != img2.type()) || 
    (img3.type() != img4.type()) || 
    (img1.type() != img4.type())) 
{ 
    std::cout << "!!! The depth doesn't match!\n"; 
    return -1; 
} 

if ((img1.depth() != img2.depth()) || 
    (img3.depth() != img4.depth()) || 
    (img1.depth() != img4.depth())) 
{ 
    std::cout << "!!! The depth doesn't match!\n"; 
    return -1; 
} 

if ((img1.channels() != img2.channels()) || 
    (img3.channels() != img4.channels()) || 
    (img1.channels() != img4.channels())) 
{ 
    std::cout << "!!! Number of channels doesn't match!\n"; 
    return -1; 
} 

// Create the destination image based on the size of the loaded images 
// _________ 
// | | | 
// |_1__|_2__| 
// | | | 
// |_3__|_4__| 

/* As the input images might have different sizes, we need to make sure 
* to create an output image that is big enough to store all of them. 
*/ 

// Compute the width of the output image 
int row1_size = img1.size().width + img2.size().width; 
int row2_size = img3.size().width + img4.size().width; 
int new_width = std::max(row1_size, row2_size); 

// Compute the height of the output image 
int col1_size = img1.size().height + img3.size().height; 
int col2_size = img2.size().height + img4.size().height; 
int new_height = std::max(col1_size, col2_size); 

// Create the destination image 
cv::Mat dst_img(cv::Size(new_width, new_height), img1.type(), cv::Scalar(0, 0, 0)); 
std::cout << "dst: size " << dst_img.size().width << "x" << dst_img.size().height << std::endl; 

/* Copy the pixels of the input images to the destination */ 

// _________ 
// | | | 
// |_1__| | 
// |   | 
// |_________| 
img1.copyTo(dst_img(cv::Rect(0, 0, img1.cols, img1.rows))); 

// _________ 
// | | | 
// |_1__|_2__| 
// |   | 
// |_________|  
img2.copyTo(dst_img(cv::Rect(img1.size().width, 0, img2.cols, img2.rows))); 

// _________ 
// | | | 
// |_1__|_2__| 
// | | | 
// |_3__|____|  
img3.copyTo(dst_img(cv::Rect(0, 
          std::max(img1.size().height, img2.size().height), 
          img3.cols, 
          img3.rows))); 

// _________ 
// | | | 
// |_1__|_2__| 
// | | | 
// |_3__|_4__|  
img4.copyTo(dst_img(cv::Rect(img3.size().width, 
          std::max(img1.size().height, img2.size().height), 
          img4.cols, 
          img4.rows))); 

// For testing purposes, display it on the screen 
cv::imshow("Test", dst_img); 
cv::waitKey(0); 

這些是用於測試的圖像的尺寸:32,64×64,128×256×256 320×320和

結果

enter image description here

+0

在這個演示中,您可以注意到所有圖像都非常接近,因爲我的2x2網格沒有預定義的尺寸。您可能想要使網格具有固定尺寸,以便圖像保持垂直和水平對齊。這將是對代碼的一個非常小的改變。 – karlphillip

0

由於OpenCV的說,你有ROI(感興趣區域)是錯誤的。

也許你有一個錯誤的錯誤,所以你有一個區域開始在-1或結束超過 的寬度/高度。

請檢查這些int他調試器,或打印座標,看看哪一個是錯誤的。