Why opencv video reading fps is not same with video encrypted fps? - python

In OpenCV with Python, when the fps of the webcam and a video file in the directory are same, why does the video file play in fast forward whereas the webcam continues to show the frames at a normal rate? What role does the cv2.waitKey() function play here

The fps of a video file means how it was encrypted, how many frames contain within a second as the name reveals. For example, if extracted 1 second of this video will produce only that number of frames (images).
The corresponding fps of the web camera means how many frames that camera can capture in a second. If saved to a video file that would mean how many frames are contained within each 1-second span.
There is a third (probably hidden to you) concept here though. How fast the opencv can read a video file. Normally, and for typical resolutions on a modern computer this fps is larger than the actual video. So, your computer seem to playback the video in fast forward mode because it reads (and displays) frames in a faster pace than the video file's fps.
Theoretically, you can calculate the delay you should import to the video playback to force it to displayed with normal pace. I am not sure how easily you can accomplish that (in a scientific way and not trial and error mode).
Hope this clarifies the issue.

Related

Playing audio in sync with video with frames generated on the fly, real time. Plausible?

I'm a self taught python programmer working on a hobby project, but I'm having some difficulty and would like to address what I see as a potential XY problem.
My app takes an input of an audio file (converts it to wav) and produces visual representations of the audio (90x90, RGB, frames) in the form of numpy arrays. I used to save these frames to a video file using open-cv, then use ffmpeg to scale the video and add the (original, non-wav) audio over the top, but this meant waiting until the app had finished to play the file. I would like to be able to play the audio and display the frames as they are generated, in sync. My generation code takes at maximum 8ms of a 16ms frame (60fps), so I have a reasonable amount of cycles to play with.
From my research, I have found that SDL is the tool that is most appropriate to display frames at high speeds, and have managed to make a simple system to display frames 'in time', by brute-force pixel editing. I have also discovered that SDL can play audio, and it even seems that I could synchronize this with the video as I would like, via the callback function. However, being a decidedly non-c programmer, I am at a loss as to how to best to display frames, as directly assigning pixels cannot be the safest or fastest, and I would like to scale the frames as the are displayed. I am also at a loss as to how best to convert numpy arrays to textures efficiently, as well as how best to control the synchronicity of my generation code, the audio, and video frames.
I'm not specifically looking for an answer to any of those problems, though advice would be appreciated, I'm just making sure that this is a reasonable way forward. Is SDL/pysdl2 coupled with numpy appropriate in this scenario? Or is this asking too much from python overall?

Why does opencv Videocapture function read video frames with wrong pixel values?

I am capturing videos from a camera and saving them using the opencv VideoWriter function. I save the captured videos as uncompressed avi files. When I finish recording the video, I have another script that is supposed to read the video frame by frame, process the pixel values. However, when I try to read the frames of the saved video, the pixel values are off a bit.
For example, comparing the first frames of the video being written, and the video being read (supposed to be 100% identical), I notice that the pixel values are off by a small number (RGB values off by a small number, usually less than 5).
I have already made sure that I am using the exact same video codex when writing the video, and when reading the video (Check code below)
def write_video():
out = cv2.VideoWriter("encrypted.avi" ,cv2.VideoWriter_fourcc(*'XVID'),30, (640,480))
foreach frame:
out.write(frame)
def read_video():
cap = cv2.VideoCapture("encrypted.avi")
cap.set(cv2.CAP_PROP_FOURCC,cv2.VideoWriter_fourcc(*'XVID'))
while(cap.isOpened()):
ret, frame = cap.read()
For my application, the frames being written and read should match 100%. I have included an image highlighting the difference between the first frame in the video being written, and the video being read. Any help is much appreciated!
These are the compression artifacts, since you are using lossy compression. If you would like your frames match down to the last bit, write them as a sequence of .PNG files -- these are losslessly compressed and preserve everything. Beware that .PNG will take much more of your HDD space than compressed video.

OpenCV gives incorrect FPS and frame count of a video

I'm trying to read, do some processing and then save an .mp4 video using OpenCV in python, but cap.get(cv2.CAP_PROP_FPS) returns the wrong FPS for some videos.
So I'm not gonna go in to the full details of what the code does, because its irrelevant to the problem at hand. I've noticed the output video from my program plays too fast, and when debugging I decided to just see how it looks when I simply playback the input video.
So the playback code looks something like this:
cap = cv2.VideoCapture(video_path)
video_fps = cap.get(cv2.CAP_PROP_FPS)
#returns 49.8
while cap.isOpened():
ret, frame = cap.read()
if ret:
cv2.imshow('a', frame)
cv2.waitkey(int(1000/video_fps))
else:
break
But the video plays too fast, so I go right click -> properties -> details, and sure enough it says frames per seconds: 49... but I know most of my videos are 25 fps (which is about half of 49.8), so just out of curiosity I change the delay to twice as much: cv2.waitkey(int(2000/video_fps))
And suddenly the video plays in perfect speed.
Another oddity is that when I divide the result of cap.get(cv2.CAP_PROP_POS_FRAMES) by the length of the video in seconds, I get yet again 49.8 and since I know the length must be correct, I can only guess that OpenCV gets the number of frames wrong (?)
So my questions are:
1) What the hell is going on here?
2) Is there a better\more reliable way to check video fps and frame count?
I know this thread is old however people still experiencing this, it seems like it is an ongoing issue: https://github.com/opencv/opencv/issues/16821. I ran into this same issue with .mp4 and what solved it for me was exporting to .mov instead. Not sure why .mp4 is having issues but seems to be a common trend in the github issue

How do I prevent openCV from changing cameras?

I have a computer connected to two external cameras and am using the Python interface to openCV to do real-time video analysis for instrument control. I love it.
But there is an odd quirk: the numbers assigned to the two cameras seem to be switching. That is, my program will be working with the correct camera. Then, if I run it again, there is a decent probability that it will grab the other camera. To temporarily correct this I can toggle between the cameras by changing the integer in the command to initialize the camera:
cap = cv2.VideoCapture(0)
vs.
cap = cv2.VideoCapture(1)
or back again. But, no matter which number I choose, there is still a chance that I'll get the wrong camera. Do any of you have any ideas for how to choose the correct camera every time?

The simplest video streaming?

I have a camera that is taking pictures one by one (about 10 pictures per second) and sending them to PC. I need to show this incoming sequence of images as a live video in PC.
Is it enough just to use some Python GUI framework, create a control that will hold a single image and just change the image in the control very fast?
Or would that be just lame? Should I use some sort of video streaming library? If yes, what do you recommend?
Or would that be just lame?
No. It wouldn't work at all.
There's a trick to getting video to work. Apple's QuickTime implements that trick. So does a bunch of Microsoft product. Plus some open source video playback tools.
There are several closely-related tricks, all of which are a huge pain in the neck.
Compression. Full-sized video is Huge. Do the math 640x480x24-bit color at 30 frames per second. It adds up quickly. Without compression, you can't read it in fast enough.
Buffering and Timing. Sometimes the data rates and frame rates don't align well. You need a buffer of ready-to-display frames and you need a deadly accurate clock to get them do display at exactly the right intervals.
Making a sequence of JPEG images into a movie is what iPhoto and iMovie are for.
Usually, what we do is create the video file from the image and play the video file through a standard video player. Making a QuickTime movie or Flash movie from images isn't that hard. There are a lot of tools to help make movies from images. Almost any photo management solution can create a slide show and save it as a movie in some standard format.
Indeed, I think that Graphic Converter can do this.

Categories