2010-12-04 18 views
13

OpenCV ile işlemeye çalıştığım 33 saniyelik bir video var. Amacım, her bir karenin hangi zamana karşılık geldiğini (videonun başlangıcına göre) belirlemek. Farklı kare hızlarında kaydedilmiş aynı sahnenin videolarından kareleri karşılaştırabilmek için bunu yapıyorum.OpenCV doğru çerçeve hızı bildiriyor/sayım

Ne Var çalışma:

  • FPS doğru 59.75 olarak bildirilir. Bu ffprobe raporları ile tutarlıdır, bu yüzden doğru olduğuna inanmaktan mutluluk duyuyorum. Ben yaşıyorum

sorunlar şunlardır:

  • CAP_PROP_POS_MSEC döner yanlış değerler. Videonun sonunda, 557924 ms'ye kadar (9 dakikadan fazla). 33'lü bir video için bu doğru olamaz.
  • CAP_PROP_FRAME_COUNT da yanlıştır. 59.75 fps'de 9 dakikadan fazla çekilebilecek 33371 olarak rapor edildi. Yukarıdaki hata ile tutarlı, ancak hala yanlış.
  • CAP_PROP_POS_FRAME benzer şekilde yanlıştır.

Video here (yaklaşık 10MB) bulunabilir.

Neyin yanlış olabileceğine dair bir fikir var mı?

ffprobe çıkışı:

FFprobe version SVN-r20090707, Copyright (c) 2007-2009 Stefano Sabatini 
    libavutil  49.15. 0/49.15. 0 
    libavcodec 52.20. 0/52.20. 1 
    libavformat 52.31. 0/52.31. 0 
    built on Jan 20 2010 00:13:01, gcc: 4.4.3 20100116 (prerelease) 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/misha/Dropbox/Public/sequence.mp4': 
    Duration: 00:00:33.37, start: 0.000000, bitrate: 2760 kb/s 
    Stream #0.0(und): Video: h264, yuv420p, 1920x1080, 59.75 tbr, 1k tbn, 2k tbc 
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16 

Tam kodu:

#include <iostream> 
#include <assert.h> 

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

#include <cmath> 
#include <iostream> 
#include <string.h> 
#include <stdio.h> 

extern "C" 
{ 
#include "options.h" 
} 

using namespace std; 

#define DEBUG 0 

static void 
print_usage(char *argv0) 
{ 
    cerr << "usage: " << argv0 << " video.avi [options]" << endl; 
} 

int main(int argc, char** argv) 
{ 
    if (argc < 2) 
    { 
     print_usage(argv[0]); 
     return -1; 
    } 

    int   step  = 30; 
    struct Option options[] = 
    { 
     { "step",  1, &step }, 
     { NULL,   0, NULL } 
    }; 

    int ret = parse_options(2, argc, argv, options); 
    if (ret == 0) 
    { 
     print_usage(argv[0]); 
     return -1; 
    } 

    CvCapture *capture = cvCaptureFromFile(argv[1]); 
    int counter = 0; 
    while (cvGrabFrame(capture)) 
    { 
     ++counter; 

     IplImage *frame = cvRetrieveFrame(capture); 
     double millis = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC); 
     double current = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES); 
     double total = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT); 
     printf("%d %d/%d %f\n", counter, (int)current, (int)total, millis); 
     int min = (int)(millis/1000/60); 
     millis -= min*60000; 
     int sec = (int)(millis/1000); 
     millis -= sec*1000; 

     printf("%d %02d:%02d:%f\n", counter, min, sec, millis); 
    } 
    cvReleaseCapture(&capture); 

    return 0; 
} 
+0

Hangi kullanıyorsunuz: Windows/Linux/Mac? – karlphillip

+0

Linux (Ubuntu 10.04 LTS) – misha

+1

Bu çok açıklar. OpenCV hala Linux altında video dosyalarının desteğini geliştirmeye çalışıyor, üzgünüm. – karlphillip

cevap

5

daima kullandığınız yazılım sürümünü bilgilendirmek: Hangi OpenCV versiyonunu bunun için kullanıyorsunuz? Sizinki eski bir sürüm olabilir, bu nedenle mümkünse en güncel şekilde güncelleyin.

CV_CAP_PROP_POS_MSEC - film current position in milliseconds or video capture timestamp 

OpenCV basitçe besbelli yanlıştır dosya başlığında, tüm bu yazdıklarını okumayı olabilir: Video dosyasının bazı diğer büyük videonun parçası ise

, bu bilgiler aslında bu yana, doğru olabilir. Bu parça, orijinal videodan bu parçayı çıkarmak için bir balta (veya başka bir ortaçağ aracı) kullandıysa gerçekleşebilir.

Yaptığınız ve kurcalanmadıklarını bildiğiniz videolarla denemelisiniz.

En kötü durum senaryosu, bu özellikleri kendiniz uygulamanız gerekecek. Hayır biggie.

DÜZENLEME: Kullandığınız ilk başta fark etmedi @misha: Uygulamayı

CvCapture *capture = cvCaptureFromFile(argv[1]); 

için değiştirilsin cvCaptureFromAVI() ve dönüş değeri DAİMA onay OpenCV çağrıları arasında:

CvCapture *capture = cvCaptureFromAVI(argv[1]); 
if(!capture) 
{ 
    printf("!!! cvCaptureFromAVI failed (file not found?)\n"); 
    return -1; 
} 

birkaç gün önce ben uses OpenCV to read a video file and then save the frames as JPG images on the disk bir kod paylaştı. Ayrıca mevcut FPS'yi geleneksel cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); kullanarak bildirir, böylece bir göz atmanız sizin için ilginç olabilir. Git göz atın.

DÜZENLEME:

Ayrıca OpenCV kullanarak kare sayısı hakkında this thread kontrol etmelidir; Bu arada

, ben sadece benim Ubuntu sisteminde bazı kütüphaneleri güncellenerek OpenCV-2.1.0.tar.bz2 ( cmake kullanarak) çekirdekler. Kaynak kodumu (her satırda hata ayıklama yönteminizi kullanarak bir şeyler yazdırmak için cvCaptureFromAVI() kullanır) değiştirdim. Şöyle görünüyor:

* Filename: sequence.mp4 
* FPS: 59 
... 
... 
... 
17 00:00:567.000000 
18 601/33371 601.000000 
18 00:00:601.000000 
19 634/33371 634.000000 
19 00:00:634.000000 
20 668/33371 668.000000 
20 00:00:668.000000 
21 701/33371 701.000000 
21 00:00:701.000000 
22 734/33371 734.000000 
22 00:00:734.000000 
23 768/33371 768.000000 
23 00:00:768.000000 
24 801/33371 801.000000 
24 00:00:801.000000 
25 835/33371 835.000000 
25 00:00:835.000000 
26 868/33371 868.000000 
26 00:00:868.000000 
27 901/33371 901.000000 
27 00:00:901.000000 
28 935/33371 935.000000 
... 
+0

Ah, bir şey unuttuğumu biliyordum. cout << "OpenCV sürümü:" << CV_VERSION << endl; 'OpenCV sürümü verir: 2.0.0 ' – misha

+0

OpenCV 2.1 (en yeni değil) kullanıyorum ve bu gayet iyi çalışıyor. OpenCV'yi makinenizde güncelleyin ve tekrar deneyin. – karlphillip

+0

2.1 yükledim. Sonuç hala aynı :(Sorunun üstesinden gelmek için bu işlevselliği yeniden yazabilirim - dediğin gibi, biggie yok. Benim sorularım: başlıkta fps değerine güvenebileceğimi nasıl bilebilirim ? Değişken fps videoları hakkında ne düşünüyorsunuz? – misha