Moviepy : How to read greyscale movies frame by frame? - python

Disclaimer : I have no experience in computer vision or image processing, but I need to process videos to obtain data for machine learning.
I wish to read a greyscale movie (I made it using greyscale images) - frame by frame using moviepy. For further processing, I need greyscale frames. Here is my code:
clip = VideoFileClip('movie.mp4')
count =1
for frames in clip.iter_frames():
print frames.shape
count+=1
print count
The frame shapes come out to be (360L, 480L, 3L) while I was expecting (360L, 480L). And this puzzles me. Is there a way to get the "expected" shape? Python OpenCV ideas may work too, but I would prefer moviepy.

If your are dealing with videos and images, OpenCV is your friend:
import cv2
from moviepy.editor import VideoFileClip
clip = VideoFileClip('movie.mp4')
count =1
for frames in clip.iter_frames():
gray_frames = cv2.cvtColor(frames, cv2.COLOR_RGB2GRAY)
print frames.shape
print gray_frames.shape
count+=1
print count

Related

How do I capture images from rtsp stream and save them without being corrupted?

I'm trying to use python to capture a photo from my ip cameras every 1 minute and save it as a file for later use.
I'm still not good at python and I don't get why some of the times I get the right image and sometimes I get a corrupted gray image.
I'm using hikvision api to get the rtsp stream and while the stream is working sometimes the images are still fully gray.
Here is the code I wrote:
import cv2
import time
count = 0
while True:
for x in range(1, 9):
count = count +1
RTSP_URL = f'rtsp://user:password#ip:port/ISAPI/Streaming/Channels/{x}01'
cap = cv2.VideoCapture(RTSP_URL, cv2.CAP_FFMPEG)
result, image = cap.read()
if result:
cv2.imwrite(f"pictures/{x}{count}.png", image)
time.sleep(60)
I would be happy to hear suggestions to find the best way to do this task.

Displayed image from a time frame of a video has the wrong color [duplicate]

This question already has answers here:
OpenCV giving wrong color to colored images on loading
(7 answers)
Closed last year.
i tried to extract a time frame of a video, and show it as image(JPEG). But unfortunately the displayed image using PIL.Image.fromarray() is bluer than it supposed to be. the tricky part is, when i save it first (using cv2.imwrite) and open that new file using PIL.Image.open(), the image has the right color.
I thought it has something to do with the RGB array composition, but then i checked it, and both array (direct from the frame and from the Image.open()) are exactly the same.
Is there anything i can do to show the right image without saving it as an external file beforehand?
Thank you.
def TimeFrame(file, tf):
capture = cv2.VideoCapture(file)
frameCount = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
capture.set(cv2.CAP_PROP_POS_FRAMES, tf)
_, frame = capture.read()
directTF = Image.fromarray(frame)
cv2.imwrite("12345678999.jpg", frame)
image = Image.open("12345678999.jpg")
note: file is the name of the video and tf is the certain timeframe that you want to extract the image from.
OpenCV uses BGR as its default colour order for images
Use cv2.cvtColor(img, cv2.COLOR_BGR2RGB) before displaying
OpenCV uses BGR, PIL uses RGB.
You might want to try
directTF = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
to have OpenCV flip those channels before you ask PIL to read the array.

Extract key frames from GIF using Python

I want to compress a GIF image by extracting 15 frames from the GIF that preferably should be distinct.
I'm using Python and Pillow library and I didn't find any way to get the number of frames a GIF has in the Pillow docs. Neither did I find how to extract a specific frame from a GIF, because Pillow restricts that.
Is there any way to extract frames without iterating through each frame consequently?
Is there a more advanced Python library for GIF processing?
Here is an extension of #radarhere's answer that divides the .gif into num_key_frames different parts and saves each part to a new image.
from PIL import Image
num_key_frames = 8
with Image.open('somegif.gif') as im:
for i in range(num_key_frames):
im.seek(im.n_frames // num_key_frames * i)
im.save('{}.png'.format(i))
The result is somegif.gif broken into 8 pieces saved as 0..7.png.
For the number of frames, you are looking for n_frames. Take a look at here.
from PIL import Image
im = Image.open('test.gif')
print("Number of frames: "+str(im.n_frames))
For extracting a single frame -
im.seek(20)
im.save('frame20.jpg')
The real working solution to extract proper frames of any GIF file:
BigglesZX/gifextract.py
If you have tf imported you can:
def load_gif(file_path):
with tf.io.gfile.GFile(file_path, 'rb') as f:
video = tf.io.decode_gif(f.read())
return np.array(video)

Extract foreground from individual frames using opencv for python

The problem
I'm working with a camera that posts a snapshot to the web every 5 seconds or so. The camera is monitoring a line of people. I'd like my script to be able to tell me how long the line of people is.
What I've tried
At first, I thought I could do this using BackgroundSubtractorMOG, but this is just producing a black image. Here's my code for that, modified to use an image instead of a video capture:
import numpy as np
import cv2
frame = cv2.imread('sample.jpg')
fgbg = cv2.BackgroundSubtractorMOG()
fgmask = fgbg.apply(frame)
cv2.imshow('frame', fgmask)
cv2.waitKey()
Next, I looked at foreground extraction on an image, but this is interactive and doesn't suit my use case of needing the script to tell me how long the line of people is.
I also tried to use peopledetect.py, but since the image of the line is from an elevated position, that script doesn't detect any people.
I'm brand new to opencv, so any help is greatly appreciated. I can supply any additional details upon request.
Note:
I'm not so much looking for someone to solve the overall problem, as I am just trying to figure out a way to separate out the people from the background. However, I am open to approaching the problem a different way if you think you have a better solution.
EDIT: Here's a sample image as requested:
I figured it out! #QED helped me get there. Basically, you can't do this with just one image. You need AT LEAST 2 frames to compare so the algorithm can tell what's different (foreground) and what's the same (background). So I took 2 frames and looped through them to "train" the algorithm. Here's my code:
import numpy as np
import cv2
i = 1
while(1):
fgbg = cv2.BackgroundSubtractorMOG()
while(i < 3):
print 'img' + `i` + '.jpg'
frame = cv2.imread('img' + `i` + '.jpg')
fgmask = fgbg.apply(frame)
cv2.imshow('frame', fgmask)
i += 1
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cv2.destroyAllWindows()
And here's the result from 2 consecutive images!

Image processing 1 bit images

I am trying to understand the basics for image processing an image of a corridor. I have have used PIL to convert find the edges in an image, then I have converted it to a 1 bit image. I know what I want to be able to extract - the longest horizontal and diagonal lines that can be found in the image. Any ideas?
from PIL import *
import Image, ImageFilter
im = im.open("c:\Python26\Lib\site-packages\PIL\corridor.jpg")
imageInfo=list(im.getdata())
im.putdata(imageInfo)
print pic.size
for i in imageInfo2[180:220]:
if i==0:
print "This is a BLACK pixel"
elif i==255:
print "This is a WHITE pixel"
else:
print "ERROR"
First don't call them 1 bit images - that normally refers to images (like icons) where each pixel is 1bit and so 8pixels can be packed into a single byte.
Images with only two levels are normally called 'binary' in image processing.
Now you only have to learn the science of image processing !
A good place to start is opencv a free image processing library that also works with python and interfaces reasonably well with PIL.
You shoudl also read their book - or one of the other good books on image processing

Categories