E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\app.py
#!/usr/bin/env python
from importlib import import_module
# import os
from flask import Flask, render_template, Response
# # import camera driver
# if os.environ.get('CAMERA'):
# Camera = import_module('camera_opencv').Camera
# # Camera = import_module('camera_' + os.environ['CAMERA']).Camera
# # print(os.environ['CAMERA'])
# else:
# from camera import Camera
from camera_opencv import Camera
# Raspberry Pi camera module (requires picamera package)
# from camera_pi import Camera
app = Flask(__name__)
@app.route('/')
def index():
"""Video streaming home page."""
return render_template('index.html')
def gen(camera):
"""Video streaming generator function."""
yield b'--frame\r\n'
while True:
frame = camera.get_frame()
yield b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n--frame\r\n'
@app.route('/video_feed')
def video_feed():
"""Video streaming route. Put this in the src attribute of an img tag."""
return Response(gen(Camera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='0.0.0.0', threaded=True)
E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\base_camera.py
import time
import threading
try:
from greenlet import getcurrent as get_ident
except ImportError:
try:
from thread import get_ident
except ImportError:
from _thread import get_ident
class CameraEvent(object):
"""An Event-like class that signals all active clients when a new frame is
available.
"""
def __init__(self):
self.events = {}
def wait(self):
"""Invoked from each client's thread to wait for the next frame."""
ident = get_ident()
if ident not in self.events:
# this is a new client
# add an entry for it in the self.events dict
# each entry has two elements, a threading.Event() and a timestamp
self.events[ident] = [threading.Event(), time.time()]
return self.events[ident][0].wait()
def set(self):
"""Invoked by the camera thread when a new frame is available."""
now = time.time()
remove = None
for ident, event in self.events.items():
if not event[0].isSet():
# if this client's event is not set, then set it
# also update the last set timestamp to now
event[0].set()
event[1] = now
else:
# if the client's event is already set, it means the client
# did not process a previous frame
# if the event stays set for more than 5 seconds, then assume
# the client is gone and remove it
if now - event[1] > 5:
remove = ident
if remove:
del self.events[remove]
def clear(self):
"""Invoked from each client's thread after a frame was processed."""
self.events[get_ident()][0].clear()
class BaseCamera(object):
thread = None # background thread that reads frames from camera
frame = None # current frame is stored here by background thread
last_access = 0 # time of last client access to the camera
event = CameraEvent()
def __init__(self):
"""Start the background camera thread if it isn't running yet."""
if BaseCamera.thread is None:
BaseCamera.last_access = time.time()
# start background frame thread
BaseCamera.thread = threading.Thread(target=self._thread)
BaseCamera.thread.start()
# wait until first frame is available
BaseCamera.event.wait()
def get_frame(self):
"""Return the current camera frame."""
BaseCamera.last_access = time.time()
# wait for a signal from the camera thread
BaseCamera.event.wait()
BaseCamera.event.clear()
return BaseCamera.frame
@staticmethod
def frames():
""""Generator that returns frames from the camera."""
raise RuntimeError('Must be implemented by subclasses.')
@classmethod
def _thread(cls):
"""Camera background thread."""
print('Starting camera thread.')
frames_iterator = cls.frames()
for frame in frames_iterator:
BaseCamera.frame = frame
BaseCamera.event.set() # send signal to clients
time.sleep(0)
# if there hasn't been any clients asking for frames in
# the last 10 seconds then stop the thread
if time.time() - BaseCamera.last_access > 10:
frames_iterator.close()
print('Stopping camera thread due to inactivity.')
break
BaseCamera.thread = None
E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\camera.py
import time
from base_camera import BaseCamera
class Camera(BaseCamera):
"""An emulated camera implementation that streams a repeated sequence of
files 1.jpg, 2.jpg and 3.jpg at a rate of one frame per second."""
imgs = [open(f + '.jpg', 'rb').read() for f in ['1', '2', '3']]
@staticmethod
def frames():
while True:
yield Camera.imgs[int(time.time()) % 3]
time.sleep(1)
E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\camera_opencv.py
import os
import cv2
from base_camera import BaseCamera
class Camera(BaseCamera):
video_source = 0
def __init__(self):
if os.environ.get('OPENCV_CAMERA_SOURCE'):
Camera.set_video_source(int(os.environ['OPENCV_CAMERA_SOURCE']))
super(Camera, self).__init__()
@staticmethod
def set_video_source(source):
Camera.video_source = source
@staticmethod
def frames():
camera = cv2.VideoCapture(Camera.video_source)
if not camera.isOpened():
raise RuntimeError('Could not start camera.')
while True:
# read current frame
_, img = camera.read()
# encode as a jpeg image and return it
yield cv2.imencode('.jpg', img)[1].tobytes()
E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\camera_pi.py
import io
import time
import picamera
from base_camera import BaseCamera
class Camera(BaseCamera):
@staticmethod
def frames():
with picamera.PiCamera() as camera:
# let camera warm up
time.sleep(2)
stream = io.BytesIO()
for _ in camera.capture_continuous(stream, 'jpeg',
use_video_port=True):
# return current frame
stream.seek(0)
yield stream.read()
# reset stream for next frame
stream.seek(0)
stream.truncate()
E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\camera_v4l2.py
import io
from PIL import Image
import select
import v4l2capture
from base_camera import BaseCamera
class Camera(BaseCamera):
"""Requires python-v4l2capture module: https://github.com/gebart/python-v4l2capture"""
video_source = "/dev/video0"
@staticmethod
def frames():
video = v4l2capture.Video_device(Camera.video_source)
# Suggest an image size. The device may choose and return another if unsupported
size_x = 640
size_y = 480
size_x, size_y = video.set_format(size_x, size_y)
video.create_buffers(1)
video.queue_all_buffers()
video.start()
bio = io.BytesIO()
try:
while True:
select.select((video,), (), ()) # Wait for the device to fill the buffer.
image_data = video.read_and_queue()
image = Image.frombytes("RGB", (size_x, size_y), image_data)
image.save(bio, format="jpeg")
yield bio.getvalue()
bio.seek(0)
bio.truncate()
finally:
video.close()
E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\templates\index.html
<html>
<head>
<title>Video Streaming Demonstration</title>
</head>
<body>
<h1>Video Streaming Demonstration</h1>
<img src="{{ url_for('video_feed') }}">
</body>
</html>
标签:BaseCamera,thread,flask,frame,pythonsocketio,camera,video,import,openv
From: https://www.cnblogs.com/zhuoss/p/17123902.html