I was wondering if anyone could help me out a bit with this problem I cannot solve. I am using Pafy to search Youtube from a text file that has a song name written in it and that gets a new song every few minutes.
I am using Watchdog to watch for file modification and when i first run the script, watchdog catches the file modification and runs the pafy and opencv script, but it won't do the same when the following modification occurs.
#watchdog file change monitoring
class MyHandler(FileSystemEventHandler):
def on_modified(self, event):
print ("Received modified event - %s." % event.src_path)
cv2.destroyAllWindows()
if __name__ == "__main__":
event_handler = MyHandler()
observer = Observer()
observer.schedule(event_handler, path='//PLAYING', recursive=False)
observer.start()
try:
while True:
#read PLAYING.txt
PLAYING = open('//PLAYING.txt').readline()
PLAYING = PLAYING[7:]
print (PLAYING)
#search youtube based on NowOnAir.txt
query_string = urllib.parse.urlencode({"search_query" : PLAYING})
html_content = urllib.request.urlopen("http://www.youtube.com/results?" + query_string)
search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
link = ('http://www.youtube.com/watch?v=' + search_results[0])
videoPafy = pafy.new(link)
best = videoPafy.getbestvideo()
videompv = best.url
#opencv youtube video output
video = cv2.VideoCapture(videompv)
while(video.isOpened()):
ret, frame = video.read()
resize = cv2.resize(frame, (1680, 1050))
gray = cv2.cvtColor(resize, cv2.COLOR_BGR2GRAY)
result = cv2.addWeighted(image, 0.2, resize, 0.8, 0)
cv2.namedWindow('frame', 0)
cv2.resizeWindow('frame', 1680, 1050)
cv2.imshow('frame', result)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
So, I what I want to happen is, when file gets modified, I want openCV to close the window and open a new one with the new youtube query result.
Any suggestions would be quite welcome, thank You in advance.
If the file is just updated once per track change, then you could check the timestamp of the file for modification and use that to trigger your search.
import os.path
import time
last_modified = time.ctime(os.path.getmtime(file))
while True:
time.sleep(1)
if last_modified != time.ctime(os.path.getmtime(file)):
# search for the track on youtube
last_modified = time.ctime(os.path.getmtime(file))
Related
I want to exact frames from a screen recorded video file, and those frames are used to object detection process later. I already have a python code which can simply exact frames and save them inside my local storage.
import os
import numpy as np
import cv2
from glob import glob
def create_dir(path):
try:
if not os.path.exists(path):
os.makedirs(path)
except OSError:
print(f"ERROR: creating directory with name {path}")
def save_frame(video_path, save_dir, gap=10):
name = video_path.split("/")[-1].split(".")[0]
save_path = os.path.join(save_dir, name)
create_dir(save_path)
cap = cv2.VideoCapture(video_path)
idx = 0
while True:
ret, frame = cap.read()
if ret == False:
cap.release()
break
if idx == 0:
cv2.imwrite(f"{save_path}/{idx}.png", frame)
else:
if idx % gap == 0:
cv2.imwrite(f"{save_path}/{idx}.png", frame)
idx += 1
if __name__ == "__main__":
video_paths = glob("C:/Users/Asus/Documents/4th year/Research/Frame Differencing/video to frame/capture1.mp4")
save_dir = "save"
for path in video_paths:
save_frame(path, save_dir, gap=50)
I want to deploy this to get endpoint (HTTP request). The Request input should be a video file and response should be frames of it. Please help me to deploy this
I have a tello ryze drone, which has got a camera onboard. I am connecting to the drone in order to receive the video over wifi. My system is windows 10 and I am using python 2.7.
I am receiving a h264 bytecode and i use the libh264 decoder from tello in order to get the frames of the video, which i also display in my UI.
What i need to do is to save this video as a file on my computer and i have problems with this. I am able to make a snapshot with opencv and save it as an image, this isn't a problem. But making a video isn't working for some reason.
I read many posts here like this one but they dont work out for me. I am getting either an error or i get a very small video file, which doesnt open.
My Frames are List of List with RGB values like:
[[255,200,100][55,200,100][25,20,100]]
Here is my code for a better understanding in order to help me
This is the UI Part(i just copy here the needed code only):
def videoLoop(self):
try:
# start the thread that get GUI image and draw skeleton
time.sleep(0.5)
self.sending_command_thread.start()
while not self.stopEvent.is_set():
system = platform.system()
# read the frame for GUI show
self.frame = self.drone.read()
if self.frame is None or self.frame.size == 0:
continue
# transfer the format from frame to image
image = Image.fromarray(self.frame)
# we found compatibility problem between Tkinter,PIL and Macos,and it will
# sometimes result the very long preriod of the "ImageTk.PhotoImage" function,
# so for Macos,we start a new thread to execute the _updateGUIImage function.
if system == "Windows" or system == "Linux":
self.refreshUI(image)
else:
thread_tmp = threading.Thread(target=self.refreshUI, args=(image,))
thread_tmp.start()
time.sleep(0.03)
except RuntimeError as e:
print("[INFO] caught a RuntimeError")
def refreshUI(self, image):
image = ImageTk.PhotoImage(image)
# if the imagePanel none ,we need to initial it
if self.imagePanel is None:
self.imagePanel = tki.Label(image=image)
self.imagePanel.image = image
self.imagePanel.pack(side="left", fill="both",
expand="yes", padx=10, pady=10)
# otherwise, simply update the imagePanel
else:
self.imagePanel.configure(image=image)
self.imagePanel.image = image
def takeSnapshot(self):
# grab the current timestamp and use it to construct the filename
ts = datetime.datetime.now()
filename = "{}.jpg".format(ts.strftime("%d-%m-%Y_%H-%M-%S"))
p = os.path.sep.join((self.screenShotPath, filename))
# save the file
cv2.imwrite(p, cv2.cvtColor(self.frame, cv2.COLOR_RGB2BGR))
print("[INFO] saved {}".format(filename))
Below you can find the Tello code (only the needed part too):
def read(self):
"""Return the last frame from camera."""
if self.is_freeze:
return self.last_frame
else:
return self.frame
def video_freeze(self, is_freeze=True):
"""Pause video output -- set is_freeze to True"""
self.is_freeze = is_freeze
if is_freeze:
self.last_frame = self.frame
def _receive_video_thread(self):
"""
Listens for video streaming (raw h264) from the Tello.
Runs as a thread, sets self.frame to the most recent frame Tello captured.
"""
packet_data = b''
while True:
try:
res_string, ip = self.socket_video.recvfrom(2048)
packet_data += res_string
# end of frame
if len(res_string) != 1460:
for frame in self._h264_decod(packet_data):
self.frame = frame
packet_data = b''
except socket.error as exc:
print(("Caught exception sock.error : %s" % exc))
def _h264_decod(self, packet_data):
"""
decode raw h264 format data from Tello
:param packet_data: raw h264 data array
:return: a list of decoded frame
"""
res_frame_list = []
frames = self.decoder.decode(packet_data)
for framedata in frames:
(frame, w, h, ls) = framedata
if frame is not None:
# print ('frame size %i bytes, w %i, h %i, linesize %i' % (len(frame), w, h, ls))
frame = np.frombuffer(frame, dtype=np.ubyte, count=len(frame))
frame = (frame.reshape((h, ls // 3, 3)))
frame = frame[:, :w, :]
res_frame_list.append(frame)
return res_frame_list
It would be very kind of you if someone could help me write a method like this pseudocode:
def saveVideo(self, frame_or_whatever_i_need_here):
out = cv2.VideoWriter('output.avi_or_other_format', -1, 20.0, (640,480))
out.write(frame_or_whatever_i_need_here)
out.release()
Edit 1:
i found an option making a video out of my snapshots, this means that i coud make snapshot over a thread and later save them to a video. That would be an option. The problem is, that it would consume too much space in the disk. The workaround link is here
I found the solution, so i will post it here if someone needs the same thing. I used the following blog and modified the code to do my work, you can find the post here
self.frame = None
self.frame_array = []
def videoLoop(self):
try:
# start the thread that get GUI image and draw skeleton
time.sleep(0.5)
self.sending_command_thread.start()
while not self.stopEvent.is_set():
system = platform.system()
# read the frame for GUI show
self.frame = self.drone.read()
self.frame_array.append(self.frame)
if self.frame is None or self.frame.size == 0:
continue
# transfer the format from frame to image
image = Image.fromarray(self.frame)
if system == "Windows" or system == "Linux":
self.refreshUI(image)
else:
thread_tmp = threading.Thread(target=self.refreshUI, args=(image,))
thread_tmp.start()
time.sleep(0.03)
except RuntimeError as e:
print("[INFO] caught a RuntimeError")
def convert_frames_to_video(self, pathOut, fps):
size = (self.videoWidth, self.videoHeight)
out = cv2.VideoWriter(pathOut, cv2.VideoWriter_fourcc(*'DIVX'), fps, size)
for i in range(len(self.frame_array)):
# writing to a image array
out.write(self.frame_array[i])
out.release()
def onClose(self):
print("[INFO] closing...")
self.convert_frames_to_video('video.avi', 25.0)
self.stopEvent.set()
del self.drone
self.root.quit()
I'm currently wanting to use an old piece of Python code called python slideshow with time and weather (github). I'm using a Raspberry Pi and I've got it all setup and it works perfectly in landscape (normal) mode. This is a slideshow application which has a weather and time overlay developed on Pygame.
I want to use the application in portrait, however when I rotate my screen in the /boot/config.txt using display_rotate=1 (or 3) and restart the slideshow, everything appears to work, the weather overlay appears in the bottom left/right as it should, however as soon as any part of the weather or clock or day update, it prints the text over itself.
Has anyone got an idea of what might be causing this behaviour? I can't see anything in the code. Here's the python file from Git below and I have attached a screenshot of the strange behavour[image showing text overlay issue in the clock in this instance][1]:
Python slideshow with time and weather on github
#!/usr/bin/env python
"""
A pygame program to show a slideshow of all images buried in a given directory.
Originally Released: 2007.10.31 (Happy halloween!)
"""
from __future__ import division
import argparse
import os
import stat
import sys
import time
import datetime
import pygame
from pygame.locals import QUIT, KEYDOWN, K_ESCAPE
#weather
import pyowm
file_list = [] # a list of all images being shown
title = "pgSlideShow | My Slideshow!" # caption of the window...
waittime = 5 # default time to wait between images (in seconds)
def walktree(top, callback):
"""recursively descend the directory tree rooted at top, calling the
callback function for each regular file. Taken from the module-stat
example at: http://docs.python.org/lib/module-stat.html
"""
for f in os.listdir(top):
pathname = os.path.join(top, f)
mode = os.stat(pathname)[stat.ST_MODE]
if stat.S_ISDIR(mode):
# It's a directory, recurse into it
walktree(pathname, callback)
elif stat.S_ISREG(mode):
# It's a file, call the callback function
callback(pathname)
else:
# Unknown file type, print a message
print 'Skipping %s' % pathname
def addtolist(file, extensions=['.png', '.jpg', '.jpeg', '.gif', '.bmp']):
"""Add a file to a global list of image files."""
global file_list # ugh
filename, ext = os.path.splitext(file)
e = ext.lower()
# Only add common image types to the list.
if e in extensions:
print 'Adding to list: ', file
file_list.append(file)
else:
print 'Skipping: ', file, ' (NOT a supported image)'
def input(events):
"""A function to handle keyboard/mouse/device input events. """
for event in events: # Hit the ESC key to quit the slideshow.
if (event.type == QUIT or
(event.type == KEYDOWN and event.key == K_ESCAPE)):
pygame.quit()
def timeSince(lastTime,interval):
if (time.time() - lastTime)>=interval:
return True
else:
return False
def main(startdir="."):
global file_list, title, waittime
lastSwitch=time.time()
lastWeather=time.time()
owm = pyowm.OWM('4cc9ae1d116c7e70c145252ab605f260')
observation = owm.weather_at_place('Ottawa,CA')
w = observation.get_weather()
temperature=(w.get_temperature('celsius'))['temp']
status=w.get_status()
#print w
pygame.init()
# Test for image support
if not pygame.image.get_extended():
print "Your Pygame isn't built with extended image support."
print "It's likely this isn't going to work."
sys.exit(1)
walktree(startdir, addtolist) # this may take a while...
if len(file_list) == 0:
print "Sorry. No images found. Exiting."
sys.exit(1)
modes = pygame.display.list_modes()
print max(modes)
pygame.display.set_mode(max(modes))
screen = pygame.display.get_surface()
screen_width, screen_height= screen.get_size()
pygame.display.set_caption(title)
#pygame.display.toggle_fullscreen()
pygame.display.set_mode(max(modes),pygame.FULLSCREEN)
pygame.mouse.set_visible(0)
#create font
timeFont = pygame.font.Font("indulta/Indulta-SemiSerif-boldFFP.otf", 100)
dateFont = pygame.font.Font("indulta/Indulta-SemiSerif-boldFFP.otf", 60)
weatherFont = pygame.font.Font("indulta/Indulta-SemiSerif-boldFFP.otf", 60)
print str(waittime) +"wait time"
current = 0
num_files = len(file_list)
while(True):
try:
img = pygame.image.load(file_list[current])
img = img.convert()
tempX,tempY=img.get_size()
ratio =tempX/tempY
tempSize=(screen_width,int(screen_width/ratio))
print str(img.get_size())+" to "+ str(tempSize) +"and ratio: "+str(ratio)
# rescale the image to fit the current display
img = pygame.transform.scale(img, tempSize)
screen.blit(img, (0, 0))
#gets current weather
if timeSince(lastWeather,30):
observation = owm.weather_at_place('Ottawa,CA')
w = observation.get_weather()
temperature=(w.get_temperature('celsius'))['temp']
status=w.get_status()
print status
lastWeather=time.time()
print "updateing weather"
#gets the current time and displays it
timeText=datetime.datetime.now().strftime("%I:%M%p")
dateText=datetime.datetime.now().strftime("%B %d, %Y")
weatherText=str(int(temperature))+"`C "+status
timeLabel = timeFont.render(timeText, 1, (255,255,255))
dateLabel = dateFont.render(dateText, 1, (255,255,255))
weatherLabel = weatherFont.render(weatherText, 1, (255,255,255))
timeWidth, timeHeight= timeLabel.get_size()
dateWidth, dateHeight= dateLabel.get_size()
weatherWidth, weatherHeight= weatherLabel.get_size()
screen.blit(weatherLabel, (0, screen_height-weatherHeight))
screen.blit(timeLabel, (screen_width-timeWidth, screen_height-timeHeight-dateHeight))
screen.blit(dateLabel, (screen_width-dateWidth, screen_height-dateHeight))
pygame.display.flip()
input(pygame.event.get())
time.sleep(1/60)
except pygame.error as err:
print "Failed to display %s: %s" % (file_list[current], err)
sys.exit(1)
# When we get to the end, re-start at the beginning
if timeSince(lastSwitch,waittime):
current = (current + 1) % num_files;
lastSwitch=time.time()
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Recursively loads images '
'from a directory, then displays them in a Slidshow.'
)
parser.add_argument(
'path',
metavar='ImagePath',
type=str,
default='.',
nargs="?",
help='Path to a directory that contains images'
)
parser.add_argument(
'--waittime',
type=int,
dest='waittime',
action='store',
default=1,
help='Amount of time to wait before showing the next image.'
)
parser.add_argument(
'--title',
type=str,
dest='title',
action='store',
default="pgSlidShow | My Slideshow!",
help='Set the title for the display window.'
)
args = parser.parse_args()
#waittime = args.waittime
title = args.title
main(startdir=args.path)
I have found the answer. Adding the line screen.fill((0,0,0)) just above img = pygame.image.load(file_list[current])has fixed the issue.
Here are my goals.
Capture video continuously until 'q; is pressed
Every ten seconds save the video in created directory file
Continue step two until 'q' is pressed
I am executing the following code. But when creating files it's creating 6kb files and saying cannot play. I am fairly new to opencv and python. Not sure what I am missing. Running this code on pycharm with Python 3.6. Also the
cv2.imshow('frame',frame)
stops after ten seconds but recording is happening in background and files are created.
import numpy as np
import cv2
import time
import os
import random
import sys
fps=24
width=864
height=640
video_codec=cv2.VideoWriter_fourcc('D','I','V','X')
name = random.randint(0,1000)
print (name)
if (os.path.isdir(str(name)) is False):
name = random.randint(0,1000)
name=str(name)
name = os.path.join(os.getcwd(), str(name))
print('ALl logs saved in dir:', name)
os.mkdir(name)
cap = cv2.VideoCapture(0)
ret=cap.set(3, 864)
ret=cap.set(4, 480)
cur_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
start=time.time()
video_file_count = 1
video_file = os.path.join(name, str(video_file_count) + ".avi")
print('Capture video saved location : {}'.format(video_file))
while(cap.isOpened()):
start_time = time.time()
ret, frame = cap.read()
if ret==True:
cv2.imshow('frame',frame)
if (time.time() - start > 10):
start = time.time()
video_file_count += 1
video_file = os.path.join(name, str(video_file_count) + ".avi")
video_writer = cv2.VideoWriter(video_file,video_codec, fps,(int(cap.get(3)),int(cap.get(4))))
time.sleep(10)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
I want files with the recorded videos. Files are generated but size 6kb and nothing is being recorded.
You're almost there! Given that I understood what your goal is, and with minimal change to your code, here is what worked for me.
This writes a new video file every ten seconds while recording each frame into the current video.
import numpy as np
import cv2
import time
import os
import random
import sys
fps = 24
width = 864
height = 640
video_codec = cv2.VideoWriter_fourcc("D", "I", "V", "X")
name = random.randint(0, 1000)
print(name)
if os.path.isdir(str(name)) is False:
name = random.randint(0, 1000)
name = str(name)
name = os.path.join(os.getcwd(), str(name))
print("ALl logs saved in dir:", name)
os.mkdir(name)
cap = cv2.VideoCapture(0)
ret = cap.set(3, 864)
ret = cap.set(4, 480)
cur_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
start = time.time()
video_file_count = 1
video_file = os.path.join(name, str(video_file_count) + ".avi")
print("Capture video saved location : {}".format(video_file))
# Create a video write before entering the loop
video_writer = cv2.VideoWriter(
video_file, video_codec, fps, (int(cap.get(3)), int(cap.get(4)))
)
while cap.isOpened():
start_time = time.time()
ret, frame = cap.read()
if ret == True:
cv2.imshow("frame", frame)
if time.time() - start > 10:
start = time.time()
video_file_count += 1
video_file = os.path.join(name, str(video_file_count) + ".avi")
video_writer = cv2.VideoWriter(
video_file, video_codec, fps, (int(cap.get(3)), int(cap.get(4)))
)
# No sleeping! We don't want to sleep, we want to write
# time.sleep(10)
# Write the frame to the current video writer
video_writer.write(frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
break
cap.release()
cv2.destroyAllWindows()
A sign that the videos are being received at 6 kb, an error with the codec. You need to download opencv_ffmpeg.dll and place it in the Python3.2.1 folder and renamed to opencv_ffmpeg321.dll
This solved the problem for me, and before that, 5.6 kb videos were created, regardless of what I do. But the problem is deeper than it seems, it can still be connected with a mismatch in the resolution of the stream and the recording.
For OpenCV version X.Y.Z
opencv_ffmpeg.dll ==> opencv_ffmpegXYZ.dll
For 64-bit version of OpenCV X.Y.Z
opencv_ffmpeg.dll ==> opencv_ffmpegXYZ_64.dll
I am working with opencv and have two video source. I am using the following code. The code works sometimes and sometimes it does not work. Is there a problem with my code. How can I make the amends...
import cv2
Channel0 = cv2.VideoCapture(0)
IsOpen0, Image0 = Channel0.read()
Channel1 = cv2.VideoCapture(1)
IsOpen1, Image1 = Channel1.read()
while IsOpen0 and IsOpen1:
IsOpen0, Image0 = Channel0.read()
IsOpen1, Image1 = Channel1.read()
cv2.imshow("Webcamera",Image0)
cv2.imshow("Panasonic",Image1)
cv2.waitKey(10)
PS It always works when I use only one video source.
I think I figured out my error. For some reason the following code works. It must have been problem with threading...
import thread
import time
import cv2
def Webcamera():
Channel0 = cv2.VideoCapture(0)
IsOpen0, Image0 = Channel0.read()
while IsOpen0:
IsOpen0, Image0 = Channel0.read()
cv2.imshow("Webcamera",Image0)
cv2.waitKey(10)
if not IsOpen0:
time.delay(0.5)
print "Error opening Web camera"
def Panasonic():
Channel1 = cv2.VideoCapture(1)
IsOpen1, Image1 = Channel1.read()
while IsOpen1:
IsOpen1, Image1 = Channel1.read()
cv2.imshow("Panasonic",Image1)
cv2.waitKey(10)
if not IsOpen1:
time.sleep(0.5)
print "Error opening Panasonic"
try:
thread.start_new_thread(Webcamera,())
thread.start_new_thread(Panasonic,())
except:
print "Error: unable to start thread"
while 1:
pass