I'm trying to make python screen recorder that outputs AVI file. The loop should stop after pressing 'q' but that doesn't work. When I interrupt the program with Ctrl + C, it doesn't output anything either. I'm using Mac OS.
import cv2
import numpy as np
import pyautogui
SCREEN_SIZE = (1440, 900)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("output2.avi", fourcc, 20.0, (SCREEN_SIZE))
while True:
img = pyautogui.screenshot()
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
out.write(frame)
cv2.imshow("screenshot", frame)
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
out.release()
I would very much appreciate your advice ;)
Here (OpenCV videowrite doesn't write video) i found the most commont problem is that it doesn't save if the resolution is wrong.
To be sure you are using the right resolution from your screen use SCREEN_SIZE = pyautogui.size()
The complete code would be:
import cv2 as cv2
import numpy as np
import pyautogui
SCREEN_SIZE = pyautogui.size() # changed this line
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("output2.avi", fourcc, 20.0, SCREEN_SIZE)
while True:
img = pyautogui.screenshot()
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
out.write(frame)
cv2.imshow("screenshot", frame)
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
out.release()
Related
I want to save a video after converting to gray scale. I don't know where exactly put the line out.write(gray_video). I use jupyter notebook with Python 3, and the Opencv library.
the code is:
import cv2
import numpy as np
video = cv2.VideoCapture("video1.mp4")
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('out_gray_scale.mp4', fourcc, 10.0, (640, 480),0)
while (True):
(ret, frame) = video.read()
if not ret:
print("Video Completed")
break
# Convert the frames into Grayscaleo
gray_video = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#writing
gray_frame = cv2.flip(gray_video, 0)
out.write(gray_video) #it suppose to save the gray video
#Show the binary frames
if ret == True:
cv2.imshow("video grayscale",gray_video)
#out.write(gray_video)
# Press q to exit the video
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
video.release()
cv2.destroyAllWindows()
The working video writer module of OpenCV depends on three main things:
the available/supported/installed codecs on the OS
getting the right codec and file extension combinations
the input video resolution should be same as output video resolution otherwise resize the frames before writing
If any of this is wrong openCV will probably write a very small video file which will not open in video player. The following code should work fine:
import cv2
import numpy as np
video = cv2.VideoCapture("inp.mp4")
video_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) # float `width`
video_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) # float `height`
video_fps = int(video.get(cv2.CAP_PROP_FPS))
print(video_width, video_height, video_fps)
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
out = cv2.VideoWriter('out_gray_scale1.avi', fourcc, video_fps, (video_width, video_height),0)
while (True):
ret, frame = video.read()
if not ret:
print("Video Completed")
break
# Convert the frames into Grayscale
gray_video = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#Show the binary frames
if ret == True:
cv2.imshow("video grayscale",gray_video)
#Writing video
out.write(gray_video)
# Press q to exit the video
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
video.release()
out.release()
cv2.destroyAllWindows()
I read all pictures from my pic directory and then convert them each to gray-scale with canny edge detections before writing it all to a video.
But, when I use my video software to play it, it shows a green background, and I can't read video frames from it. Could someone show me how to solve it?
Sample code
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
fourcc = cv.VideoWriter_fourcc(*"I420")
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0)
for pic in glob.glob1("./pic/", "A*"):
img = cv.imread(f"./pic/{pic}", -1)
edge = cv.Canny(img, 100, 200)
edge = cv.resize(edge, (640, 480))
out.write(edge)
out.release()
# Cant read video frame here:
cap = cv.VideoCapture("t2.avi")
ret, frame = cap.read()
if ret:
plt.imshow(frame)
else:
print("end")
cap.release()
Video plays with green background
It looks like a compatibility issue between I420 FOURCC and Grayscale format.
Replace fourcc = cv.VideoWriter_fourcc(*"I420") with:
fourcc = cv.VideoWriter_fourcc(*"GREY")
Note:
I am using OpenCV 4.5.5 in Windows 10, and it's working with "GREY".
I am not sure it's going to work in all platforms and versions.
I420 applies colored video.
You may use I420 with colored video:
Replace out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0) with:
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 1)
Convert edge to BGR before writing:
edge = cv.cvtColor(edge, cv.COLOR_GRAY2BGR)
out.write(edge)
Code sample using "GREY" FOURCC:
import numpy as np
import cv2 as cv
#import matplotlib.pyplot as plt
import glob
#fourcc = cv.VideoWriter_fourcc(*"I420")
fourcc = cv.VideoWriter_fourcc(*"GREY")
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0)
for pic in glob.glob1("./pic/", "A*"):
img = cv.imread(f"./pic/{pic}", -1)
edge = cv.Canny(img, 100, 200)
edge = cv.resize(edge, (640, 480))
out.write(edge)
out.release()
# Cant read video frame here:
cap = cv.VideoCapture("t2.avi")
while True:
ret, frame = cap.read()
if ret:
#plt.imshow(frame)
cv.imshow('frame', frame)
cv.waitKey(1000)
else:
print("end")
cap.release()
break
cv.destroyAllWindows()
i am trying to play a video using cv2 but it's only showing one frame and the video disappears
import cv2
img_file = 'car image.jpg'
video = cv2.VideoCapture('Tesla Dashcam AccidentTrim.mp4')
while True:
(read_successful, frame) = video.read()
if read_successful:
grayscaled_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
else:
break
classifier_file = 'car_detector.xml'
#Display the image with the faces spotted
cv2.imshow('Newton Caffrey Face Detector', grayscaled_frame)
#Don't Autoclose here (wait here in the code and listen for a key press)
cv2.waitKey(1)
I used the following code for displaying the video using cv2. It will keep displaying frames untill video ends. hope this will work for you, peace!
import cv2
cap = cv2.VideoCapture("Video.mp4")
width = 400
height = 300
num = 0
while True:
ret, frame = cap.read()
if ret:
frame = cv2.resize (frame, (width, height))
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xff == ord('q'):
break
cv2.destroyAllWindows()
I tried to save a video after it changes resolution to 300x300 on Python, but my video can't play after saving with
0xc10100be error: "This file isn't playable. That might be because the file type is unsupported, the file extension is incorrect, or the file is corrupt."
Here is my program:
import numpy as np
import cv2
cap = cv2.VideoCapture("F:\\mi\\Camera\\2b7d9eccaddffffe3c9ba70b7fe6c12e(0).mp4")
cv2.namedWindow("vid1", 0)
cv2.resizeWindow("vid1", 300,300)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (300,300))
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow('vid1',frame)
out.write(frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
What is wrong?
after asking my teacher about this problem, He fixed my program:
import numpy as np
import cv2
cap = cv2.VideoCapture("F:\\mi\\Camera\\2b7d9eccaddffffe3c9ba70b7fe6c12e(0).mp4")
cv2.namedWindow('frame',0)
cv2.resizeWindow('frame',300,300)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (300,300))
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
vidout=cv2.resize(frame,(300,300)) #create vidout funct. with res=300x300
out.write(vidout) #write frames of vidout function
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
Thanks for your attention about my question!
I appears to me that you're not doing anything with "out".
You should add:
out.write(frame)
inside the loop.
I'm using Python 2.7 and OpenCV 2.4.9.
I need to capture the current frame that is being shown to the user and load it as an cv::Mat object in Python.
Do you guys know a fast way to do it recursively?
I need something like what's done in the example below, that captures Mat frames from a webcam recursively:
import cv2
cap = cv2.VideoCapture(0)
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow('WindowName', frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
cap.release()
cv2.destroyAllWindows()
break
In the example it's used the VideoCapture class to work with the captured image from the webcam.
With VideoCapture.read() a new frame is always being readed and stored into a Mat object.
Could I load a "printscreens stream" into a VideoCapture object? Could I create a streaming of my computer's screen with OpenCV in Python, without having to save and delete lots of .bmp files per second?
I need this frames to be Mat objects or NumPy arrays, so I can perform some Computer Vision routines with this frames in real time.
That's a solution code I've written using #Raoul tips.
I used PIL ImageGrab module to grab the printscreen frames.
import numpy as np
from PIL import ImageGrab
import cv2
while(True):
printscreen_pil = ImageGrab.grab()
printscreen_numpy = np.array(printscreen_pil.getdata(),dtype='uint8')\
.reshape((printscreen_pil.size[1],printscreen_pil.size[0],3))
cv2.imshow('window',printscreen_numpy)
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
I had frame rate problems with other solutions, mss solve them.
import numpy as np
import cv2
from mss import mss
from PIL import Image
mon = {'top': 160, 'left': 160, 'width': 200, 'height': 200}
sct = mss()
while 1:
sct.get_pixels(mon)
img = Image.frombytes('RGB', (sct.width, sct.height), sct.image)
cv2.imshow('test', np.array(img))
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
This is the updated answer for the answer by #Neabfi
import time
import cv2
import numpy as np
from mss import mss
mon = {'top': 160, 'left': 160, 'width': 200, 'height': 200}
with mss() as sct:
# mon = sct.monitors[0]
while True:
last_time = time.time()
img = sct.grab(mon)
print('fps: {0}'.format(1 / (time.time()-last_time)))
cv2.imw('test', np.array(img))
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
And to save to a mp4 video
import time
import cv2
import numpy as np
from mss import mss
def record(name):
with mss() as sct:
# mon = {'top': 160, 'left': 160, 'width': 200, 'height': 200}
mon = sct.monitors[0]
name = name + '.mp4'
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
desired_fps = 30.0
out = cv2.VideoWriter(name, fourcc, desired_fps,
(mon['width'], mon['height']))
last_time = 0
while True:
img = sct.grab(mon)
# cv2.imshow('test', np.array(img))
if time.time() - last_time > 1./desired_fps:
last_time = time.time()
destRGB = cv2.cvtColor(np.array(img), cv2.COLOR_BGRA2BGR)
out.write(destRGB)
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
record("Video")
Here's the Python 3 Implementation
This Function finds the Application in the List of Running Applications:
def capture_dynamic():
toplist, winlist = [], []
def enum_cb(hwnd, results):
winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
win32gui.EnumWindows(enum_cb, toplist)
wnd = [(hwnd, title) for hwnd, title in winlist if 'spotify' in title.lower()]
if wnd:
wnd = wnd[0]
hwnd = wnd[0]
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
return img
else:
return None
This Function Displays the Images until the Letter 'q' is pressed:
import cv2
import numpy as np
while(True):
# Dynamic Version
screen_grab = capture_dynamic()
if(screen_grab == None):
print("No Window Found! Please Try Again")
break
screen_grab = np.array(screen_grab)
cv2.imshow('window',cv2.cvtColor(screen_grab, cv2.COLOR_BGR2RGB))
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
Make sure the Application you want to capture should be in the Foreground and not behind any other Application
Please Upvote!