How to RTSP stream a video using Gstreamer and Python? - python

I have a code that currently takes one video and show it in screen using the gstreamer bindings for Python. I can seek the video when a "Forward" button is clicked at the player opened, and that is an important feature for me, hence the reason I don't want to use a parse to write a pipeline and send it to gst-launch.
What I want to do now is stream this video not only to a new opened window, but also (or only if I can't have both) via RTSP to open it at VLC or even another client over LAN. Is there any way to do that?
I am sorry, for the long code, but here it is:
import sys, os, time
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, Gtk
from gi.repository import GdkX11, GstVideo
class GTK_Main(object):
def __init__(self):
window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
window.set_title("Vorbis-Player")
window.set_default_size(500, -1)
window.connect("destroy", Gtk.main_quit, "WM destroy")
vbox = Gtk.VBox()
window.add(vbox)
self.entry = Gtk.Entry()
vbox.pack_start(self.entry, False, False, 0)
hbox = Gtk.HBox()
vbox.add(hbox)
buttonbox = Gtk.HButtonBox()
hbox.pack_start(buttonbox, False, False, 0)
rewind_button = Gtk.Button("Rewind")
rewind_button.connect("clicked", self.rewind_callback)
buttonbox.add(rewind_button)
self.button = Gtk.Button("Start")
self.button.connect("clicked", self.start_stop)
buttonbox.add(self.button)
forward_button = Gtk.Button("Forward")
forward_button.connect("clicked", self.forward_callback)
buttonbox.add(forward_button)
self.time_label = Gtk.Label()
self.time_label.set_text("00:00 / 00:00")
hbox.add(self.time_label)
window.show_all()
self.player = Gst.ElementFactory.make("playbin", "player")
bus = self.player.get_bus()
bus.add_signal_watch()
bus.enable_sync_message_emission()
bus.connect("message", self.on_message)
bus.connect("sync-message::element", self.on_sync_message)
def start_stop(self, w):
if self.button.get_label() == "Start":
filepath = self.entry.get_text().strip()
if os.path.isfile(filepath):
filepath = os.path.realpath(filepath)
self.butto
n.set_label("Stop")
self.player.set_property("uri", "file://" + filepath)
self.player.set_state(Gst.State.PLAYING)
time.sleep(1)
self.forward_callback(60)
else:
self.player.set_state(Gst.State.NULL)
self.button.set_label("Start")
def on_message(self, bus, message):
t = message.type
if t == Gst.MessageType.EOS:
self.player.set_state(Gst.State.NULL)
self.button.set_label("Start")
elif t == Gst.MessageType.ERROR:
self.player.set_state(Gst.State.NULL)
err, debug = message.parse_error()
print ("Error: %s" % err, debug)
self.button.set_label("Start")
def on_sync_message(self, bus, message):
if message.get_structure().get_name() == 'prepare-window-handle':
imagesink = message.src
imagesink.set_property("force-aspect-ratio", True)
imagesink.set_window_handle(self.movie_window.get_property('window').get_xid())
def rewind_callback(self, w):
rc, pos_int = self.player.query_position(Gst.Format.TIME)
seek_ns = pos_int - 10 * 1000000000
if seek_ns < 0:
seek_ns = 0
print ("Backward: %d ns -> %d ns" % (pos_int, seek_ns))
self.player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, seek_ns)
def forward_callback(self, w):
rc, pos_int = self.player.query_position(Gst.Format.TIME)
if type(w) == int:
seek_ns = w * 1000000000
else:
seek_ns = pos_int + 10 * 1000000000
print ("Forward: %d ns -> %d ns" % (pos_int, seek_ns))
self.player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, seek_ns)
def convert_ns(self, t):
# This method was submitted by Sam Mason.
# It's much shorter than the original one.
s,ns = divmod(t, 1000000000)
m,s = divmod(s, 60)
if m < 60:
return "%02i:%02i" %(m,s)
else:
h,m = divmod(m, 60)
return "%i:%02i:%02i" %(h,m,s)
GObject.threads_init()
Gst.init(None)
GTK_Main()
Gtk.main()
I found this code at this tutorial.

So, I ended up managing to make the link provided work. My problem was with the video's width and height, which must have the exact same values as the video you want to play, maybe something to do with opencv frames passing...also, the "is-live" property, which was set to true due to the use of webcam camera from the link's solution must be set to false (or not used at all since that is the default value) or else the video will begin with a certain delay in black screen. The code ended up being:
import cv2
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import Gst, GstRtspServer, GObject
class SensorFactory(GstRtspServer.RTSPMediaFactory):
def __init__(self, **properties):
super(SensorFactory, self).__init__(**properties)
self.cap = cv2.VideoCapture("path/to/video")
self.number_frames = 0
self.fps = 8
self.duration = 1 / self.fps * Gst.SECOND # duration of a frame in nanoseconds
self.launch_string = 'appsrc name=source block=true format=GST_FORMAT_TIME ' \
'caps=video/x-raw,format=BGR,width=1280,height=720,framerate={}/1 ' \
'! videoconvert ! video/x-raw,format=I420 ' \
'! x264enc speed-preset=ultrafast tune=zerolatency ! queue ' \
'! rtph264pay config-interval=1 name=pay0 pt=96 '.format(self.fps)
# streams to gst-launch-1.0 rtspsrc location=rtsp://localhost:8554/test latency=50 ! decodebin ! autovideosink
def on_need_data(self, src, lenght):
if self.cap.isOpened():
ret, frame = self.cap.read()
if ret:
data = frame.tostring()
#print(data)
buf = Gst.Buffer.new_allocate(None, len(data), None)
buf.fill(0, data)
buf.duration = self.duration
timestamp = self.number_frames * self.duration
buf.pts = buf.dts = int(timestamp)
buf.offset = timestamp
self.number_frames += 1
retval = src.emit('push-buffer', buf)
#print('pushed buffer, frame {}, duration {} ns, durations {} s'.format(self.number_frames,
# self.duration,
# self.duration / Gst.SECOND))
if retval != Gst.FlowReturn.OK:
print(retval)
def do_create_element(self, url):
return Gst.parse_launch(self.launch_string)
def do_configure(self, rtsp_media):
self.number_frames = 0
appsrc = rtsp_media.get_element().get_child_by_name('source')
appsrc.connect('need-data', self.on_need_data)
class GstServer(GstRtspServer.RTSPServer):
def __init__(self, **properties):
super(GstServer, self).__init__(**properties)
self.factory = SensorFactory()
self.factory.set_shared(True)
self.get_mount_points().add_factory("/test", self.factory)
self.attach(None)
GObject.threads_init()
Gst.init(None)
server = GstServer()
loop = GObject.MainLoop()
loop.run()

Related

How to get 1280x1280 from 3840x2160 output stream without scaling?

My goal is to get 1280x1280 frame from nvarguscamerasrc. The problem is that nvarguscamerasrc scaled the 3840x2160 frame to 1280x720. The consequence is that the bottom of the frame is always black.
JetsonCamera.py
def gstreamer_pipeline(
# Issue: the sensor format used by Raspberry Pi 4B and NVIDIA Jetson Nano B01 are different
# in Raspberry Pi 4B, this command
# $ libcamera-still --width 1280 --height 1280 --mode 1280:1280
# uses sensor format 2328x1748.
# However, v4l2-ctl --list-formats-ext do not have such format.
capture_width=1920,
capture_height=1080,
display_width=640,
display_height=360,
framerate=21,
flip_method=0,
):
return (
"nvarguscamerasrc ! "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
% (
capture_width,
capture_height,
framerate,
flip_method,
display_width,
display_height,
)
)
class Camera(object):
frame_reader = None
cap = None
previewer = None
def __init__(self, width=640, height=360):
self.open_camera(width, height)
def open_camera(self, width=640, height=360):
self.cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=0, display_width=width, display_height=height), cv2.CAP_GSTREAMER)
if not self.cap.isOpened():
raise RuntimeError("Failed to open camera!")
if self.frame_reader == None:
self.frame_reader = FrameReader(self.cap, "")
self.frame_reader.daemon = True
self.frame_reader.start()
def getFrame(self, timeout = None):
return self.frame_reader.getFrame(timeout)
class FrameReader(threading.Thread):
queues = []
_running = True
camera = None
def __init__(self, camera, name):
threading.Thread.__init__(self)
self.name = name
self.camera = camera
def run(self):
while self._running:
_, frame = self.camera.read()
while self.queues:
queue = self.queues.pop()
queue.put(frame)
def addQueue(self, queue):
self.queues.append(queue)
def getFrame(self, timeout = None):
queue = Queue(1)
self.addQueue(queue)
return queue.get(timeout = timeout)
def stop(self):
self._running = False
main.py
exit_ = False
if __name__ == "__main__":
camera = Camera(width=1280, height=1280)
while not exit_:
global frame
frame = camera.getFrame(2000)
cv2.imshow("Test", frame)
key = cv2.waitKey(1)
if key == ord('q'):
exit_ = True

Unable to save image from Raspi camera -> cv2.imwrite (Using Jetson Nano)

I am trying to save images from the Raspi cameras connected to my Jetson nano. My Code is below. However, the code shows that it is saving the files, but no matter which method I try I cannot find the images. Thanks for your help. I've included a smaller snippet of just the while loop itself so it will be easier for you all to refer to.
While loop:
while True:
_ , left_image=left_camera.read()
_ , right_image=right_camera.read()
camera_images = np.hstack((left_image, right_image))
cv2.imshow("CSI Cameras", camera_images)
t1 = datetime.now()
cntdwn_timer = countdown - int ((t1-t2).total_seconds())
# If cowntdown is zero - let's record next image
if cntdwn_timer == -1:
counter += 1
filename = './scenes/scene_'+ str(counter) + 'x'+'_'+ '.png'
#img = cv2.imread(camera_images)
#cv2.imwrite(os.path.join(os.path.expanduser('~'),'CSI-Camera', filename), camera_images)
cv2.imwrite('/home/aryan/CSI-Camera/{}'.format(filename), camera_images)
print (' monkey'+filename)
t2 = datetime.now()
time.sleep(1)
cntdwn_timer = 0 # To avoid "-1" timer display
next
# This also acts as
keyCode = cv2.waitKey(30) & 0xFF
# Stop the program on the ESC key
if keyCode == 27:
break
left_camera.stop()
left_camera.release()
right_camera.stop()
right_camera.release()
cv2.destroyAllWindows()
import cv2
import threading
import numpy as np
import time
from datetime import datetime
# gstreamer_pipeline returns a GStreamer pipeline for capturing from the CSI camera
# Flip the image by setting the flip_method (most common values: 0 and 2)
# display_width and display_height determine the size of each camera pane in the window on the screen
left_camera = None
right_camera = None
#PiCam
# Photo session settings
total_photos = 30 # Number of images to take
countdown = 5 # Interval for count-down timer, seconds
font=cv2.FONT_HERSHEY_SIMPLEX # Cowntdown timer font
class CSI_Camera:
def __init__ (self) :
# Initialize instance variables
# OpenCV video capture element
self.video_capture = None
# The last captured image from the camera
self.frame = None
self.grabbed = False
# The thread where the video capture runs
self.read_thread = None
self.read_lock = threading.Lock()
self.running = False
def open(self, gstreamer_pipeline_string):
try:
self.video_capture = cv2.VideoCapture(
gstreamer_pipeline_string, cv2.CAP_GSTREAMER
)
except RuntimeError:
self.video_capture = None
print("Unable to open camera")
print("Pipeline: " + gstreamer_pipeline_string)
return
# Grab the first frame to start the video capturing
self.grabbed, self.frame = self.video_capture.read()
def start(self):
if self.running:
print('Video capturing is already running')
return None
# create a thread to read the camera image
if self.video_capture != None:
self.running=True
self.read_thread = threading.Thread(target=self.updateCamera)
self.read_thread.start()
return self
def stop(self):
self.running=False
self.read_thread.join()
def updateCamera(self):
# This is the thread to read images from the camera
while self.running:
try:
grabbed, frame = self.video_capture.read()
with self.read_lock:
self.grabbed=grabbed
self.frame=frame
except RuntimeError:
print("Could not read image from camera")
# FIX ME - stop and cleanup thread
# Something bad happened
def read(self):
with self.read_lock:
frame = self.frame.copy()
grabbed=self.grabbed
return grabbed, frame
def release(self):
if self.video_capture != None:
self.video_capture.release()
self.video_capture = None
# Now kill the thread
if self.read_thread != None:
self.read_thread.join()
# Currently there are setting frame rate on CSI Camera on Nano through gstreamer
# Here we directly select sensor_mode 3 (1280x720, 59.9999 fps)
def gstreamer_pipeline(
sensor_id=0,
sensor_mode=3,
capture_width=1280,
capture_height=720,
display_width=1280,
display_height=720,
framerate=30,
flip_method=0,
):
return (
"nvarguscamerasrc sensor-id=%d sensor-mode=%d ! "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
% (
sensor_id,
sensor_mode,
capture_width,
capture_height,
framerate,
flip_method,
display_width,
display_height,
)
)
def start_cameras():
left_camera = CSI_Camera()
left_camera.open(
gstreamer_pipeline(
sensor_id=0,
sensor_mode=3,
flip_method=0,
display_height=540,
display_width=960,
)
)
left_camera.start()
right_camera = CSI_Camera()
right_camera.open(
gstreamer_pipeline(
sensor_id=1,
sensor_mode=3,
flip_method=0,
display_height=540,
display_width=960,
)
)
right_camera.start()
cv2.namedWindow("CSI-AV Cameras", cv2.WINDOW_AUTOSIZE)
if (
not left_camera.video_capture.isOpened()
or not right_camera.video_capture.isOpened()
):
# Cameras did not open, or no camera attached
print("Unable to open any cameras")
# TODO: Proper Cleanup
SystemExit(0)
counter = 0
t2 = datetime.now()
#Main stuff here
while True:
_ , left_image=left_camera.read()
_ , right_image=right_camera.read()
camera_images = np.hstack((left_image, right_image))
cv2.imshow("CSI Cameras", camera_images)
t1 = datetime.now()
cntdwn_timer = countdown - int ((t1-t2).total_seconds())
# If cowntdown is zero - let's record next image
if cntdwn_timer == -1:
counter += 1
filename = './scenes/scene_'+ str(counter) + 'x'+'_'+ '.png'
#img = cv2.imread(camera_images)
#cv2.imwrite(os.path.join(os.path.expanduser('~'),'CSI-Camera', filename), camera_images)
cv2.imwrite('/home/aryan/CSI-Camera/{}'.format(filename), camera_images)
print (' monkey'+filename)
t2 = datetime.now()
time.sleep(1)
cntdwn_timer = 0 # To avoid "-1" timer display
next
# This also acts as
keyCode = cv2.waitKey(30) & 0xFF
# Stop the program on the ESC key
if keyCode == 27:
break
left_camera.stop()
left_camera.release()
right_camera.stop()
right_camera.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
start_cameras()
Put breakpoint on line where you want to save image. Inspect image you want to save:
Does it have data inside?
Does it have camera_images.shape ?
What is return value of cv2.imwrite function?
Does path you are trying to write really exist?
Did you appended .png or .jpg ?

Write image frames into gstreamer rtp pipeline

I am trying to use the gstreamer pipeline to view an rtp stream in vlc on my computer. I mostly looked into this thread. My end result is something like this
#!/usr/bin/env python
import gi
import numpy as np
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject
import time
class RtpPipeline(object):
def __init__(self):
self.number_frames = 0
self.fps = 30
self.duration = 1 / self.fps * Gst.SECOND # duration of a frame in nanoseconds
self.launch_string = 'appsrc name=source ' \
'!videoconvert !x264enc speed-preset=ultrafast tune=zerolatency byte-stream=true ' \
'! mpegtsmux ! rtpmp2tpay ! udpsink host=127.0.0.1 port=5000'
pipeline = Gst.parse_launch(self.launch_string)
appsrc = pipeline.get_child_by_name('source')
while True:
try:
img = np.zeros([320, 320, 3], dtype=np.uint8)
img.fill(255) # white image
data = img.tostring()
buf = Gst.Buffer.new_allocate(None, len(data), None)
buf.fill(0, data)
buf.duration = self.duration
timestamp = self.number_frames * self.duration
buf.pts = buf.dts = int(timestamp)
buf.offset = timestamp
self.number_frames += 1
retval = appsrc.emit('push-buffer', buf)
if retval != Gst.FlowReturn.OK:
print(retval)
time.sleep(0.2)
except Exception as e:
break
Gst.init(None)
factory = RtpPipeline()
loop = GObject.MainLoop()
loop.run()
Which doesn't throw an error but does not show anything in my vlc client. Any tips would be great (OpenCV VideoWriter is not an option).
The Image frames need to be decoded (based on the format you are reading the image file from ) and then converted to the RAW formats ( RGB/BGR/YUV etc.) and then passed to the gstreamer pipeline.
if you are filling the image buffer with specific color, and not reading from any image files, you should know what format of the image buffer.
The Gstreamer pipeline also should know what RAW format is being passed to it with what resolution and fps details.
Python script should push the image files at the same frame rate as set in the fps. check you sleep time.
Check after changing these parameters, if the problem still exists - add the gstreamer logs too.
I think the most important thing that was missing was:
pipeline.set_state(Gst.State.PLAYING)
I also added the comments from mail2subhajit. Here is the final result, which is kinda buggy but is a good start.
class RtpPipeline(object):
def __init__(self):
self.number_frames = 0
self.fps = 30
self.cap = cv2.VideoCapture(0)
self.duration = 1 / self.fps * Gst.SECOND # duration of a frame in nanoseconds
self.launch_string = 'appsrc name=source is-live=true format=GST_FORMAT_TIME ' \
' caps=video/x-raw,format=BGR,width=640,height=480,framerate=30/1 ' \
'! videoconvert ! video/x-raw,format=I420 ' \
'! x264enc speed-preset=ultrafast tune=zerolatency byte-stream=true ' \
'! mpegtsmux ! rtpmp2tpay ! udpsink host=127.0.0.1 port=5000 sync=false'
pipeline = Gst.parse_launch(self.launch_string)
appsrc = pipeline.get_child_by_name('source')
pipeline.set_state(Gst.State.PLAYING)
while True:
try:
ret, frame = self.cap.read()
start = time.time()
data = frame.tostring()
buf = Gst.Buffer.new_allocate(None, len(data), None)
buf.fill(0, data)
buf.duration = self.duration
timestamp = self.number_frames * self.duration
buf.pts = buf.dts = int(timestamp)
buf.offset = timestamp
self.number_frames += 1
retval = appsrc.emit('push-buffer', buf)
if retval != Gst.FlowReturn.OK:
print(retval)
except Exception as e:
break

How to pass image grabbed from camera to tf.read_file

I have a function which grabs an image from a camera:
img = cam.read()
Now I want to read that image with tf.read_file,
but when I do img_raw = tf.read_file(img), it doesn't work.
This is the code for the camera class:
"""camera.py
This code implements the Camera class, which encapsulates code to
handle IP CAM, USB webcam or the Jetson onboard camera. The Camera
class is further extend to take either a video or an image file as
input.
"""
import time
import logging
import threading
import numpy as np
import cv2
def open_cam_rtsp(uri, width, height, latency):
"""Open an RTSP URI (IP CAM)."""
gst_str = ('rtspsrc location={} latency={} ! '
'rtph264depay ! h264parse ! omxh264dec ! '
'nvvidconv ! '
'video/x-raw, width=(int){}, height=(int){}, '
'format=(string)BGRx ! videoconvert ! '
'appsink').format(uri, latency, width, height)
return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
def open_cam_usb(dev, width, height):
"""Open a USB webcam.
We want to set width and height here, otherwise we could just do:
return cv2.VideoCapture(dev)
"""
gst_str = ('v4l2src device=/dev/video{} ! '
'video/x-raw, width=(int){}, height=(int){}, '
'format=(string)RGB ! videoconvert ! '
'appsink').format(dev, width, height)
return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
def open_cam_onboard(width, height):
"""Open the Jetson onboard camera.
On versions of L4T prior to 28.1, you might need to add
'flip-method=2' into gst_str.
"""
gst_str = ('nvcamerasrc ! '
'video/x-raw(memory:NVMM), '
'width=(int)2592, height=(int)1458, '
'format=(string)I420, framerate=(fraction)30/1 ! '
'nvvidconv ! '
'video/x-raw, width=(int){}, height=(int){}, '
'format=(string)BGRx ! videoconvert ! '
'appsink').format(width, height)
return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
def grab_img(cam):
"""This 'grab_img' function is designed to be run in the sub-thread.
Once started, this thread continues to grab a new image and put it
into the global 'img_handle', until 'thread_running' is set to False.
"""
while cam.thread_running:
if cam.args.use_image:
assert cam.img_handle is not None, 'img_handle is empty in use_image case!'
# keep using the same img, no need to update it
time.sleep(0.01) # yield CPU to other threads
else:
_, cam.img_handle = cam.cap.read()
if cam.img_handle is None:
logging.warning('grab_img(): cap.read() returns None...')
break
cam.thread_running = False
class Camera():
"""Camera class which supports reading images from theses video sources:
1. Video file
2. Image (jpg, png, etc.) file, repeating indefinitely
3. RTSP (IP CAM)
4. USB webcam
5. Jetson onboard camera
"""
def __init__(self, args):
self.args = args
self.is_opened = False
self.thread_running = False
self.img_handle = None
self.img_width = 0
self.img_height = 0
self.cap = None
self.thread = None
def open(self):
"""Open camera based on command line arguments."""
assert self.cap is None, 'Camera is already opened!'
args = self.args
if args.use_file:
self.cap = cv2.VideoCapture(args.filename)
# ignore image width/height settings here
elif args.use_image:
self.cap = 'OK'
self.img_handle = cv2.imread(args.filename)
# ignore image width/height settings here
if self.img_handle is not None:
self.is_opened = True
self.img_height, self.img_width, _ = self.img_handle.shape
elif args.use_rtsp:
self.cap = open_cam_rtsp(
args.rtsp_uri,
args.image_width,
args.image_height,
args.rtsp_latency
)
elif args.use_usb:
self.cap = open_cam_usb(
args.video_dev,
args.image_width,
args.image_height
)
else: # by default, use the jetson onboard camera
self.cap = open_cam_onboard(
args.image_width,
args.image_height
)
if self.cap != 'OK':
if self.cap.isOpened():
# Try to grab the 1st image and determine width and height
_, img = self.cap.read()
if img is not None:
self.img_height, self.img_width, _ = img.shape
self.is_opened = True
def start(self):
assert not self.thread_running
self.thread_running = True
self.thread = threading.Thread(target=grab_img, args=(self,))
self.thread.start()
def stop(self):
self.thread_running = False
self.thread.join()
def read(self):
if self.args.use_image:
return np.copy(self.img_handle)
else:
return self.img_handle
def release(self):
assert not self.thread_running
if self.cap != 'OK':
self.cap.release()
So in another python script I want to use this camera class in order to grab a image and load it with tf.read_file:
from utils.camera import Camera
import numpy as np
import cv2
import tensorflow as tf
cam = Camera(args)
cam.open()
cam.start()
img = cam.read()
img_raw = tf.read_file(img)#here read_file expects a string but I am passing img which is an array
No need to call tf.read_file(img).
ret_val, img = cam.read()
img = tf.convert_to_tensor(img, dtype=tf.float32)
img = tf.image.resize(img, (HEIGHT, WIDTH))
images = tf.expand_dims(img, axis=0) / 255.0
Results = model.predict(images)

Moving python code to separate file

I'm having trouble moving my functions into a separate file as they access a wxpython gui.
The functions are from "onSaveMovieFile" to "LogThis"
#!/usr/bin/env python
# -*- coding: us-ascii -*-
# generated by wxGlade 0.6.3 on Fri Jul 22 11:53:07 2011
"""
Copyright (c) 2011 Mitchell Lafferty <coolspeedy6 at gmail dot com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
self.Bind(wx.EVT_CLOSE,self.OnClose)
self.Stop_Never.Bind(wx.EVT_TOGGLEBUTTON, self.onToggleNever)
self.On.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleOn)
self.Compile_every_now.Bind(wx.EVT_BUTTON, self.Compile)
self.Stills_Select.Bind(wx.EVT_BUTTON, self.onDirStills)
self.Movie_Select.Bind(wx.EVT_BUTTON, self.onSaveMovieFile)
self.Cap_every_SpinCtrl.Bind(wx.EVT_SPINCTRL,self.OnSpinUnlimited)
self.Comp_every_SpinCtrl.Bind(wx.EVT_SPINCTRL, self.OnSpinUnlimited)
self.Framerate_SpinCtrl.Bind(wx.EVT_SPINCTRL, self.OnSpinUnlimited)
self.Comp_Frames_SpinCtrl.Bind(wx.EVT_SPINCTRL, self.OnSpinUnlimited)
self.InitSizeAndQuality()
def onSaveMovieFile(self, event=None):
dlg = wx.FileDialog(
self, message="Save file as ...",
defaultFile="Timelapse.avi",
wildcard="Video files (*.avi)|*.avi",
style=wx.SAVE
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
if not path.endswith(".avi"): path += ".avi" # NOTE: Not safe?
self.Movie_Input.SetValue(path)
dlg.Destroy()
def onDirStills(self, event=None):
dlg = wx.DirDialog(self, "Choose a directory:",
style=wx.DD_DEFAULT_STYLE
## | wx.DD_DIR_MUST_EXIST
## | wx.DD_CHANGE_DIR
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
if not path.endswith("/"): path += "/" # NOTE: Not safe?
self.Stills_Input.SetValue(path)
dlg.Destroy()
def onToggleNever(self,event=None):
self.Stop_Date.Enable(not self.Stop_Never.GetValue())
def OnToggleOn(self,event=None):
self.Snap()
self.Compile()
def Snap(self,event=None):
"""
NOTE: returns cause late work,
if "self.CheckDueDate()" is at bottom
this makes it execed deadline also,
late work should be a user option.
"""
# Haha, "Snapshot and save" sounds like a photo discount store!
print "Snapshot and save code here..."
if not self.Latework.GetValue(): self.CheckDueDate() # NOTE: does not cause late work
try:
if self.On.GetValue():
CapUnit = self.Cap_every_append.GetSelection()
CapVal = self.Cap_every_SpinCtrl.GetValue()
CapVal = self.Time2seconds(CapVal,CapUnit)
print CapVal
if CapVal > 0:
CapTimer = threading.Timer(CapVal,self.Snap)
CapTimer.start()
except Exception as err:
print "Error:", err
self.On.SetValue(False)
if not self.On.GetValue():
if 'CapTimer' in vars():
CapTimer.cancel()
return
path = self.Stills_Input.GetValue()
file = ""
if not os.path.exists(path):
print "Error opening: " + path
return
try:
capture = cv.CreateCameraCapture(-1)
if not capture:
print "Error opening: Camera device"
return
#cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 640 );
#cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 480 );
frame = cv.QueryFrame(capture)
if frame is None: return
file = time.strftime("%Y%m%d%H%M%S", time.gmtime())
file = path + "TS" + file + ".png"
cv.SaveImage(file, frame)
except Exception as err:
print "Error getting/saving frame: ", err
if os.path.isfile(file):
try:
self.Picture.SetBitmap(wx.Bitmap(file, wx.BITMAP_TYPE_ANY))
except Exception as err:
print "Can't show picture!: ", err
else:
print "Error opening: " + file
return
print file
if self.Latework.GetValue(): self.CheckDueDate() # NOTE: causes late work
##if 'CapTimer' in vars(): CapTimer.start()
def Compile(self,event=None):
print "Compile into movie code here.."
if not self.Latework.GetValue(): self.CheckDueDate() # NOTE: does not cause late work
try:
if self.On.GetValue():
CompUnit = self.Comp_every_append.GetSelection()
CompVal = self.Comp_every_SpinCtrl.GetValue()
CompVal = self.Time2seconds(CompVal,CompUnit)
print CompVal
if CompVal > 0:
CompTimer = threading.Timer(CompVal,self.Compile)
CompTimer.start()
except Exception as err:
print "Error:", err
self.On.SetValue(False)
if not self.On.GetValue():
if 'CompTimer' in vars():
CompTimer.cancel()
return
file = self.Movie_Input.GetValue()
path = self.Stills_Input.GetValue()
TimeApart = self.Time2seconds( self.Comp_Frames_SpinCtrl.GetValue(), self.Comp_Frames_append.GetSelection())
if not os.path.exists(path):
self.LogThis("opening: " + path,None,False)
return
try:
fps = self.Framerate_SpinCtrl.GetValue()
if fps<=0: fps = 10
frames = glob.glob(path + "TS*.png")
writer = cvCreateVideoWriter(file, -1, fps, is_color=1) # frame_size=-1
for i in range(len(frames)):
if TimeApart > 0:
frames[i] = re.search('TS(.*)\.png', frames[i]) # find correct file
frames[i] = frames[i].group(0) # grab date
frames[i] = mktime(time.strptime(frames[i], "%Y%m%d%H%M%S")) # make into timestamp
frames[i] += TimeApart # add to timestamp
frames[i] = path + time.strftime("TS%Y%m%d%H%M%S.png", time.gmtime(frames[i])) # make path+file place
if os.path.isfile(frames[i]):
self.ImageResize(frames[i])
cvWriteFrame(writer, frames[i])
except Exception as err:
self.LogThis("Can't make movie: " + str(err),None,False)
if self.Latework.GetValue(): self.CheckDueDate() # NOTE: causes late work
##if 'CompTimer' in vars(): CompTimer.start()
def CheckDueDate(self):
if self.Stop_Never.GetValue(): return
print "Timer duedate code here..."
selected = self.Stop_Date.GetValue()
month = selected.Month + 1
day = selected.Day
year = selected.Year
date_str = "%4d%02d%02d" % (year, month, day)
#?print date_str
#?print time.strftime("%Y%m%d", time.gmtime())
if date_str <= time.strftime("%Y%m%d", time.gmtime()):
print "Deadline reached!"
self.On.SetValue(False)
if 'CapTimer' in vars(): CapTimer.cancel()
if 'CompTimer' in vars(): CompTimer.cancel()
##self.OnToggleOn()
def Time2seconds(self,time,unit):
# errors "long int too large to convert to c long"
# unit == (anything else) # seconds 1
if unit == 1:
time *= 60 # minutes 60
elif unit == 2:
time *= 60 * 60 # hours 60 * 60
elif unit == 3:
time *= 24 * 60 * 60 # days 24 * 60 * 60
elif unit == 4:
time *= 365 * 24 * 60 * 60 # years 365 * 24 * 60 * 60
return time
def OnSpinUnlimited(self,event=None):
obj = event.GetEventObject()
obj.SetRange(0, obj.GetValue() + 100)
def OnClose(self,event=None):
if 'CapTimer' in vars(): CapTimer.cancel()
if 'CompTimer' in vars(): CompTimer.cancel()
self.Destroy()
def ImageResize(self,file):
"""##
try:
from PIL import Image
except Exception as err:
print 'We need This module!: ', err
self.Size_Combo.Enable(False)
self.Quality_SpinCtrl.Enable(False)
self.label_7.Enable(False)
return
##"""
try:
OldImage = Image.open(file)
# pil_image.size pil_image.format pil_image.mode
SizeVal = self.Size_Combo.GetValue()
Size = SizeVal.split('x', 1);
if Size[0] <= 0 or Size[1] <= 0: return
NewImage = OldImage.resize((Size[0], Size[1]), Image.ANTIALIAS)
NewImage.save(file,quality=Quality_SpinCtrl.GetValue())
except Exception as err:
self.Error_GUI_Print_Log('resize: ' + str(err),None,False)
def InitSizeAndQuality(self):
try:
from PIL import Image
except Exception as err:
self.LogThis('We need This module!: ' + str(err))
self.Size_Combo.Enable(False)
self.Quality_SpinCtrl.Enable(False)
self.Size_and_Quality_label.Enable(False)
def LogThis(self,msg,level=None,LOUD=True):
if level == None: level = logging.ERROR
LEVELS ={}
LEVELS[logging.DEBUG]=_('Debug')
LEVELS[logging.INFO]=_('Info')
LEVELS[logging.WARNING]=_('Warning')
LEVELS[logging.ERROR]=_('Error')
LEVELS[logging.CRITICAL]=_('Critical')
print LEVELS[level],":",msg
if LOUD:
try:
wx.MessageBox(msg,LEVELS[level])
except:
pass
if NoLog: return #'NoLog' in vars() and
logger = logging.getLogger('YaTLC')
hdlr = logging.FileHandler('./YaTLC.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
#logger.setLevel(logging.INFO)
logger.log(level,msg)
#logger.shutdown()
PS: I fixed it, all I did was put the function in a different file, imported it, and replaced some "self's" with the name of the different file
I see you are using wxglade for the design of you gui.
The best procedure is to keep the code from glade untouched in a file. Then you import and subclass the wxglade created class in a new file. There you write all your Bind() and functions there.
For example suposse this is your wxglade autogenerated file:
mygui.py
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# generated by wxGlade HG on Tue Jul 26 20:03:16 2011
import wx
# begin wxGlade: extracode
# end wxGlade
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
self.__set_properties()
self.__do_layout()
# end wxGlade
def __set_properties(self):
# begin wxGlade: MyFrame.__set_properties
self.SetTitle("frame_1")
# end wxGlade
def __do_layout(self):
# begin wxGlade: MyFrame.__do_layout
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
# end wxGlade
# end of class MyFrame
Then in your application:
myaplication.py
import wx
from mygui import MyFrame
class MyApplication(MyFrame):
def __init__(self, *args, **kargs):
MyFrame.__init__(self, *args, **kargs)
##**put here all your Bind()**
#**then put all your methods here:**
def onSaveMovieFile(self, evt):
----------------
def LogThis(self, evt):
----------------
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = MyApplication(None)
frame.Show()
app.MainLoop()

Categories

Resources