2012-07-13 23 views
10

मैं CV_CAP_PROP_POS_FRAMES संपत्ति की स्थापना और उसके बाद इस तरह के फ्रेम को पढ़ कर एक विशिष्ट फ्रेम के लिए कूद करने की कोशिश कर रहा हूँ:cvSetCaptureProperty में CV_CAP_PROP_POS_FRAMES का उपयोग कर व्यक्तिगत फ्रेम हो रही

cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES, current_frame); 
frame = cvQueryFrame(input_video); 
समस्या का सामना करना पड़ रहा हूँ

कि, OpenCV 2.1 रिटर्न है current_frame के लगातार 12 मानों के लिए एक ही फ्रेम जबकि मैं प्रत्येक फ्रेम फ्रेम को पढ़ना चाहता हूं, न केवल मुख्य फ्रेम। क्या कोई मुझे बता सकता है कि क्या गलत है?


मैंने कुछ शोध किया और पाया कि समस्या डिकंप्रेशन एल्गोरिदम के कारण होती है।

एमपीईजी-जैसे एल्गोरिदम (एचडी सहित, सभी) अलग-अलग फ्रेम को संपीड़ित नहीं करते हैं, लेकिन समय-समय पर एक कीफ्रेम सहेजते हैं, और फिर अंतिम फ्रेम और बाद के फ्रेम के बीच अंतर।

आपके द्वारा रिपोर्ट की गई समस्या इस तथ्य के कारण होती है कि, जब आप कोई फ्रेम चुनते हैं, तो डीकोडर (ffmpeg, संभावित) स्वचालित रूप से अगले कीफ्रेम पर आगे बढ़ता है।

तो, क्या इसके आसपास कोई रास्ता है? मैं केवल मुख्य फ्रेम नहीं चाहता बल्कि प्रत्येक व्यक्तिगत फ्रेम चाहता हूं।

+0

मुझे इस पर कोई समाधान नहीं मिला है। मैं जो कर रहा हूं वह ओपनसीवी से बच रहा है और मैटलैब में कार्य कर रहा है जो प्रत्येक फ्रेम देता है लेकिन कम गति के खर्च पर। OpenCv में समस्या का कोई समाधान कृपया: -/ – Random

उत्तर

1

CV_CAP_PROP_POS_FRAMES एक प्रमुख फ्रेम पर कूदता है। मेरे पास एक ही समस्या थी और इस (पायथन-) कोड का उपयोग करके इसके आसपास काम किया। यह शायद पूरी तरह से कुशल नहीं है, लेकिन मिल काम किया है:

def seekTo(cap, position): 
    positiontoset = position 
    pos = -1 
    cap.set(cv.CV_CAP_PROP_POS_FRAMES, position) 
    while pos < position: 
    ret, image = cap.read() 
    pos = cap.get(cv.CV_CAP_PROP_POS_FRAMES) 
    if pos == position: 
     return image 
    elif pos > position: 
     positiontoset -= 1 
     cap.set(cv.CV_CAP_PROP_POS_FRAMES, positiontoset) 
     pos = -1 
4

मैं या नहीं, इस उद्देश्य के लिए पर्याप्त सटीक होगा पता नहीं है, लेकिन मैं सफलता एक MPEG में एक खास बिंदु के लिए हो रही लिया है फ्रेम दर को पकड़कर, फ्रेम संख्या को एक समय में परिवर्तित करके, फिर उस समय आगे बढ़कर वीडियो। इस तरह:

cv::VideoCapture sourceVideo("/some/file/name.mpg"); 
double frameRate = sourceVideo.get(CV_CAP_PROP_FPS); 
double frameTime = 1000.0 * frameNumber/frameRate; 
sourceVideo.set(CV_CAP_PROP_POS_MSEC, frameTime); 
+1

मेरे पास एक ही समस्या है। हालांकि इस जवाब ने समस्या हल नहीं की, मुझे एक लापता चीज़ मिली: फ्रेमटाइम सेकंड में है और यह एमसीईसी में होना चाहिए: 'डबल फ्रेमटाइम = 1000.0 * फ्रेम नम्बर/फ्रेमरेट; ' – cbuchart

+0

अच्छा बिंदु, @cbuchart। मैंने जवाब अपडेट कर लिया है। क्या आप मुझे बता सकते हैं कि यह जवाब आपके लिए क्यों काम नहीं करता? –

+0

ऐसा लगता है कि एक कीफ्रेम गायब है। यहां तक ​​कि अगर मैं एक स्रोत Video.set (CV_CAP_PROP_POS_MSEC, 0.0) बना देता हूं और वहां से शुरू करता हूं, तो यह मुझे गलत फ्रेम देता है ("भूत" ईफेक्ट के साथ) – cbuchart

3

ओपनसीवी में इस सीमा के कारण, एफएफएमपीईजी का उपयोग करना बुद्धिमान हो सकता है। Moviepy एक अच्छी रैपर लाइब्रेरी है।

# Get nth frame from a video 
from moviepy.video.io.ffmpeg_reader import FFMPEG_VideoReader 
cap = FFMPEG_VideoReader("movie.mov",True) 
cap.initialize() 
cap.get_frame(n/FPS) 

प्रदर्शन भी बहुत अच्छा है। get_frame के साथ एनएच फ्रेम की तलाश ओ (1) है, और एक गति-अप का उपयोग तब किया जाता है जब (लगभग) लगातार फ्रेम अनुरोध किए जाते हैं। मुझे एक से अधिक 720p वीडियो लोड करने के बाद-से-रीयलटाइम परिणाम मिल गए हैं।

0

मैं सफलतापूर्वक OpenCV पर निम्नलिखित 3/अजगर 3 उपयोग किया है:

# Skip to 150 frame then read the 151th frame 
cap.set(cv2.CAP_PROP_POS_FRAMES, 150)) 
ret, frame = cap.read() 
0

कुछ साल एक unsavable बग के रूप में यह सोचते हैं के बाद, मुझे लगता है कि मैं एक अच्छा संतुलन के साथ उपयोग करने के लिए एक तरीका खोज निकाला है गति और शुद्धता के बीच।

एक पिछले समाधान फ्रेम पढ़ने से पहले CV_CAP_PROP_POS_MSEC संपत्ति का उपयोग करने का सुझाव दिया:

cv::VideoCapture sourceVideo("/some/file/name.mpg"); 
const auto frameRate = sourceVideo.get(CV_CAP_PROP_FPS); 

void readFrame(int frameNumber, cv::Mat& image) { 
    const double frameTime = 1000.0 * frameNumber/frameRate; 
    sourceVideo.set(CV_CAP_PROP_POS_MSEC, frameTime); 
    sourceVideo.read(image); 
} 

यह उम्मीद फ्रेम वापसी करता है, लेकिन समस्या यह है कि CV_CAP_PROP_POS_MSEC का उपयोग कर बहुत धीमी गति से हो सकता है, एक के लिए उदाहरण के लिए है वीडियो रूपांतरण

नोट: सादगी के लिए वैश्विक चर का उपयोग करना।


दूसरी ओर, अगर तुम सिर्फ वीडियो क्रमिक रूप से पढ़ना चाहते हैं, यह बिल्कुल की मांग के बिना फ्रेम को पढ़ने के लिए पर्याप्त है। पिछले पूछे फ्रेम, lastFrameNumber याद करने के लिए, और केवल की तलाश जब अनुरोध फ्रेम अगले एक नहीं है एक चर का उपयोग कर:

for (int frameNumber = 0; frameNumber < nFrames; ++frameNumber) { 
    sourceVideo.read(image); 
} 

समाधान दोनों के संयोजन से आता है। इस तरह यादृच्छिक पढ़ने में गति को बढ़ाने के दौरान गति को बढ़ाने के लिए संभव है।

cv::VideoCapture sourceVideo("/some/file/name.mpg"); 
const auto frameRate = sourceVideo.get(CV_CAP_PROP_FPS); 
const int lastFrameNumber = -2; // guarantee seeking the first time 

void readFrame(int frameNumber, cv::Mat& image) { 
    if (lastFrameNumber + 1 != frameNumber) { // not the next frame? seek 
    const double frameTime = 1000.0 * frameNumber/frameRate; 
    sourceVideo.set(CV_CAP_PROP_POS_MSEC, frameTime); 
    } 

    sourceVideo.read(image); 
    lastFrameNumber = frameNumber; 
}