{ "cells": [ { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "import cv2\n", "import time, os\n", "import threading\n", "import numpy as np\n", "import multiprocessing as mp\n", "import matplotlib.pyplot as plt\n", "\n", "from situtils import FPSTimes" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "class VideoWriter(FPSTimes):\n", " # precise timing https://stackoverflow.com/questions/42565297/precise-loop-timing-in-python\n", " \n", " default_cfg = {\n", " 'fps': 20,\n", " 'file_path': 'test_video.avi',\n", " }\n", " \n", " def __init__(self, status, video_stream, cfg):\n", " super(VideoWriter, self).__init__()\n", " \n", " self.cfg = cfg\n", " self.video_stream = video_stream # cv2 video stream\n", " self.stopped = False\n", " self.status = status\n", " \n", " fourcc = cv2.VideoWriter_fourcc(*'XVID')\n", " res_x, res_y = int(video_stream.stream.get(3)), int(video_stream.stream.get(4))\n", " self.out = cv2.VideoWriter(cfg['file_path'], fourcc, cfg['fps'], (res_x, res_y))\n", "\n", " @property\n", " def latency(self):\n", " return 1.0/self.cfg['fps']\n", " \n", " def start(self):\n", " self._th = threading.Thread(target=self.update, args=())\n", " self._th.start()\n", " \n", " def stop(self):\n", " self.stopped = True\n", " time.sleep(0.2) # wait until device is released\n", " self._th.join()\n", " print('Video writer stopped')\n", " \n", " def update(self):\n", " next_frame = time.time() + self.latency\n", " \n", " while not self.stopped:\n", " if self.status.value == 2:\n", " if time.time() < next_frame:\n", " continue # TODO sleep here?\n", "\n", " #frame = self.video_stream.read()\n", " frame = self.video_stream.frame_with_infos\n", " if frame is not None:\n", " self.count() # count FPS\n", " t0 = time.time()\n", " self.out.write(frame)\n", " with open(self.cfg['csv_path'], 'a') as f:\n", " f.write(\",\".join([str(x) for x in (t0,)]) + \"\\n\")\n", " \n", " frames_missed = np.floor((time.time() - next_frame) * self.cfg['fps'])\n", " next_frame += self.latency * frames_missed + self.latency\n", " else:\n", " time.sleep(0.005)\n", " \n", " self.out.release()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Testing video recording" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'WebcamStream' is not defined", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;31m# let's use a webcam stream\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0mvs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mWebcamStream\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mWebcamStream\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdefault_cfg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 6\u001b[0m \u001b[0mvs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mstart\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# stream runs in a separate thread\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 7\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mNameError\u001b[0m: name 'WebcamStream' is not defined" ] } ], "source": [ "#import nbimporter\n", "#from camera import WebcamStream\n", "\n", "# let's use a webcam stream\n", "vs = WebcamStream(WebcamStream.default_cfg)\n", "vs.start() # stream runs in a separate thread\n", "\n", "# recording status: 1 - idle, 2 - recording\n", "status = mp.Value('i', 1)\n", "\n", "# start/stop recording by pressing 's'\n", "vw = VideoWriter(status, vs, VideoWriter.default_cfg)\n", "vw.start()\n", "\n", "try:\n", " while True:\n", " frame = vs.read()\n", " if frame is not None:\n", " color = (127, 255, 0) if status.value == 1 else (0, 0, 255)\n", " frame = cv2.circle(frame, (20, 20), 15, color, -1)\n", " cv2.imshow('Webcam', frame)\n", "\n", " k = cv2.waitKey(33)\n", " if k == ord('q'):\n", " break\n", " \n", " if k == ord('s'):\n", " status.value = 2 if status.value == 1 else 1\n", "finally:\n", " cv2.destroyAllWindows()\n", " vs.stop(), vw.stop()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 4 }