-
-
Notifications
You must be signed in to change notification settings - Fork 55.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VideoCapture::set (CAP_PROP_POS_FRAMES, frameNumber) not exact in opencv 3.2 with ffmpeg #9053
Comments
@nji9nji9 The "category:highui-video" category label captures the video input/output functionality as such functionality has come to be associated with highui ... since at least 2.4. See here. "category:video" is for video processing functionality (not input/output). I believe maintainer has chosen the appropriate label. Hope this clarifies things. |
Some more info: |
Found another issue with that bug. Solved or not solved? What is happening here? |
…_PROP_POS_FRAMES,) with ffmeg av_seek_frame() is seeking with DTS time, hence the initial time should be first_dts instead of start_time. Why: with my limit understanding of ffmpeg, start_time is the +ve offset from first_dts. For most video files, start_time and first_dts are the same hence the code seem to work. When they are different, using start_time to seek will result in the next key frame(eg. 30 for me).
What can be done to prevent to close this issue after merging the above commit? As it doesn't solve the problem. |
Hi, |
Hi. If I need only very few frames I start at 0 and continue to If I need more or all frames I process the movie multithreaded |
OpenCV 3.3 With TBB ,LIBV4L, FFMPEG have the same bug. Avi FOURCC MJPEG is OK I'm puzzled how this error isn't a higher priority. This actually forced users to iterate and count the whole video just to be sure they dragged out a valid frame. Otherwise results are corrupted |
To my opinion it would be best to remove the whole code from opencv. |
OpenCV highly uses FFmpeg (in case of FFmpeg backend). Consider to extract frames from video (into .png files) and use them. Main purpose of OpenCV library is not highly correlated with goals of Media I/O library. Video I/O and Image I/O things added into OpenCV for demo purposes initially.
|
OK, let's take it as a fact that FFmpeg is the cause for the wrong function. |
I believe we could add some notification message for users about using of optional (and actually untested) features.
Tests; many tests; tests for anything including tests for tests. |
I think an unspecific notice somewhere in the openCV docu Tests. Who would deny that they are essential ;-) But this used FFmpeg code is not untested, but tested and shown as buggy. When there will be no reaction from the openCV users - good, nobody affected. |
To state it explicite:
What makes it even worse:
Can't imagine a more neglected (sad) situation. |
I am very much in favour of warning developers about these problems. Perhaps print a warning to the console when using It's quite broken. I have used A potential upshot of making these problems more obvious is that it would potentially add some motivation for someone with the relevant video codec skills to develop a fix. :) |
So this bit me too and after several hours of trying I concluded, just as mentioned in this thread, that both VideoCapture::set with CAP_PROP_POS_FRAMES and VideoCapture::set with CAP_PROP_POS_MSEC are completely unreliable. I can also state that FFmpeg will not have this problem. Frames seeked and grabbed from FFmpeg will always return the correct one. I ended up having to rewrite all frame captures to grab from FFmpeg and then importing the still image into cv2 so I could then send it to the video writer object in cv2 as needed. As pointed out by @nji9nji9 this issue only happens when VideoCapture::set is used. This issue does not happen when all frames are iterated from the beginning of the video file. It seems to me that the problem is that VideoCapture ignores all duplicate frames, while FFmpeg will return duplicates without issues. In consequence, when calling VideoCapture::set with CAP_PROP_POS_FRAMES you will get a frame offset by something approximate (or likely equal) to the number of duplicate frames in the video file, or the number of duplicate frames in video file up to the frame you've tried to set to.. If this is right, then, resolving this bug should therefore just be a matter of having VideoCapture::set not ignore duplicate frames in the video. Just a couple of thoughts, if useful at all |
My gosh, totally right. To debug, I reviewed my code several times until I foundd this terrible bug here. 😢 How could such a bug been left in master branch??? And marked as low priority??? |
I have the same problem ! |
This bug should definitely not have low priority. |
That's what I always say. First - and simplest - thing to do would be to disable |
Two years old bug and still no attention or at least warning? |
av_seek_frame(... , AVSEEK_FLAG_BACKWARD) |
In the name of the dozens (?) apps where this bug Thank you Robird! Unfortunately I don't have the ability to assess |
I believe it is not just a OpenCV or ffmpeg problem : it's also the video codec issue. Video codec (eg x264) do not store frame number in their frame. Or at least it is not mandatory. It is an issue for video that do not have fix frame rate : how do you know what is the frame number at 5.36s when the frame rate could have changed mean while ? The only reliable way to get frame number is then by running from the beginning ! That is why I went away from referencing using frame number and use dts. But it would still be really professional to have some sort of warning from OpenCV when compiling or when running, when someone is trying to seek using frame number ! |
But if it is a codec issue the effect should be in DirectShow too... If you're true (and some results from the mentioned thread) |
The link to a recapEveryone who enters this conversation should read this clear summary by roninpawn. link to the summary Thanks a lot. It really saved me. The conclusion of the recap?I guess the conclusion of this thread is never use the Alternative video I/OMy goal was to extract every 5 frames in a constant framerate video and process it with other python functions. I encountered this issue when some videos started to return the same frame even if I changed the play header. Although I can read all five frames, get one, and toss others away, many of you recommended ffmpeg, the more reliable and faster package for video I/O, and found the workaround using it. (deffcode by abhitronix, simple videostream script by roninpawn) Speed issueA stupid but more reliable (if sequentially reading does not mess up as I quoted) way of frame seeking is reading through the whole video and stopping until the target frame is found. I have tried this with opencv's
Source code for the test (gist) I don't know what magic is done inside the |
I definitely think your contribution is "worthy of sharing" and an excellent contribution. We're both looking to just get the fastest and most accurate library out there. Sorry if you've had difficulty reproducing that benchmarking repo, I've put a minimal and fully reproducible google collab here which evidences that when working with RGB, libraries like That's not to say it's always the case that this library is the fastest, it really depends on the amount of CPU available, so an application that is IO-bound will have different results than one which is CPU bound. The video size itself affects whether it's CPU bound, so if we use a smaller video file in a minimal benchmark, we'll get almost the same optimal video reading speed no matter what library we use. Working with FFMPEG directly also has a lot more flexibility - coming back to the topic of this thread, if we want better control |
@bml1g12 Sorry to break it to you but imutils is never fast as it appears to, as it has problem of duplicate frames and your benchmarks lack sanity check. If you include checking every frame is distinct and not empty, I'm sure your benchmarks will be flawed. I can't go into details but we all know opencv-python itself is slower than FFMPEG wrappers like |
Please stop hijacking this issue. This issue is about seeking to the wrong frame in OpenCV. Please use a different forum or issue, to discuss your speed benchmarking. This issue is not about speed. People (like me) would not mind the speed as long as it seek to the right frame. |
I agree, let's keep on topic here but I'd love to discuss further @abhiTronix elsewhere (To address your concerns I've updated the colab to prove no duplicate frames occur with the With regards to accurate frame seeking, I would argue benchmarking is still relevant, as there's no point in obtaining accurate frame seeking if it were slower than reading the file in serial (as we know we can read file in a serial frame-by-frame manner without using the set operation and get accurate frame seeking). Any python ffmpeg wrapper which offers us options, like Deffcode etc., seems like a great contribution to the field, allowing us more control over how to read video in Python |
When you need to seek, I have found calling |
As the thread starter... may I annotate my ceterum censeo? The main problem of the situation still isn't addressed by all the posts: There is a (probably wide used) method in opencv that returns This should be addressed first of all at opencv. 1st option 2nd option AFTER having done this first step it is time to check alternatives. So my kind question: |
Seems reliably seeking through video with OpenCV is a lost cause. Building on @Eugeny 's excellent tool posted above, I have made an alternative that uses pyav. Gist: https://gist.github.com/petered/db8e334c7aefdf367af1b11e6eefe733 Usage:
|
This is a very ugly bug that has been opened for more than 5 years. Any way to make it higher priority? Thanks. |
It seems that in my case, a conversion into the mkv container has helped:
|
CAP_PROP_POS_MSEC is not working correctly when cap.grab() is used to skip frames, instead of cap.read() |
The issue isn't the container. The default setting for ffmpeg is to output videos with a constant frame rate. Both mp4 and mkv files can have a variable frame rate. Re-encoding a video can be slow. Depending on the use case you are probably better of calling |
@alalek is there a bug fix ETA? thanks |
Any links to examples of video with a constant frame rate to actually test that OpenCV works well in this case? |
I've tried both mp4 and mkv and have seen how mkv is working decently while mp4 isn't. Also they're not re-encoding the video, they are actually copying it and just changing the container, so it's a fast operation that is usually limited by I/O. |
Any fix for this yet ? I see a very weird issue, |
As far as I know no - and wouldn't bet on it happening. Best bets as far as I know are pyav (works (mostly) but slow) or decord (fast but uses up too much memory for longer videos). If anyone comes up with a good solution that reliably and quickly seeks to specific video frames ... we're all ears. |
I encountered the same problem. Randomly accessing a frame with
Output:
Imageio.v3 doesn't have the problem. |
Example and confirmed effect:
http://answers.opencv.org/question/162781/videocaptureset-cap_prop_pos_frames-framenumber-not-exact-in-opencv-32-with-ffmpeg/
The text was updated successfully, but these errors were encountered: