2013-03-12 2 views
0

Я хочу запустить другое видео в окне основного видео. Предпринятый код:Вложение видео на другое видео с помощью Opencv

#include <cv.h> 
#include <highgui.h> 
#include <iostream> 

using namespace std; 

void OverlayImage(IplImage* src, IplImage* overlay, CvScalar S, CvScalar D) { 

CvPoint location; 
//location.x = (0.5*(src->width))-50; 
//location.y = src->height-110; 
//cout << location.x << " " << location.y << endl; 

location.x = 100; 
location.y = 100; 

for (int i = location.y; i < (location.y + overlay->height); i++) { 
    for (int j = location.x; j < (location.x + overlay->width); j++) { 
     CvScalar source = cvGet2D(src, i, j); 
     CvScalar over = cvGet2D(overlay, i-location.y, j-location.x); 
     CvScalar merged; 

     for(int i = 0; i < 4; i++) 
      merged.val[i] = (S.val[i] * source.val[i] + D.val[i] * over.val[i]); 

     cvSet2D(src, i + location.y, j + location.x, merged); 
    } 
} 
} 

int main (int argc, char* argv[]) { 
CvCapture* capture = NULL; 
CvCapture* ad  = NULL; 
capture = cvCaptureFromAVI("Cricketc11.avi"); 
ad  = cvCaptureFromAVI("Cricketc1.avi"); 
assert(ad); 
assert(capture); 
cvNamedWindow("Video", 0); 

int fps   = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); 
int noOfFrames = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT); 
int height  = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT); 
int width  = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH); 
cout << height << " " << width << endl; 

int fpsad  = (int)cvGetCaptureProperty(ad, CV_CAP_PROP_FPS); 
int noOfFramesad = (int)cvGetCaptureProperty(ad, CV_CAP_PROP_FRAME_COUNT); 
int heightad  = (int)cvGetCaptureProperty(ad, CV_CAP_PROP_FRAME_HEIGHT); 
int widthad  = (int)cvGetCaptureProperty(ad, CV_CAP_PROP_FRAME_WIDTH); 

IplImage* tempimg = NULL; 
IplImage* tempad = NULL; 

while(capture) { 
    tempimg = cvQueryFrame(capture); 
    assert(tempimg); 
    if (ad) { 
     tempad = cvQueryFrame(ad); 
     assert(tempad); 
     IplImage* newimg = cvCreateImage(cvSize(100,100), IPL_DEPTH_8U, tempad->nChannels); 
     cvResize(tempad, newimg, 1); 
     OverlayImage(tempimg, newimg, cvScalar(0,0,0,0), cvScalar(1,1,1,1)); 
    } 
    else 
     cvReleaseCapture(&ad); 
    cvWaitKey(1000/fps); 
    cvShowImage("Video", tempimg); 
} 
cvReleaseCapture(&capture); 
cvDestroyAllWindows(); 
return 0; 
} 

Этот код работает нормально, только если входные видеоролики одинаковы. Если видео имеют разную длину или fps, это дает ошибку после завершения встроенного видео.

Как исправить это?

ответ

0

Что происходит

Каждый раз, когда вы звоните cvQueryFrame(source) внутренний счетчик кадров источника увеличивается. Вот почему ваш второй фильм должен быть длинным (говорящим в кадрах) главным фильмом.

В качестве обходного пути я предлагаю вам использовать рекламный ролик с числом кадров (длина * fps), равным целочисленному соотношению основного фильма, и использовать временные буферы изображений для хранения необходимых данных.

Идеальное решение состоит в том, чтобы сначала интерполировать самый короткий (в кадрах) фильм на размер самого длинного, а затем объединить их так же, как и вы, но временная upsampling может быть сложной для реализации, если вы не хотите использовать ближайший соседняя или линейная интерполяция.

Если объявление Видо меньше

Вы можете выбрать один из нескольких решений:

  • обнаружить, что вы достигли конца и прекратить передачу изображения
  • обнаружить, что вы достигли end и повторно открыть рекламный ролик с начала
  • используйте временное изображение, чтобы всегда хранить в памяти последний действительный кадр из рекламного ролика и отправлять это изображение, если нет нового
  • и т. Д.
+0

Возможно ли иметь рекламное видео размера меньшего размера, чем основное видео? –

+0

Какая техника ближайшего соседа вы говорите? –

+0

Вы можете взглянуть на Википедию для интерполяции: http://en.wikipedia.org/wiki/Interpolation. Обратите внимание, что «ближайший сосед» соответствует термину «кусочно-постоянная» в статье. – sansuiso

Смежные вопросы