【OpenCV DNN】Flask 视频监控目标检测教程 03

欢迎关注『OpenCV DNN @ Youcans』系列,持续更新中


本系列从零开始,详细讲解使用 Flask 框架构建 OpenCV DNN 模型的 Web 应用程序。

上节介绍了 从URL地址读取图片进行处理 和 上传本地图片进行卡通处理,本节介绍上传本地图片进行人脸检测。


3.3 上传本地图片进行人脸检测

我们的第三个例程,在cvFlask02的基础上,使用OpenCV级联检测器检测上传图像中的人脸和人眼。

我们可以完全套用cvFlask02的项目结构和程序框架,只需要修改Python程序cvFlask02.py中的调用图像处理子程序,使用OpenCV级联检测器检测上传图像中的人脸和人眼。


3.3.1 OpenCV 级联分类器类 cv::CascadeClassifier

OpenCV 中定义了级联分类器类 cv::CascadeClassifier。在 Python 语言中,使用接口函数 cv.CascadeClassifier() 从文件加载级联分类器模型,成员函数 cv.CascadeClassifier.detectMultiScale() 对图像进行目标检测。

cv.CascadeClassifier(filename)
cv.CascadeClassifier.detectMultiScale(image[, scaleFactor=1.1, 
minNeighbors=3, flags=0, minSize=Size(), maxSize=Size()]) → objects

OpenCV 提供了 Haar 级联检测器的预训练模型如下,可以从 OpenCV 安装包 \data\haarcascades中提取,或者从【GitHub】opencv/data下载。

haarcascade_eye.xml, 眼睛
haarcascade_eye_tree_eyeglasses.xml, 戴眼镜的眼睛
haarcascade_frontalface_alt.xml, 正面人脸
haarcascade_frontalface_alt2.xml, 正面人脸
haarcascade_frontalface_alt_tree.xml, 正面人脸
haarcascade_frontalface_default.xml, 正面人脸
haarcascade_fullbody.xml, 人体
haarcascade_lefteye_2splits.xml, 左眼 
haarcascade_righteye_2splits.xml, 右眼
haarcascade_smile.xml, 笑脸

使用 Haar 级联检测器检测图片中的人脸的步骤如下:
(1)创建一个 CascadeClassifier 级联分类器对象,使用 load() 方法从 .xml 文件加载级联分类器模型。
(2)读取待检测的图片。
(3)使用detectMultiScale()函数检测图片,返回检测到的边界矩形。
(4)将检测到的边界矩形绘制到检测图片上。


3.3.2 cvFlask03 项目的构建步骤

项目cvFlask03的文件树如下。

---项目文件名\
    |---static\
|---templates\
    |    |---processed.html
    |    |---upload.html
|--- cvFlask03.py

cvFlask03.py中图像处理子程序的代码如下,其它部分的代码与cvFlask02.py相同。

# cvFlask03.py
def imageProcessing(filepath):  # 图片处理子程序:人脸检测+人眼检测
    imgCV = cv2.imread(filepath)  # 从 filepath 路径读取图片
    gray = cv2.cvtColor(imgCV, cv2.COLOR_BGR2GRAY)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "../data/haarcascade_frontalface_alt2.xml"
    face_detector = cv2.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    eye_path = "../data/haarcascade_eye.xml"  # 人眼检测器
    eye_detector = cv2.CascadeClassifier(eye_path)  # <class 'cv2.CascadeClassifier'>

    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=1,
                                           minSize=(40, 40), maxSize=(300, 300))

    # 绘制人脸检测框
    for x, y, w, h in faces:
        cv2.rectangle(imgCV, (x,y), (x+w,y+h), (0, 0, 255), 3)

        # 在人脸区域内检测人眼
        roi = gray[y:y+h, x:x+w]  # 提取人脸
        # 检测人眼
        eyes = eye_detector.detectMultiScale(roi, scaleFactor=1.1, minNeighbors=1,
                                             minSize=(15, 15), maxSize=(80, 80))
        # 绘制人眼
        for ex, ey, ew, eh in eyes:
            cv2.rectangle(imgCV, (x+ex,y+ey), (x+ex+ew,y+ey+eh), (255,0,0),2)

    return imgCV

cvFlask03的脚本运行过程也与cvFlask02完全相同,具体步骤如下。

(1)进入cvFlask03项目的根目录,运行程序cvFlask03.py,启动流媒体服务器。
(2)在浏览器输入URL(http://192.168.3.249:5000/upload),打开upload.html网页。在浏览器点击页面上的选择按钮,选择本地的图片上传,上传的图片保存到static\images目录。
(3)程序cvFlask03.py对上传的图片进行人脸检测和人眼检测,在图片上以红色和蓝色方框标记检测到的人脸和人眼。然后激活processed.html网页,显示原始图像和处理后的图像。

在这里插入图片描述

(4)手机连接到局域网,按照控制台显示的内容在浏览器输入IP地址(http://192.168.3.249:5000/upload),也可以上传手机中的图片进行处理,结果如图所示。

在这里插入图片描述


Flask03 完整例程

---项目文件名\
    |---static\
|---templates\
    |    |---processed.html
    |    |---upload.html
|--- cvFlask03.py

cvFlask03.py

# cvFlask03.py
# OpenCV+Flask 图像处理例程 03
# 上传本地图片进行处理,在网页上显示处理结果
# Copyright 2023 Youcans, XUPT
# Crated:2023-4-28

# coding:utf-8
import cv2
import os, time
from flask import Flask, render_template, request, make_response, jsonify
from werkzeug.utils import secure_filename
from datetime import timedelta

# 设置允许的文件格式
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])

app = Flask(__name__)  # 用当前脚本名称实例化Flask对象
app.send_file_max_age_default = timedelta(seconds=1)  # 设置静态文件缓存过期时间

@app.route('/upload', methods=['POST', 'GET'])  # 添加路由
def upload():
    if request.method == 'POST':
        f = request.files['file']  # 从表单的 file 字段获取文件,file为该表单的name值
        print("user_input:", f.filename)  # tiger02.png
        if not (f and allowed_file(f.filename)):  # 检查图片类型
            return jsonify({"error": 1001, "msg": "上传图片必须是 png/jpg/jpeg/bmp 类型"})

        user_input = request.form.get("name")  # 获取表单输入的 name 值, png/jpg/jpeg/bmp
        basepath = os.path.dirname(__file__)  # 当前文件所在路径 C:\Users\David\cvFlask\
        # upload_filepath = os.path.join(basepath, 'static\images', secure_filename(f.filename))  # 合成上传图片的保存路径
        upload_filepath = os.path.join(basepath, 'static\images', 'upload.jpg')  # 合成上传图片的保存路径
        print("upload_filepath", upload_filepath)  # upload_path, C:\Users\David\cvFlask\static\images\upload.jpg
        f.save(upload_filepath)  # 将上传的图片保存到 upload_path 路径

        # OpenCV 图像处理
        dst = imageProcessing(upload_filepath)  # 调用图片处理子程序
        cv2.imwrite(os.path.join(basepath, 'static/images', 'processed.jpg'), dst)  # 保存处理后的图片
        user_input = f.filename  # 上传图片的文件名
        return render_template('processed.html', userinput=user_input, val1=time.time())

    return render_template('upload.html')

def imageProcessing(filepath):  # 图片处理子程序:人脸检测+人眼检测
    imgCV = cv2.imread(filepath)  # 从 filepath 路径读取图片
    gray = cv2.cvtColor(imgCV, cv2.COLOR_BGR2GRAY)

    # 加载 Haar 级联分类器 预训练模型
    model_path = "../data/haarcascade_frontalface_alt2.xml"
    face_detector = cv2.CascadeClassifier(model_path)  # <class 'cv2.CascadeClassifier'>
    eye_path = "../data/haarcascade_eye.xml"  # 人眼检测器
    eye_detector = cv2.CascadeClassifier(eye_path)  # <class 'cv2.CascadeClassifier'>

    # 使用级联分类器检测人脸
    faces = face_detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=1,
                                           minSize=(40, 40), maxSize=(300, 300))

    # 绘制人脸检测框
    for x, y, w, h in faces:
        cv2.rectangle(imgCV, (x,y), (x+w,y+h), (0, 0, 255), 3)

        # 在人脸区域内检测人眼
        roi = gray[y:y+h, x:x+w]  # 提取人脸
        # 检测人眼
        eyes = eye_detector.detectMultiScale(roi, scaleFactor=1.1, minNeighbors=1,
                                             minSize=(15, 15), maxSize=(80, 80))
        # 绘制人眼
        for ex, ey, ew, eh in eyes:
            cv2.rectangle(imgCV, (x+ex,y+ey), (x+ex+ew,y+ey+eh), (255, 0, 0), 2)

    return imgCV

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

if __name__ == '__main__':
    # 启动一个本地开发服务器,激活该网页
    print("URL: http://127.0.0.1:5000/upload")
    app.run(host='0.0.0.0', port=5000, debug=True)  # 绑定 IP 地址和端口号


processed.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>OpenCV+Flask 上传图片</title>
</head>
<body>
    <h1 align="center">OpenCV+Flask 例程:上传本地图片进行处理</h1>
    <p align="center">Developed by youcans@xupt, 2023</p>    
    <form action="" enctype='multipart/form-data' method='POST'>
        <label>选中文件:</label>
        <input type="text" class="txt_input" name="name" value={{userinput}} style="margin-top:10px;"/>
    </form>
    <h2 align="center">图片处理结果</h2>
    <table width="700" height="350" border="5" align="center" frame=void>
		<tr>
			<td align="center" valign="middle">原始图片</td>
			<td align="center" valign="middle">处理结果</td>
		</tr>
		<tr>
			<td align="center" valign="middle">
                <img src="{{ url_for('static', filename= './images/upload.jpg',_t=val1) }}" width="300" height="300" alt="上传的原始图片"/>
            </td>
			<td align="center" valign="middle">
                <img src="{{ url_for('static', filename= './images/processed.jpg',_t=val1) }}" width="300" height="300" alt="处理完成的图片"/>
            </td>
		</tr>
    </table>

</body>
</html>

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>OpenCV+Flask 上传图片</title>
</head>
<body>
    <h1 align="center">OpenCV+Flask 例程:上传本地图片处理</h1>
    <p align="center">Developed by youcans@xupt, 2023</p>
        <form action="" enctype='multipart/form-data' method='POST'>
        <label>选择按钮:</label>
        <input type="file" name="file" style="margin-top:25px;"/>
        <br>
        <label>选中文件:</label>
        <input type="text" class="txt_input" name="name"  value="png/jpg/jpeg/bmp" style="margin-top:20px;"/>
        <br>
        <label>上传按钮:</label>
        <input type="submit" value="上传图片" class="button-new" style="margin-top:20px;"/>
        <br>
    </form>
</body>
</html>

【本节完】

下节我们将讨论:使用Flask框架构建一个视频流服务器。


版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:
【OpenCV DNN】Flask 视频监控目标检测教程 03(https://blog.csdn.net/youcans/article/details/130864216)
Copyright 2023 youcans, XUPT
Crated:2023-05-25

欢迎关注『OpenCV DNN @ Youcans』系列,持续更新中
【OpenCV DNN】Flask 视频监控目标检测教程 01
【OpenCV DNN】Flask 视频监控目标检测教程 02

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youcans_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值