Advertisement
Guest User

with_billiard.py

a guest
Apr 23rd, 2017
175
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Entry point
  2. import numpy as np
  3. import time
  4. import ctypes
  5. import argparse
  6.  
  7. from multiprocessing import Array, Value, Process
  8. from billiard import Process, forking_enable
  9. import cv2
  10.  
  11.  
  12. class VideoCapture:
  13.     """
  14.    Class that handles video capture from device or video file
  15.    """
  16.     def __init__(self, device=0, delay=0.):
  17.         """
  18.        :param device: device index or video filename
  19.        :param delay: delay between frame captures in seconds(floating point is allowed)
  20.        """
  21.         self._cap = cv2.VideoCapture(device)
  22.         self._delay = delay
  23.  
  24.     def _proper_frame(self, delay=None):
  25.         """
  26.        :param delay: delay between frames capture(in seconds)
  27.        :param finished: synchronized wrapper for int(see multiprocessing.Value)
  28.        :return: frame
  29.        """
  30.         snapshot = None
  31.         correct_img = False
  32.         fail_counter = -1
  33.         while not correct_img:
  34.             # Capture the frame
  35.             correct_img, snapshot = self._cap.read()
  36.             fail_counter += 1
  37.             # Raise exception if there's no output from the device
  38.             if fail_counter > 10:
  39.                 raise Exception("Capture: exceeded number of tries to capture the frame.")
  40.             # Delay before we get a new frame
  41.             time.sleep(delay)
  42.         return snapshot
  43.  
  44.     def get_size(self):
  45.         """
  46.        :return: size of the captured image
  47.        """
  48.         return (int(self._cap.get(int(cv2.CAP_PROP_FRAME_HEIGHT))),
  49.                 int(self._cap.get(int(cv2.CAP_PROP_FRAME_WIDTH))), 3)
  50.  
  51.     def get_stream_function(self):
  52.         """
  53.        Returns stream_function object function
  54.        """
  55.  
  56.         def stream_function(image, finished):
  57.             """
  58.            Function keeps capturing frames until finished = 1
  59.            :param image: shared numpy array for multiprocessing(see multiprocessing.Array)
  60.            :param finished: synchronized wrapper for int(see multiprocessing.Value)
  61.            :return: nothing
  62.            """
  63.             # Incorrect input array
  64.             if image.shape != self.get_size():
  65.                 raise Exception("Capture: improper size of the input image")
  66.             print("Capture: start streaming")
  67.             # Capture frame until we get finished flag set to True
  68.             while not finished.value:
  69.                 image[:, :, :] = self._proper_frame(self._delay)
  70.             # Release the device
  71.             self.release()
  72.  
  73.         return stream_function
  74.  
  75.     def release(self):
  76.         self._cap.release()
  77.  
  78.  
  79. def main():
  80.     # Add program arguments
  81.     parser = argparse.ArgumentParser(description='Captures the video from the webcamera and \nwrites it into the output file with predefined fps.', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  82.     parser.add_argument('-output', dest="output",  default="output.avi", help='name of the output video file')
  83.     parser.add_argument('-log', dest="log",  default="frames.log", help='name of the log file')
  84.     parser.add_argument('-fps', dest="fps",  default=25., help='frames per second value')
  85.  
  86.     # Read the arguments if any
  87.     result = parser.parse_args()
  88.     fps = float(result.fps)
  89.     output = result.output
  90.     log = result.log
  91.  
  92.     # Initialize VideoCapture object and auxilary objects
  93.     cap = VideoCapture()
  94.     shape = cap.get_size()
  95.     stream = cap.get_stream_function()
  96.  
  97.     # Define shared variables(which are synchronised so race condition is excluded)
  98.     shared_array_base = Array(ctypes.c_uint8, shape[0] * shape[1] * shape[2])
  99.     frame = np.ctypeslib.as_array(shared_array_base.get_obj())
  100.     frame = frame.reshape(shape[0], shape[1], shape[2])
  101.     finished = Value('i', 0)
  102.  
  103.     # Start processes which run in parallel
  104.     forking_enable(0)  # Supposedly this is all I need
  105.     video_process = Process(target=stream, args=(frame, finished))
  106.     video_process.start()  # Launch capture process
  107.  
  108.     # Sleep for some time to allow videocapture start working first
  109.     time.sleep(2)
  110.  
  111.     # Termination function
  112.     def terminate():
  113.         print("Main: termination")
  114.         finished.value = True
  115.         # Wait for all processes to finish
  116.         time.sleep(1)
  117.         # Terminate working processes
  118.         video_process.terminate()
  119.  
  120.     # The capturing works until keyboard interrupt is pressed.
  121.     while True:
  122.         try:
  123.             # Display the resulting frame
  124.             cv2.imshow('frame', frame)
  125.             cv2.waitKey(1)  # Display it at least one ms before going to the next frame
  126.             time.sleep(0.1)
  127.  
  128.         except KeyboardInterrupt:
  129.             cv2.destroyAllWindows()
  130.             terminate()
  131.             break
  132.  
  133. if __name__ == '__main__':
  134.     main()
Advertisement
RAW Paste Data Copied
Advertisement