0

メイン ビデオのウィンドウで別のビデオを実行したいと考えています。試行されたコードは次のとおりです。

#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 が異なる場合、埋め込みビデオの終了後にエラーが発生します。

それを修正する方法は?

4

1 に答える 1

0

何が起こるのですか

cvQueryFrame(source)ソースの内部フレーム カウンターを呼び出すたびにインクリメントされます。これが、2 番目のムービーがメイン ムービーと同じ長さ (フレーム数) である必要がある理由です。

回避策として、フレーム数 (長さ * fps) がマスター ムービーの整数比に等しい広告ムービーを使用し、必要なデータを保持するために一時的な画像バッファーを使用することをお勧めします。

理想的な解決策は、最初に最短の (フレーム単位の) ムービーを最長のサイズに補間してから、それらをマージすることですが、最近隣または線形補間を使用したくない場合は、一時的なアップサンプリングを実装するのが難しい場合があります。 .

広告動画が小さい場合

いくつかのソリューションから選択できます。

  • 最後に到達したことを検出し、画像の送信を停止します
  • 最後に到達したことを検出し、最初から広告ムービーを再開します
  • 一時的な画像を使用して、広告ムービーの最後の有効なフレームを常にメモリに保持し、新しい画像がない場合はこの画像を送信します
于 2013-03-12T14:24:57.317 に答える