Python Web开发:在线人脸检测

来自CloudWiki
跳转至: 导航搜索

背景

在上一节基础上 提供一种在线Web调用的功能,

即用户在网页上上传一张照片,然后单击检测即可在网页上实现人脸检测并获取检测结果。

这种方式可以方便的让用户无须编写任何脚本代码即可体验功能

实训步骤

编写网页端功能

主要使用Bootstrap的模式对话框来实现图片的在线检测,

采用这种方式,可以方便的在页面中进行额外的界面操作 而不影响页面原有布局。

serviceApp/platform.html:

在<h3>一. 体验产品</h3></br>下面添加“模式对话框”代码:

<!-- 按钮触发模态框 -->
                <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
                    人脸检测
                </button>
                <!-- 模态框(Modal) -->
                <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
                    aria-hidden="true">
                    <div class="modal-dialog">
                        <div class="modal-content">
                            <div class="modal-header">
                                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
                                    ×
                                </button>
                                <h4 class="modal-title" id="myModalLabel">
                                    在线人脸检测
                                </h4>
                            </div>
                            <div class="modal-body">
                                <img id="photoIn" src="{% static 'img/sample.png' %}" class="img-responsive"
                                    style="max-width:250px">
                                <input type="file" id="photo" name="photo" />
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-default" data-dismiss="modal">关闭
                                </button>
                                <button type="button" id="compute" class="btn btn-primary">
                                    开始检测
                                </button>
                            </div>
                        </div><!-- /.modal-content -->
                    </div><!-- /.modal -->
                </div>
                <script>
                    $(function () {
                        $('#photo').on('change', function () {
                            var r = new FileReader();
                            f = document.getElementById('photo').files[0];
                            r.readAsDataURL(f);
                            r.onload = function (e) {
                                document.getElementById('photoIn').src = this.result;
                            };
                        });
                    });
                </script>

  • 通过“人脸检测”的按钮来调用模式对话框,通过设定按钮的data-toggle和data-target参数来设定模式对话框,
  • 模式对话框分为三部分功能:modal-header,modal-body 和modal-footer.
  • 图像显示逻辑:模式对话框主体放置了两个组件:一个组件用于显示当前上传图片,另一个文件上传组件用于选择本地图片进行上传。当用户单击“浏览”时,会触发输入图片的change属性,待上传的图片实时显示在图片组件上。

图片发送和结果显示

接下来使用Ajax技术实现图片发送,将图片发送至服务器并进行人脸检测。

                <script>
                    $('#compute').click(function () {
                        formdata = new FormData();
                        var file = $("#photo")[0].files[0];
                        formdata.append("image", file);
                        $.ajax({
                            url: '/serviceApp/facedetectDemo/', // 调用Django服务器计算函数
                            type: 'POST', // 请求类型
                            data: formdata,
                            dataType: 'json', // 期望获得的响应类型为json
                            processData: false,
                            contentType: false,
                            success: ShowResult // 在请求成功之后调用该回调函数输出结果
                        })
                    })
                </script>
                <script>
                    function ShowResult(data) {
                        var v = data['img64'];
                        document.getElementById('photoIn').src = "data:image/jpeg;base64, " + v;
                    }
                </script>
  • 基于Ajax的图像发送,采用FormData的格式,即将上传的图片文件用formdata.append完成封装,
  • 在ajax的data属性中嵌入formdata变量,以POST方式发送到地址/serviceApp/facedetectDemo/中。
  • 如果成功,返回结果使用函数ShowResult显示。base64是网络上最常见的用于传输8位字节码的编码方式之一,为了能够在网络上正常传输图像数据,这里采用base64进行图像的解编码。

后台视图函数

后台视图函数 我们可以在Python Web开发:人脸识别后台搭建 代码的基础上修改,

在原代码的基础上增加人脸框划定功能。

serviceApp/views.py:

import base64

@csrf_exempt
def facedetectDemo(request):
    result = {}

    if request.method == "POST":
        if request.FILES.get('image') is not None:  #
            img = read_image(stream=request.FILES["image"])
        else:
            result["#faceNum"] = -1
            return JsonResponse(default)

        if img.shape[2] == 3:
            imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 彩色图像转灰度图像
        else:
            imgGray = img

        #进行人脸检测
        values = face_detector.detectMultiScale(imgGray,
                                           scaleFactor=1.1,
                                           minNeighbors=5,
                                           minSize=(30, 30),
                                           flags=cv2.CASCADE_SCALE_IMAGE)

        #将检测得到的人脸检测关键点坐标封装
        values = [(int(a), int(b), int(a + c), int(b + d))
                  for (a, b, c, d) in values]

        # 将检测框显示在原图上
        for (w, x, y, z) in values:
            cv2.rectangle(img, (w, x), (y, z), (0, 255, 0), 2)

        retval, buffer_img = cv2.imencode('.jpg', img)  # 在内存中编码为jpg格式
        img64 = base64.b64encode(buffer_img)  # base64编码用于网络传输
        img64 = str(img64, encoding='utf-8')  # bytes转换为str类型
        result["img64"] = img64  # json封装
    return JsonResponse(result)

  • 实现逻辑: 处理函数从POST请求中通过request.FILES.get('image')获取图像
  • 然后根据定义的read_image来读取图像,转灰度,进行人脸检测
  • 将检测到的矩形画在原图上,然后对图像进行jpg及base64转码 返回数据。

添加路由

serviceApp/urls.py:

from django.urls import path
from . import views

app_name = 'serviceApp'

urlpatterns = [
    path('download/', views.download, name='download'),  # 资料下载
    path('platform/', views.platform, name='platform'),  # 人脸识别开放平台
    path('getDoc/<int:id>/',views.getDoc,name='getDoc'),
    path('facedetect/',views.facedetect,name='facedetect'),#人脸检测API
    path('facedetectDemo/',views.facedetectDemo,name='facedetectDemo'),#人脸检测API
]


验证

Python21060502.png

Python21060503.png