Get images of a streaming video url with Python - python

I have this url
https://www.earthcam.com/js/video/embed.php?type=h264&vid=AbbeyRoadHD1.flv
And I want get frames from the streaming and save them in Python. Is this possible? I looked into the streamlink library, but I'm not sure if it will work.
Sorry for my bad English, thanks.
streams = streamlink.streams("https://www.earthcam.com/js/video/embed.php?type=h264&vid=AbbeyRoadHD1.flv")

Copied from this question: Python - Extracting and Saving Video Frames
Try this:
import cv2
vidcap = cv2.VideoCapture('https://www.earthcam.com/js/video/embed.php?type=h264&vid=AbbeyRoadHD1.flv')
success,image = vidcap.read()
count = 0
while success:
cv2.imwrite("frame%d.jpg" % count, image) # save frame as JPEG file
success,image = vidcap.read()
print('Read a new frame: ', success)
count += 1

Related

Read and extract keypoints from folder of videos opencv

I have a list of videos (10 sec each) in a folder and I'm trying to loop through each action video to extract keypoints and save them as json files.
path = "path to video folder"
for file in os.listdir(path):
cap = cv2.VideoCapture(path+file)
while cap.isOpened():
try:
ret, frame = cap.read()
I ran into a problem where the extracted data has some keypoints from other videos, and I just want to run this code, end with the stop time for the video is done, pause, start next video. How can I help correct this?
If you want to process multiple videos in turn you can check the ret (success) value of cap.read() to detect the end of each file. Here is a basic example you can start with:
import os
import cv2
path = "videos"
for file in os.listdir(path):
print(file)
cap = cv2.VideoCapture(path + '/' + file)
count = 0
while True:
ret, frame = cap.read()
# check for end of file
if not ret:
break
# process frame
count += 1
print(f"{count} frames read")
cap.release()

Python - How to save the *exact* video stream that my USB cam is streaming live?

I am using OpenCV 4.5.0 to stream a video from a USB webcam using the VideoCapture method of OpenCV. Here is the snippet of how I am reading the frames, processing them and then writing them to a file.
import cv2
import numpy as np
dev_id = 0
stream = cv2.VideoCapture(dev_id, cv2.CAP_V4L2)
fourcc = cv2.VideoWriter_fourcc(*'FMP4')
vpath = 'test.mp4'
writer = cv2.VideoWriter(vpath, fourcc, 30, (640,480), isColor=True)
if stream.isOpened():
rval, frame = stream.read()
else:
print('Could not open the stream for reading')
if not writer.isOpened():
print('Could not open the file for writing')
i = 0
while rval:
i += 1
with open('frame_{}.pkl'.format(i),'wb') as fout:
np.save(fout, frame)
writer.write(frame)
rval, frame = stream.read()
key = cv2.waitkey(1)
if key == 27: # ESC
break
writer.release()
My goal is to then read the video file that was written above and reproduce the exact same frames that I got during the live stream. I have not been able to find a way to write the live video stream to a file such that the frame extracted from the written video file matches exactly with the frame stored in the numpy array. In addition to FMP4 as the FourCC, I tried with MJPG, MP4V, XVID, LAGS, H264, MPG4. No luck so far. What am I doing wrong?
Here is how I am reading the video and comparing the frames:
vc = cv2.VideoCapture(vpath)
if vc.isOpened():
rval, frame_read = vc.read()
else:
print('Could not read video from the file')
j = 0
while rval:
j += 1
with open('frame_{}.pkl'.format(j),'rb') as fin:
frame_orig = np.load(fin)
if np.array_equal(frame_read, frame_orig):
print('same')
else:
print('different')
rval, frame_read = vc.read()
I have also tested if this is simply the indexing mismatch between the video writer and the video reader. It is not. This really looks like the difference caused by the codec used to write the frame to a file. Is there no codec which writes the same exact frame that is emitted by VideoCapture.read()?

Error creating new directories for video frames for different videos

Per title, I'm trying to write code to loop through multiple videos in a folder to extract their frames, then write each video's frames to their own new folder, e.g. video1 to frames_video1, video2 to frames_video2.
This is my code:
subclip_video_path = main_path + "\\subclips"
frames_path = main_path + "\\frames"
#loop through videos in file
for subclips in subclip_video_path:
currentVid = cv2.VideoCapture(subclips)
success, image = currentVid.read()
count = 0
while success:
#create new frames folder for each video
newFrameFolder = ("frames_" + subclips)
os.makedirs(newFrameFolder)
I get this error:
[ERROR:0] global C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-k8sx3e60\opencv\modules\videoio\src\cap.cpp (142) cv::VideoCapture::open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.4.0) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-k8sx3e60\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): P in function 'cv::icvExtractPattern'
What does this mean? How can I fix this?
You can't loop though string: for subclips in subclip_video_path:
You need to get the list of your videos:
from glob import glob
sub_clip_video_path = glob("sub_clip_video_path/*.mp4")
This means get all the .mp4 extension video files and store it in sub_clip_video_path variable.
My Result:
['sub_clip_video_path/output.mp4', 'sub_clip_video_path/result.mp4']
Since I'm sure the directory contains two .mp4 extension files, now I can continue.
You don't need to re-declare VideoCapture for each frame.
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
success, image = currentVid.read()
count = 0
After you declare VideoCapture read all the frames from the current video, then declare VideoCapture for the next video.
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
.
.
Don't use while success this will create an infinite loop.
If the first frame grabbed from the video, then the success variable returns True. When you say:
while success:
#create new frames folder for each video
newFrameFolder = ("frames_" + subclips)
os.makedirs(newFrameFolder)
You will create infinite amount of folder for the current frame.
Here my result:
import os
import cv2
from glob import glob
sub_clip_video_path = glob("sub_clip_video_path/*.mp4") # Each image extension is `.mp4`
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
success, image = currentVid.read()
if success:
newFrameFolder = "frames_video{}".format(count + 1)
if not os.path.exists(newFrameFolder):
os.makedirs(newFrameFolder)
image_name = os.path.join(newFrameFolder, "frame{}.png".format(image_counter + 1))
cv2.imwrite(image_name, image)
image_counter += 1
else:
break
I gathered all the videos using glob
While the current video is being read:
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
If the current frame successfully grabbed, then declare folder name. If the folder does not exist, create it.
if success:
newFrameFolder = "frames_video{}".format(count + 1)
if not os.path.exists(newFrameFolder):
os.makedirs(newFrameFolder)
Then declare the image name and save it.
image_name = os.path.join(newFrameFolder, "frame{}.png".format(image_counter + 1))
cv2.imwrite(image_name, image)
image_counter += 1

Why does my code using OpenCv extracts less number of frame from a video

When I used below built-in properties of OpenCv to count number of frame of a video, its shows correct result.
video = cv2.VideoCapture(path)
total = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
But, when I tried to save all those frames, its store less number of frames. Below is another code for saving frame-
def ExtractFrames(self, videoPath):
srcVideo = cv2.VideoCapture(videoPath)
try:
if not os.path.exists('VideoFrames'):
os.makedirs('VideoFrames')
except OSError:
print('Error: Creating directory.')
currentframe = 0
while (True):
success, image = srcVideo.read()
if success:
fileName = './VideoFrames/frame' + str(currentframe) + '.jpg'
self.lstVideoFrames.append(fileName)
cv2.imwrite(fileName, image)
currentframe += 1
else:
break

How to extract thermal frame from FLIR video export file?

I have a IR camera video file. I want to extract this video into n-frames. I followed normal opencv method to extract frames from video. like below,
import cv2
vidcap = cv2.VideoCapture('3.mp4')
success,image = vidcap.read()
count = 0
while success:
cv2.imwrite("frame%d.jpg" % count, image) # save frame as JPEG file
success,image = vidcap.read()
print('Read a new frame: ', success)
count += 1
It extracts image as a normal image, instead of thermal image.
I found that using below code.
import flirimageextractor
from matplotlib import cm
from glob import glob
flir = flirimageextractor.FlirImageExtractor(palettes=[cm.jet, cm.bwr, cm.gist_ncar])
for file_ in glob("images/*.jpg"):
flir.process_image(file_)
flir.save_images()
flir.plot()
it throws KeyError: 'RawThermalImageType'
Full stack trace
Traceback (most recent call last):
File "thermal_camera.py", line 8, in
flir.process_image(file_)
File "/usr/local/lib/python3.5/dist-packages/flirimageextractor/flirimageextractor.py", line 101, in process_image
if self.get_image_type().upper().strip() == "TIFF":
File "/usr/local/lib/python3.5/dist-packages/flirimageextractor/flirimageextractor.py", line 133, in get_image_type
return json.loads(meta_json.decode())[0]["RawThermalImageType"]
KeyError: 'RawThermalImageType'
But the above code works well for sample thermal images. Which means i am not extracting frame from the video as a proper frame.
How to extract frame from FLIR video without losing thermal(raw) information?
Just export the movie from the Flir Research Software as a .wmv file then it will work just fine.
import cv2
vidcap = cv2.VideoCapture('3.wmv')
success,image = vidcap.read()
count = 0
while success:
cv2.imwrite("frame%d.jpg" % count, image) # save frame as JPEG file
success,image = vidcap.read()
print('Read a new frame: ', success)
count += 1

Categories