基于hnsw近邻算法的人脸图像检索Web应用

最近用Bootstrap+Flask+hnsw近邻搜索算法+人脸识别算法,实现了人脸相似度检索的Web应用,最后利用Apache部署了这个web应用。

  • 人脸识别算法是face recognition,可以通过pip安装:sudo pip3 install face_recognition。
  • hnsw算法来自hnswlib:sudo pip3 install hnswlib。
  • 使用Bootstrap之前,要先搭好脚手架,否则设置的class无效。

一、界面及搜索效果

1. 建立索引页面

在这里插入图片描述

2. 显示建立成功

在这里插入图片描述

3. 检索页

在这里插入图片描述

4. 显示检索结果

在这里插入图片描述

二、建立索引页

2.1 页面

下面是建立索引页的关键,也就是body部分。其中第一个row是为了传递给用户交互信息,当索引建立完成后,这个地方会显示建立成功或失败的信息。之后的row部分是输入框组和按钮组。每点击一个button,会向Flask后台返回该button的value值,这时,只要根据返回的value,确定执行什么函数就可以了。


<div class="container">
    <div class="row">
        <div class="col-md-12">
            {% with messages = get_flashed_messages() %}
                {% if messages %}
                    <div class="flashes alert alert-success alert-dismissible" role="alert">
                        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                        {% for message in messages %}
                        {{ message }}
                    {% endfor %}
                    </div>
                {% endif %}
            {% endwith %}
        </div>
    </div>
    <div class="row">
        <div class="col-md-4 col-md-offset-5">
            <h1>Create Index</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <form action="" enctype='multipart/form-data' method='POST'>
                <div class="form-group">
                    <label for="exampleInputEmail">Input Images' Path</label>
                    <input type="text" name="img_path" class="form-control" id="exampleInputEmail" placeholder="Input Images' Path">
                </div>
                <div class="form-group">
                    <label for="exampleM">Input M</label>
                    <input type="text" name="M" class="form-control" id="exampleM" placeholder="Input M">
                </div>
                <div class="form-group">
                    <label for="exampleMax">Input max elements</label>
                    <input type="text" name="Max" class="form-control" id="exampleMax" placeholder="Input Max Elements">
                </div>
                <!--<div class="form-group">-->
                    <!--<input type="file" name="file" style="margin-top:20px;"/>-->

                <!--</div>-->
                <div class="form-group">
                    <input type="submit" name="create_index" value="创建索引" class="btn btn-primary btn-lg btn-block button-new" onclick="" style="margin-top:50px;"/>
                </div>

                <div class="form-group">
                    <input type="submit" name="add_items" value="增量索引" class="btn btn-primary btn-lg btn-block button-new" onclick="" style="margin-top:20px;"/>
                </div>
                <div class="form-group">
                    <input type="submit" name="search" value="检索" class="btn btn-success btn-lg btn-block button-new" style="margin-top:20px;"/>
                </div>
                <div class="form-group">
                    <input type="submit" name="delete" value="删除索引" class="btn btn-danger btn-lg btn-block button-new" onclick="" style="margin-top:20px;"/>
                </div>

            </form>
        </div>
    </div>
</div>

2.2 Flask后台

根据点击button返回的value执行相应的函数


if request.method == 'POST':
    create_index = request.form.get('create_index')
    add_items = request.form.get('add_items')
    search_yes = request.form.get('search')
    delete = request.form.get('delete')

    config = configparser.ConfigParser()
    config.read('config')
    feature_dim = int(config.get('hnsw', 'dimension'))
    index_path = 'index.idx'

    if create_index:
        flash('')
        # 初始化变量
        imgDir = request.form.get('img_path')
        m = int(request.form.get('M'))
        max_elements = int(request.form.get('Max'))

        # 调用函数
        info = createIndex_function(feature_dim, max_elements, m, index_path, imgDir, config)
        flash(info)
        return redirect('/create')

    if add_items:
        flash('')
        imgDir = request.form.get('img_path')
        info = addIndex(feature_dim,index_path,imgDir)
        flash(info)
        return redirect('/create')

    if search_yes:
        return redirect('/upload')

    if delete:
        flash('')
        if os.path.exists(index_path):
            os.rename(index_path, 'index_backup.idx')
            # os.remove(self.index_path)
        flash('Already removed.')
        return redirect('/create')



return render_template('create_index.html')

三、检索页

3.1 页面

检索页一共分为两个页面,一个是初始页,另一个是返回检索结果的页面。两者唯一的不同就是检索成功页多了一个img区域。
以下是检索初始页的container 部分(upload.html)

<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-5">
            <h1>图像检索</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <form action="" enctype='multipart/form-data' method='POST'>
                <div class="form-group">
                    <label for="exampleInputEmail">Input K</label>
                    <input type="number" name="K" class="form-control" id="exampleInputEmail" placeholder="Enter K">
                </div>
                <div class="form-group">
                    <input type="file" name="file" style="margin-top:20px;"/>

                </div>

                <div class="form-group">
                    <input type="submit" value="上传" class="btn btn-primary btn-lg btn-block button-new" style="margin-top:50px;"/>
                </div>
            </form>
        </div>
    </div>
</div>

下面是检索成功页面的container部分,其实只是多了img标签里的内容,用于返回检索结果。(upload_ok.html)

<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-5">
            <h1>图像检索</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <form action="" enctype='multipart/form-data' method='POST'>
                 <div class="form-group">
                    <label for="exampleInputEmail">Input K</label>
                    <input type="number" name="K" class="form-control" id="exampleInputEmail" placeholder="Enter K">
                </div>
                <div class="form-group">
                    <input type="file" name="file" style="margin-top:20px;"/>

                </div>

                <div class="form-group">
                    <input type="submit" value="上传" class="btn btn-primary btn-lg btn-block button-new" style="margin-top:50px;"/>
                </div>
            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <img src="{{ url_for('static', filename= './images/results.jpg',_t=val1) }}" width="100%" height="100%" alt=""/>
        </div>
    </div>

</div>

3.2 Flask 后台

def upload():
    if request.method == 'POST':
        f = request.files['file']
        k = request.form.get('K')
        # print('*************************************************',k)
        if not (f and allowed_file(f.filename)):
            return jsonify({"error": 1001, "msg": "请检查上传的图片类型,仅限于png、PNG、jpg、JPG、bmp"})

        user_input = request.form.get("name")
        basepath = os.path.dirname(__file__)  # 当前文件所在路径

        upload_path = os.path.join(basepath, 'static/images', secure_filename(f.filename))  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径
        # upload_path = os.path.join(basepath, 'static/images','test.jpg')  #注意:没有的文件夹一定要先创建,不然会提示没有该路径
        f.save(upload_path)
        # print(upload_path)
        print('*************************************************',k)
        k = int(k)
        search(upload_path,k)
        return render_template('upload_ok.html', userinput=user_input, val1=time.time())

    return render_template('upload.html')

四、Apache部署

apache部署的时候遇到了很多问题,在试过了网上各大教程后,这篇最靠谱(从头到尾都很靠谱)!
How To Deploy a Flask Application on an Ubuntu VPS

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值