简体   繁体   English

HTML 按钮通过 Python、Flask 和 ZB385E1A4D74C2AFA71FZ9FE39FE3 开启网络摄像头

[英]HTML Button to switch on a Webcam via Python, Flask and OPENCv

I have been working on a project for quite a while.我从事一个项目已经有一段时间了。 Scenario, I want to start my webcam service from the backend so that I can perform some AI tasks, like object identification and face recognition.场景,我想从后端启动我的网络摄像头服务,这样我就可以执行一些 AI 任务,比如 object 识别和人脸识别。 I am using flask in my back end, but having a serious challenge using a toggle button attached to my index page to start the process.我在后端使用 flask,但是在使用附加到我的索引页面的切换按钮来启动该过程时遇到了严峻的挑战。

When I run the process without any button command using an infinite while loop, the camera starts smoothly, but I want to start the camera only when there is a button command with a start command.当我使用无限while循环在没有任何按钮命令的情况下运行该过程时,相机会顺利启动,但我只想在有带有启动命令的按钮命令时启动相机。

Find below my code:在我的代码下面找到:

Index.html


<form action="javascript:0" id="show-cam" class="col s12">
     <label class="form-switch">
           <span id="webcam-caption">Click to Start Camera</span>
           <input type="checkbox" name="checkbox" id="webcam-switch">          
      </label>  
      <div id="attend-image" class="row">
          <div class="container">
              <div class="row">
                 <div>
                   <h3>Live Streaming</h3>
                   <img src="{{ url_for('video_feed') }}" >
                 </div>
              </div>
          </div>                        
      </div>          
   </form>

My Javascript file is as below:我的 Javascript 文件如下:

app.js

$('input[name=checkbox]').change(function () {
      if($(this).is(':checked')){
        console.log("Checkbox is checked..") 
        let command = 'start';

        $.ajax({
          url: '/camera_cmd',
          type: 'POST',
          dataType: 'json',
          data: JSON.stringify({
            'command': command,
          }),
          contentType: 'application/json, charset=UTF-8',
          success: function(data) {
            // location.reload();
            console.log(command);
          },
          error: function(err){
            console.log(err);
          }
        });
      }
      else {        
        $('#attend-image').removeClass('hide'); 
        console.log("Checkbox is not checked..");
        let command = 'stop';

        $.ajax({
          url: '/camera_cmd',
          type: 'POST',
          dataType: 'json',
          data: JSON.stringify({
            'command': command,
          }),
          contentType: 'application/json, charset=UTF-8',
          success: function(data) {
            // location.reload();
            console.log(command);
          },
          error: function(err){
            console.log(err);
          }
        });
      }        
   });

From the Javascript, you would notice that I am using Ajax to send the command to the server.从 Javascript 中,您会注意到我正在使用 Ajax 将命令发送到服务器。 On the server, there is a route that handles the request, and calls the function to do the job as below:在服务器上,有一个路由处理请求,并调用 function 完成如下工作:

app.py

import JSON
import os
import cv2
import threading
from camera import VideoCamera

command = False

video_stream = VideoCamera()

app = Flask(__name__)

@app.route('/camera_cmd', methods=['POST'])
def camera_cmd():
    global command
    
    req = request.get_json()
    
    take_it  = req['command']
     
    state = print(take_it)
    if take_it:
        if take_it == 'start':
            command = True   
            print('command is True')              
        elif take_it == 'stop':
            command = False 
            print('command is False')     
               
    flash("Camera had a smooth operation!", "flash_success") 
        
    t1 = threading.Thread(target=thread_delay, args=('t1', 5))
    t1.start()
    t1.join()   
        
    return json.dumps(state)

def gen(camera):
    global command
    print('Arrived camera Loop')

    while command: 
        print('In the Loop Now!')
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
    
    video_stream.release()


def thread_delay(thread_name, delay):
    global command
    while command:
        time.sleep(delay)
        print(thread_name, '---------->', time.time())
        t2 = threading.Thread(target=gen, args=(video_stream, ))
        t2.start()
        t2.join()

@app.route('/video_feed')
def video_feed():
    return Response(gen(video_stream), 
                    mimetype='multipart/x-mixed-replace; boundary=frame')

I get receive the command sent from the frontend, well printed out and it successfully updates my command global variable to the respective True or False to run the while loop.我收到了从前端发送的命令,打印得很好,它成功地将我的命令全局变量更新为相应的 True 或 False 以运行 while 循环。 Notice I kept the camera control function defined as gen(camera) and the thread_delay(thread_name, delay) function in threads, yet the gen(camera) has refused to be called so that it can start my camera.请注意,我将相机控制 function 定义为gen(camera)thread_delay(thread_name, delay) function 在线程中,但gen(camera)拒绝被调用,以便它可以启动我的相机。

I am sure there is a better way to achieve this, but dont just know how, can someone please help me out?我确信有更好的方法来实现这一点,但不知道如何,有人可以帮我吗? All I want to achieve is, when I click the toggle switch, I want to start my webcam process some AI function and when I am done, I returned the toggle switch, and the camera should go off.我想要实现的是,当我单击切换开关时,我想启动我的网络摄像头进程一些 AI function,当我完成后,我返回了切换开关,并且相机应该 go 关闭。

In your gen() function in your FLASK backend.在 FLASK 后端的 gen() function 中。 Rather than checking Command at while loop, Check it inside while loop.与其在 while 循环中检查命令,不如在 while 循环中检查它。

def gen(camera):
    global command
    print('Arrived camera Loop')
    while (True):
        if(command):# Check Command Here
            frame = camera.get_frame()
            yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')   
        else:
            pass  

As a Part of Front end when you stop the camera feed just replace the camera div with image or the hide the element作为前端的一部分,当您停止摄像头馈送时,只需将摄像头 div 替换为图像或隐藏元素

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM