前言

在这篇博文中,我们将使用 Flask 框架构建一个相机应用程序,我们可以在其中单击图片、录制视频、应用诸如灰度、负片和“仅人脸”之类的滤镜,就像出现在 Snapchat 上的滤镜一样。
文中为前端使用了一个非常基本的设计,因为该项目的主要动机是让自己熟悉 Flask 网络框架并在其中包括实时视频流。同样可以扩展以添加更多功能。

前端

首先,前端是一个基本的 HTML 文件,带有用于获取输入的按钮和用于在后端进行预处理后显示输出帧的图像源标签。文件中的按钮将数据发布到服务器。该文件还显示了一些使用该应用程序的说明。该文件保存在项目目录的“模板”文件夹中。

<body>
<div class="container"><div class="row"><div class="col-lg-8  offset-lg-2"><h2 class="mt-5">CAMERA APP by Hemanth Nag</h2><form method="post" action="{{ url_for('tasks') }}"><input type="submit" value="Stop/Start" name="stop" /><input type="submit" value="Capture" name="click"/><input type="submit" value="Grey" name="grey" /><input type="submit" value="Negative" name="neg" /><input type="submit" value="Face Only" name="face" /><input type="submit" value="Start/Stop Recording" name="rec" /></form><img src="{{ url_for('video_feed') }}" height="80%"><h3 style="font-family:courier;">Instructions:</h3><ol style="font-family:courier;"><li>Stop/Start--Toggle between stop or start live streaming</li><li>Capture--Take still-shot and save in the 'shots' directory</li><li>Grey--Toggle between grayscale and RGB output</li><li>Negative--Toggle between negative and RGB output</li><li>Face Only--Shows just your face if present(Toggle on/off)</li> <li>Start/Stop Recording--Toggle between starting and stopping video recording</li> </div></div>
</div>
</body>

后端

至于后端,它是一个完成所有“魔法”的单个 python 脚本。它保存在项目目录中。
让我们分别查看文件的各个部分以了解它的工作原理。
初始化:

from flask import Flask, render_template, Response, request
import cv2
import datetime, time
import os, sys
import numpy as np
from threading import Threadglobal capture,rec_frame, grey, switch, neg, face, rec, out
capture=0
grey=0
neg=0
face=0
switch=1
rec=0#make shots directory to save pics
try:os.mkdir('./shots')
except OSError as error:pass#Load pretrained face detection model
net = cv2.dnn.readNetFromCaffe('./saved_model/deploy.prototxt.txt', './saved_model/res10_300x300_ssd_iter_140000.caffemodel')#instatiate flask app
app = Flask(__name__, template_folder='./templates')camera = cv2.VideoCapture(0)

在上面的代码中,我们导入了所有必要的模块。
Flask 是一个微型网络框架,它就像是前端和后端之间的桥梁。
我们从flask中导入’Response’和’request’模块来处理HTTP响应请求
'render_template ’ 用于渲染之前显示的 HTML 文件。
OpenCV是用于执行所有计算机视觉任务的模块。
“Thread”模块用于产生新线程。
然后我们声明所有全局变量,它们就像一个“切换开关”来执行不同的任务,比如捕获图像、开始/停止记录和应用滤镜。将变量初始化为 0 以将所有内容设置为 false。
在第 18 行,我们尝试创建一个名为“ shots ”的文件夹(如果它不存在)。这是保存所有捕获图像的位置。
第 24 行加载一个预训练的人脸检测模型以备将来使用,第 27 行创建 Flask 应用程序的实例。第 30 行为内置摄像头创建了一个视频捕获对象。

功能:

def record(out):global rec_framewhile(rec):time.sleep(0.05)out.write(rec_frame)

’ record ’ 函数用于开始记录,即在 ’ rec ’ 变量设置为 true 时将帧写入 avi 文件。它使用“ out ”,这是稍后初始化的视频编写器的对象。
(注意:如果你觉得录制的视频快或慢,请修改 time.sleep 的值)。

def detect_face(frame):global net(h, w) = frame.shape[:2]blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0,(300, 300), (104.0, 177.0, 123.0))   net.setInput(blob)detections = net.forward()confidence = detections[0, 0, 0, 2]if confidence < 0.5:            return frame           box = detections[0, 0, 0, 3:7] * np.array([w, h, w, h])(startX, startY, endX, endY) = box.astype("int")try:frame=frame[startY:endY, startX:endX](h, w) = frame.shape[:2]r = 480 / float(h)dim = ( int(w * r), 480)frame=cv2.resize(frame,dim)except Exception as e:passreturn frame

’ detect_face() ’ 将相机帧作为输入,并返回一个只包含在该帧中检测到的人脸的裁剪帧。它使用之前加载的预训练人脸检测模型。
可以访问此网站 https://www.pyimagesearch.com/2018/02/26/face-detection-with-opencv-and-deep-learning/ 以深入了解这是如何完成的。

def gen_frames():  # generate frame by frame from cameraglobal out, capture,rec_framewhile True:success, frame = camera.read() if success:if(face):                frame= detect_face(frame)if(grey):frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)if(neg):frame=cv2.bitwise_not(frame)    if(capture):capture=0now = datetime.datetime.now()p = os.path.sep.join(['shots', "shot_{}.png".format(str(now).replace(":",''))])cv2.imwrite(p, frame)if(rec):rec_frame=frameframe= cv2.putText(cv2.flip(frame,1),"Recording...", (0,25), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255),4)frame=cv2.flip(frame,1)try:ret, buffer = cv2.imencode('.jpg', cv2.flip(frame,1))frame = buffer.tobytes()yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')except Exception as e:passelse:pass

’ gen_frames ’ 是一个重要的函数,完成实际的帧捕获(通过相机)和处理。它在无限循环中运行。
第 4 行从相机对象捕获帧。如果帧捕获成功,它会检查是否有任何滤镜开关为真。如果’ *face’、‘neg’*或’ gray '为真,则分别在读取帧上应用面部滤镜、负片滤镜和灰度滤镜。
如果 ’ capture ’ 变量设置为 true,则将其重置为 false(全局变量)并且当前帧以 ‘png’ 格式保存。如果“ rec ”为真,则将帧复制到“ rec_frame”全局变量,触发时将其保存到视频文件中。
第 25 行将帧编码到内存缓冲区中,然后转换为字节数组。第 27 行以需要作为 HTTP 响应发送的格式生成帧数据。

HTTP 路由:
这是前端与服务器通信的地方。通信通过 URL 路由在*'GET* ’ 和 ’ POST ’ 方法中发生。

app.route('/')
def index():return render_template('index.html')

‘@app. route(‘/’)’ 是一个 Python 装饰器,Flask 提供它来轻松地将 URL 分配给我们应用程序中的函数。
路由’/‘是根URL,输入根URL时调用’ index() '函数。*“index.html”*文件从函数呈现到网页中。

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

路由 ’ /video_feed ’ 被设置为 html 文件中的图像源。此函数在循环中返回由“ gen_frames() ”产生的帧的响应块。

@app.route('/requests',methods=['POST','GET'])
def tasks():global switch,cameraif request.method == 'POST':if request.form.get('click') == 'Capture':global capturecapture=1elif  request.form.get('grey') == 'Grey':global greygrey=not greyelif  request.form.get('neg') == 'Negative':global negneg=not negelif  request.form.get('face') == 'Face Only':global faceface=not face if(face):time.sleep(4)   elif  request.form.get('stop') == 'Stop/Start':if(switch==1):switch=0camera.release()cv2.destroyAllWindows()else:camera = cv2.VideoCapture(0)switch=1elif  request.form.get('rec') == 'Start/Stop Recording':global rec, outrec= not recif(rec):now=datetime.datetime.now() fourcc = cv2.VideoWriter_fourcc(*'XVID')out = cv2.VideoWriter('vid_{}.avi'.format(str(now).replace(":",'')), fourcc, 20.0, (640, 480))#Start new thread for recording the videothread = Thread(target = record, args=[out,])thread.start()elif(rec==False):out.release()elif request.method=='GET':return render_template('index.html')return render_template('index.html')

路由“ /requests ”被分配给“ tasks() ”函数,它处理所有的开关和视频录制。这个路由有’ POST '和*'GET* '方法,即它接受信息并发送信息。默认情况下,所有以前的路由都是“ GET ”。
如果来自客户端的 HTTP 方法是“POST”,则“ request.form.get ”接受来自用户按下的按钮的数据,并反转全局变量的先前状态,这些变量的作用类似于“ gen_frame ”函数中的开关。
例如,当用户按下“灰色”按钮时,“灰色”全局变量被设置为 True,从而在“ gen_frames ”函数中将帧转换为灰度。当再次按下“灰色”按钮时,“灰色”设置为假,使帧恢复正常。
在运行 Flask 应用程序的同时将帧录制到视频中非常棘手。最简单的解决方案是启动一个新线程。

线程是一个独立的执行流。这意味着你的程序将同时发生两件事。线程与其对等线程共
享数据段、代码段、文件等信息,同时包含自己的寄存器、堆栈、计数器等。

在我们的例子中,’ record() ’ 函数有它自己的 while 循环,因此该循环在新线程中运行。
首先,当“ rec ”为真时,我们创建一个“ VideoWriter ”对象。在第 37 行,我们初始化一个新线程,目标是“ record() ”函数,第 38 行开始运行“ *record()”函数的新线程。
当再次按下录制按钮时,
‘VideoWriter’*对象被释放并且停止录制以将视频保存在根目录中。
最后,如果来自客户端的 HTTP 方法是“ GET ”,则呈现“index.html”模板。

主函数:

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

*‘app.run()’*用于在其默认地址启动Flask应用程序: http://127.0.0.1:5000/
通过向函数“run”添加“host”和“port”参数,可以设置不同的主机和端口号。将主机设置为广播地址0.0.0.0将使应用程序在整个局域网(wifi 等)中可见。
因此,如果你的移动设备连接到同一个 Wi-Fi,你就可以从它访问该应用程序。这是一个很好的“间谍摄像头”。

结论

要运行这个应用程序,你应该在你的 PC 上安装 python、flask 和 OpenCV。
要启动应用程序,请移至命令提示符中的项目目录。键入并输入

python camera_flask_app.py

现在,将http://127.0.0.1:5000/ 复制粘贴到你的浏览器中,就是这样。
你可以添加更多功能(例如 AI 滤镜)来构建 Snapchat 式应用程序。你还可以增强用户界面,使其更具交互性和色彩。你可以在这个 GitHub 帐户中获取该项目的源代码。

https://github.com/hemanth-nag/Camera_Flask_App

使用Python+Flask+OpenCV构建一个相机应用程序相关推荐

  1. 用 Python 和 OpenCV 来测量相机到目标的距离

    用 Python 和 OpenCV 来测量相机到目标的距离 http://python.jobbole.com/84378/ 几天前,一个叫 Cameron 的 PyImageSearch 读者发来邮 ...

  2. 使用Python和OpenCV构建图像金字塔

    使用Python和OpenCV的图像金字塔 1. 效果图 2. 什么是图像金字塔? 3. 依赖 4. 源码 参考 这篇博客将介绍如何使用两种方法构造图像金字塔. 使用Python和OpenCV构建金字 ...

  3. Python使用tkinter构建一个多元回归预测模型GUI界面(接受用户输入数据并给出模型推理结果)

    Python使用tkinter构建一个多元回归预测模型GUI界面(接受用户输入数据并给出模型推理结果) 目录

  4. 使用Python,OpenCV构建移动文档扫描仪

    使用Python,OpenCV构建移动文档扫描仪 1. 效果图 2. 步骤 3. 源码 参考 1. 效果图 图1,鸟瞰图 图2,角度不太一样,鸟瞰图的效果也不一致: 2. 步骤 使用OpenCV构建文 ...

  5. 程序员疯狂记事:如何利用众多技术栈构建一个 Web 应用程序?!

    [CSDN 编者按]"Elixir.Phoenix.Absinthe.GraphQL.React和Apollo"--在这几个关键词中,有几个是身为开发者的你一直想玩但还没来得及玩的 ...

  6. 构建一个移动应用程序要花多少钱?

    构建一个移动应用程序要花多少钱? How much does it cost to build a mobile app? 不幸的是,对于一个移动应用程序的开发成本应该是多少这个问题,没有一个单一的答 ...

  7. python flask实战订餐系统微信小程序-60nginx + uwsgi 实现多进程访问

    python flask实战订餐系统微信小程序-60nginx + uwsgi 实现多进程访问 B站配套视频教程观看 uwsgi多进程配置 uwsgi.ini配置 nginx和uwsgi通过配置文件s ...

  8. LabWindows_CVI测试技术及工程应用_学习笔记1(构建一个简单的程序)

    构建一个简单的程序 1.创建工程文件 或File--〉New--〉Project(*.prj),默认名Untitled.prj,存储在Unititled.cws的工作空间中 File--〉Save U ...

  9. python flask实战订餐系统微信小程序-59flask部署单进程启动服务

    欢迎关注原创 Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn. ...

最新文章

  1. win7下,发布到iis上,本地可以正常访问,远程访问失败
  2. logging总结 - log4j2使用流程[归档存储]
  3. python py生成及调用pyd(so)文件
  4. 小波降噪与重构例子 python
  5. 最牛营业部——国信泰然九路揭秘
  6. *** line xxxx of `fraud.data': bad value of xxxx for attribute `id_11'
  7. 算术编码(Arithmetic Coding)源代码
  8. ubuntu grub 操作
  9. kali linux 2019.1 替换burpsuite pro 1.7.37
  10. Zabbix 监控 MySQL
  11. 测开之路二十二:迭代器、生成器
  12. android6.0闪光灯源码,android手电筒+闪光灯基本源码_linux编程_linux公社-linux系统门户网站...
  13. Jmeter之接口测试流程详解
  14. mysql索引的常识
  15. [总结]IOS开发工程师之路
  16. 生产环境和开发环境_环境部署:开发、测试和线上环境的区别
  17. SLAM基础——李群李代数
  18. 【图文详解】Android手机系统精简 搭建Linux集群硬件环境 Jdk运行HelloWorld
  19. 阿里巴巴离职DBA职业生涯总结--吕海波
  20. redis.clients java_redis报错redis/clients/jedis/JedisPoolConfig'(curren

热门文章

  1. c/c++程序员的黄金发展方向:音视频开发
  2. 如何开好一家水果店,海尔冷链在线助您一臂之力
  3. python爬虫翻页_使用Python实现博客上进行自动翻页
  4. 【宠物远程监控DIY】openwrt+rt5350+mjpg摄像头
  5. vivado2018.2与modelsim10.6安装
  6. 有个程序员父亲是一种什么样的体验?
  7. 用PIL实现滤镜(一)——素描、铅笔画效果
  8. 全国C++职位需求统计20170507
  9. 半波、全波、滤波的电路经验公式(小白的学习工作总结)
  10. python多线程+socket实现聊天室(最终版)