E:\song2\树莓派视频流\flask_opencv_video_stream\flask-video-streaming\app.py
| |
| from importlib import import_module |
| |
| from flask import Flask, render_template, Response |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| from camera_opencv 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: |
| |
| |
| |
| 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(): |
| |
| |
| event[0].set() |
| event[1] = now |
| else: |
| |
| |
| |
| |
| 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 |
| frame = None |
| last_access = 0 |
| 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() |
| |
| |
| BaseCamera.thread = threading.Thread(target=self._thread) |
| BaseCamera.thread.start() |
| |
| |
| BaseCamera.event.wait() |
| |
| def get_frame(self): |
| """Return the current camera frame.""" |
| BaseCamera.last_access = time.time() |
| |
| |
| 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() |
| time.sleep(0) |
| |
| |
| |
| 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: |
| |
| _, img = camera.read() |
| |
| |
| 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: |
| |
| time.sleep(2) |
| |
| stream = io.BytesIO() |
| for _ in camera.capture_continuous(stream, 'jpeg', |
| use_video_port=True): |
| |
| stream.seek(0) |
| yield stream.read() |
| |
| |
| 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) |
| |
| 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,), (), ()) |
| 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> |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2022-02-15 autojs 读取多行文本 一行一行读取文本
2022-02-15 微信公众号 话题链接提取
2022-02-15 创建多层目录 文件写入
2022-02-15 微信公众号 爬虫 提取url
2022-02-15 cheerio 解析新浪博客目录列表
2022-02-15 jQuery_ 使用 each() 方法倒序遍历元素(获取元素、逆序操作)