Web开发:React+Flask实现实时相机调用

这篇具有很好参考价值的文章主要介绍了Web开发:React+Flask实现实时相机调用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、问题描述

为了方便利用机器视觉算法,使用React+Flask前后端分离的办法实现实时相机的调用。由前端向后端请求视频流,后端接受请求后向前端发送视频流数据,方便在后端使用各种算法对视频流数据进行处理。

成功实现后,打开相机开关,即可在前端调用相机。

Web开发:React+Flask实现实时相机调用,Web开发,flask,react.js,opencv

二、解决方法

项目采用前后端分离架构,前端React+TypeScript,使用TSX编程,创建方法见我前面的一篇博文。Web开发:React+Flask前后端分离简介与初步实现;后端就是普遍使用的Flask框架。

文件夹结构:

  • camera-switch
    • frontend
    • backend

2.1 frontend 前端

前端使用AntD提供的组件展示相机拍摄的视频,并使用axios库来与后端进行交互,向后端传递请求,获取视频流。

定义自己的相机展示组件CameraDisplay

import React, { useState } from 'react';
import { Image, Space, Switch } from 'antd';
import axios from "axios";
import LoadPNG from './loading01.png';

interface CameraDisplayProps {
    cameraSwitchUrl: string;
}


const CameraDisplay: React.FC<CameraDisplayProps> = (props) => {
    const [cameraStatus, setCameraStatus] = useState(false);
    const [videoStream, setVideoStream] = useState(LoadPNG);

    const { cameraSwitchUrl } = props;

    const handleSwitchChange = async (checked: boolean) => {
        setCameraStatus(checked);
        axios.post(cameraSwitchUrl, {
            status: checked
        }).then(response => {

            if (checked) {
                if (response.data.result === 'success') {
                    console.log('后端响应:', response.data.message);
                    setVideoStream('http://127.0.0.1:5000/video');
                } else {
                    console.log('后端响应:', response.data.message);
                }
            } else {
                console.log('后端响应:', response.data.message);
                setVideoStream(LoadPNG);
            }

        }).catch(error => {
            console.error('发送数据到后端时出错:', error);
        })
    };

    return (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Space direction='vertical' size='large'>
                <div>
                    <Image key={cameraStatus.toString()} src={ videoStream } preview={ false } height={ '480px' } width={ '640px' } />
                </div>

                <div style={{ display: 'flex', alignItems: 'center', float: 'right' }}>
                    <span style={{ marginRight: '24px' }}>相机开关</span>

                    <Switch checkedChildren='ON' unCheckedChildren='OFF' onChange={ handleSwitchChange } />
                </div>
            </Space>
        </div>
    )
};

export default CameraDisplay;

注意,当组件 Switch 状态为 true 时,前端向后端获取的路由为

'http://127.0.0.1:5000/video'

实际上可以设置 axios 的默认基础路由defaults.baseURL为

"http://127.0.0.1:5000"

这样就可以将原来的路由简化为

'/video'

将创建的自己的组件导入到主文件App.tsx中。

import React from 'react';
import './App.css';
import CameraDisplay from "./components/CameraDisplay";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <CameraDisplay cameraSwitchUrl={'/camera_switch'} />
      </header>
    </div>
  );
}

export default App;

最后不要忘了在src目录下的index.tsx文件中设置默认路由

import axios from "axios";

axios.defaults.baseURL = "http://127.0.0.1:5000";

2.2 backend 后端

后端主要使用Flask-RESTful库来进行与前端的交互。后端相机稳定地输出到前端使用了threading.Lock()如果不使用的话,相机打开会卡顿,一段时间后就会自动关闭,如果有明白原理的大佬麻烦在评论区帮忙解答一下~

首先是app.py文件

from flask import Flask
from flask_cors import CORS
from flask_restful import Api

from CameraSwitch import *

app = Flask(__name__)
CORS(app)
api = Api(app)

api.add_resource(CameraSwitch, '/camera_switch')
api.add_resource(Video, '/video')


if __name__ == '__main__':
    app.run()

 由于前端和后端使用的不是一个网络,所以跨域传输数据时,需要导入CORS允许跨域传输。

接着定义Flask-RESTful的Resource

import cv2
import threading
from flask import Response
from flask_restful import Resource, reqparse

from camera import USBCamera


lock = threading.Lock()
webcam = USBCamera()


def gen():
    global lock, webcam
    while True:
        with lock:
            frame = webcam.frame
            if frame is None:
                continue

            # encode the frame in JPEG format
            (flag, encodedImage) = cv2.imencode(".jpg", frame)

            # ensure the frame was successfully encoded
            if not flag:
                continue

        # yield the output frame in the byte format
        yield (b'--frame\r\n' 
               b'Content-Type: image/jpeg\r\n\r\n' + bytearray(encodedImage) + b'\r\n')


class CameraSwitch(Resource):
    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument(
            'status', dest='status', type=bool, required=True, help='The order to switch the camera'
        )

    def post(self):
        global webcam
        args = self.parser.parse_args()
        status = args.status
        if status:
            try:
                webcam.camera_open()
                return {
                    'message': 'Open the camera successfully!',
                    'result': 'success'
                }
            except Exception as e:
                print('打开摄像头失败:', e)
                return {
                    'result': 'fail'
                }
        else:
            webcam.camera_close()
            return {
                'message': 'Close the camera'
            }


class Video(Resource):
    def get(self):
        print('Video has been loaded.')
        return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')

最后需要相机的SDK文件camera.py来调用相机。

import cv2
import time
import threading


class USBCamera:
    def __init__(self, device=-1, resolution=(640, 480)):

        self.device = device
        self.width = resolution[0]
        self.height = resolution[1]

        self.cap = None
        self.frame = None
        self.opened = False

        self.th = None
        self.th = threading.Thread(target=self.camera_task, args=(), daemon=True)
        self.th.start()

    def camera_open(self):
        try:
            self.cap = cv2.VideoCapture(self.device)
            # self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('Y', 'U', 'Y', 'V'))
            # self.cap.set(cv2.CAP_PROP_FPS, 30)
            # self.cap.set(cv2.CAP_PROP_SATURATION, 40)
            self.opened = True
        except Exception as e:
            print('打开摄像头失败:', e)

    def camera_close(self):
        try:
            self.opened = False
            time.sleep(0.2)
            if self.cap is not None:
                self.cap.release()
                time.sleep(0.05)
            self.cap = None
        except Exception as e:
            print('关闭摄像头失败:', e)

    def camera_task(self):
        while True:
            try:
                if self.opened and self.cap.isOpened():
                    ret, frame_tmp = self.cap.read()
                    if ret:
                        frame_resize = cv2.resize(frame_tmp, (self.width, self.height), interpolation=cv2.INTER_NEAREST)
                        self.frame = frame_resize
                    else:
                        print(1)
                        self.frame = None
                        cap = cv2.VideoCapture(self.device)
                        ret, _ = cap.read()
                        if ret:
                            self.cap = cap
                elif self.opened:
                    print(2)
                    cap = cv2.VideoCapture(self.device)
                    ret, _ = cap.read()
                    if ret:
                        self.cap = cap
                else:
                    time.sleep(0.01)
            except Exception as e:
                print('获取摄像头画面出错:', e)
                time.sleep(0.01)


if __name__ == '__main__':
    camera = USBCamera()
    camera.camera_open()
    while True:
        img1 = camera.frame
        if img1 is not None:
            cv2.imshow('img', img1)
            key1 = cv2.waitKey(1)
            if key1 == 27:
                break
    camera.camera_close()
    cv2.destroyAllWindows()

三、代码汇总

完整的项目已经上传到本人的Github上,需要的朋友可以自取。

https://github.com/piggy-wanger/camera-switch

四、参考文献

1. Camera App with Flask and OpenCV

2. Flask-RESTful官方文档文章来源地址https://www.toymoban.com/news/detail-816130.html

到了这里,关于Web开发:React+Flask实现实时相机调用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React+Flask实现前后端交互

    在最近工作中, 有一个小任务是需要前端发送一个请求去后端, 调用python并返回给前端结果. 因为只是一个小需求, 因此挑选了比较轻量化的flask来满足后端和前端的交互 以下是一个小小的示例 1.1 构建前后端文件夹安装基础依赖 前端使用React.js, 如何安装就不再赘述, 使用如下

    2024年02月10日
    浏览(26)
  • 使用Flask Web创建一个调用ChatGPT API的网页--简单示例(linux环境下)

    前提:你应该要有一个能正常使用chatGPT的openAI账号;即你已经成功注册了chatGPT,并能正常使用。 下面是一个使用Flask Web框架创建调用ChatGPT API的网页的示例代码和工程结构: 具体的工程,你可以选择自己创建,也可以直接下载我创建好的工程,链接如下: https://download.csd

    2024年02月13日
    浏览(29)
  • 使用Flask Web创建一个调用ChatGPT API的网页--简单示例(Windows环境下)

    前提:你应该要有一个能正常使用chatGPT的openAI账号;即你已经成功注册了chatGPT,并能正常使用。 要使用Flask Web创建一个调用ChatGPT API的网页,你需要以下几个主要组成部分: ChatGPT API:一个可以处理用户输入并生成回复的ChatGPT模型的API。你可以使用OpenAI提供的GPT-3.5 Playgro

    2024年02月12日
    浏览(39)
  • Python Web 开发 Flask 介绍

    WEB开发是现在程序必会的技能,因为大部分软件都以Web形式提供,及时制作后台开发,或者只做前台开发,也需要了解Web开发的概念和特点。由于Python是解释性脚本语言,用来做Web开发非常适合,而且Python有上百种Web开发框架,以及成熟的模板技术,使得Web开发如虎添翼。今

    2024年02月14日
    浏览(28)
  • 【web开发】1、flask入门和html开发

    HTML:标签具有模式特点。 CSS:修改标签的特点。 JavaScript:动态效果。 在终端输入下面代码: 要保证templates目录及web.py文件在同一级 web.py代码如下(示例): 并在templates目录下创建对应的get_news.html文件。 get_news.html文件代码如下: 运行web.py文件:鼠标右键点击 或点击运行

    2024年02月09日
    浏览(35)
  • 【自学开发之旅】基于Flask的web开发(一)

    web开发项目设计: 立项-需求分析-设计(原型图、数据库、api设计)-技术选型-写代码-测试-上线 web开发的 本质上就是生成超文本。 前端负责展示,后端负责 逻辑处理 :后逻辑请求(接收请求、响应请求) 概念: Flask是一个由python语言编写开发而成的轻量级web开发框架,基

    2024年02月10日
    浏览(24)
  • Web 开发 1: Flask 框架介绍和使用

    在 Web 开发中,Flask 是一个流行且灵活的 Python Web 框架,用于构建 Web 应用程序。它简洁而易于上手,适用于小型到中型的项目。在本篇博客中,我将为你介绍 Flask 框架的基础知识和常用技巧,帮助你更好地掌握 Web 开发中的框架部分。 安装 Flask 在开始使用 Flask 之前,你需要

    2024年01月23日
    浏览(38)
  • 《Flask Web 开发指南 pt.2》

    哈喽大家好,我是咸鱼   在 《Flask Web 开发指南 pt.1》 中,咸鱼跟大家介绍了 Flask 的由来——诞生于一个愚人节玩笑,简单介绍了一些关于 Flask 的概念,并且编写了一个简单的 Flask 程序   在编写 Flask 程序的时候,你需要注意你的程序文件不要命名为 flask.py,建议命名为

    2023年04月08日
    浏览(20)
  • Python Web 开发之 Flask 入门实践

    导语:Flask 是一个轻量级的 Python Web 框架,广受开发者喜爱。本文将带领大家了解 Flask 的基本概念、搭建一个简单的 Web 项目以及如何进一步扩展功能。 Flask 是一个基于 Werkzeug 和 Jinja2 的微型 Web 框架,它的特点是轻量、易学习、可扩展。使用 Flask,我们可以快速构建 Web 应

    2024年01月22日
    浏览(51)
  • Python Web开发:Django与Flask框架

    Django和Flask都是Python中非常受欢迎的Web开发框架。虽然它们都是用于构建Web应用程序的工具,但它们在设计理念、使用方式和适用场景等方面存在一些差异。 Django Django是一个“大而全”的框架,遵循MVC设计模式。它内置了很多功能,如ORM(对象关系映射)、模板引擎、表单处

    2024年02月22日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包