为什么在使用 Flask 的网页上使用 jinja 模板将数据返回为 none?

Why is using jinga template returning data as none on a webpage using flask?

我正在尝试基本上打印一个 table 来显示我在网页上调用 flask 的函数的数据。我查看了 Jinga 模板,这就是我尝试使用的模板,但无济于事。

我的代码附在下面。我的 cv_acp 文件中的 结果 是我试图以 table 形式显示的结果。

目前,我的TSN_PICreturns结果如下:

The input video frame is classified to be PlayingCello - 99.33 PlayingGuitar - 0.28 PlayingPiano - 0.16 BoxingSpeedBag - 0.10 StillRings - 0.06

但我希望能够使用 flask 以 table 格式在网页上显示此内容

我的代码如下:

cv_acp

def TSN_PIC(img):
    img = image.imread(img)
 
    fig, ax = plt.subplots(figsize=(18, 18))
    ax.imshow(img.asnumpy())

    transform_fn = transforms.Compose([
    video.VideoCenterCrop(size=224),
    video.VideoToTensor(),
    video.VideoNormalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
    img_list = transform_fn([img.asnumpy()])
    net = get_model('vgg16_ucf101', nclass=101, pretrained=True)
    pred = net(nd.array(img_list[0]).expand_dims(axis=0))
    classes = net.classes
    topK = 5
    ind = nd.topk(pred, k=topK)[0].astype('int')
    print('The input video frame is classified to be')
    for i in range(topK):
        result = ('\t%s - %.2f'%(classes[ind[i].asscalar()], nd.softmax(pred)[0][ind[i]].asscalar()*100))
        print((result)) 
    return plt.show()

app.py

@app.route("/cv/action_prediction/TSN_PIC", methods=['POST'])
def cv_acp_TSN_PIC_upload_image():
    if 'file' not in request.files:
        flash('No file part')
        return redirect(request.url)
    file = request.files['file']
    if file.filename == '':
        flash('No image selected for uploading')
        return redirect(request.url)
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        print(app.config)
        path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        print(path)
        file.save(path)
        #print(file.config)
        result = cv_acp.TSN_PIC(path)
       # print (results)
        #print('upload_image filename: ' + filename)
        flash('Image successfully uploaded and displayed below')
        return render_template('cv_acp_TSN_PIC.html', filename=filename, result=result)
    else:
        flash('Allowed image types are -> png, jpg, jpeg, gif')
        return redirect(request.url)


@app.route('/cv/action_prediction/TSN_PIC/display/<filename>')
def cv_acp_TSN_PIC_display_image(filename):
    #print('display_image filename: ' + filename)
    #return MASK_RCNN('static', filename='uploads/' + filename)
    return redirect(url_for('static', filename='uploads/' + filename), code=301)

if __name__ == "__main__":
#app.run()
app.run()

cv_acp_TSN_PIC.html

<div id="content" class="p-4 p-md-5 pt-5">

        <h2 class="mb-4">TSN PIC</h2>
        <!Doctype html>
<title>Python Flask File Upload Example</title>
<h2>Select a file to upload</h2>
<p>
    {% with messages = get_flashed_messages() %}
      {% if messages %}
        <ul>
        {% for message in messages %}
          <li>{{ message }}</li>
        {% endfor %}
        </ul>
      {% endif %}
    {% endwith %}
</p>
{% if filename %}
    <div>
        <img src="{{ url_for('cv_acp_TSN_PIC_display_image', filename=filename) }}">
        {% block content %}
    <div class="container">
        <p>{{results}}</p>
    </div>
{% endblock %}
    </div>
    

    
{% endif %}
<form method="post" action="/cv/action_prediction/TSN_PIC" enctype="multipart/form-data">
    <dl>
        <p>
            <input type="file" name="file" autocomplete="off" required>
        </p>
    </dl>
    <p>
        <input type="submit" value="Submit">
    </p>
</form>
      </div>

如果您在终端或 Jupyter notebook 中工作,plt.show() 可以满足您的需求。对于网页来说,没那么多。

除此之外,您的开端不错,这似乎取决于获取要显示的上传图像。因此,您的挑战是要么在生成页面之前将 matplotlib 图像保存到磁盘,要么推迟生成图像直到通过 <img src=... 请求它,然后以某种方式 return 来自 cv_acp_TSN_PIC_display_image 而不是保存文件的路径。

要执行前者,plt.savefig('uploads/image.png') 可能是您所需要的,但需要注意的是,一旦有多个用户访问该应用程序,固定文件名就会严重破坏事情。

要执行后者,请参阅 this question and its answer

创建一个包含您需要的数据和 return 数据的字典列表。然后你可以遍历数据并构建你的 table.

results = []
for i in range(topK):
    result = ('\t%s - %.2f'%(classes[ind[i].asscalar()], nd.softmax(pred)[0][ind[i]].asscalar()*100))
    datadict = {
         'header': yourheadername,
         'data': yourdatahere
    }
        
    results.append(datadict)

return results


<table border=1>
{% for result in results%}
    <tr>
      <th>
        {{result.header}}
      </th>
    </tr>
    <tr>
      <td>
        {{result.data}}
      </td> 
    </tr>
{% endfor %}

    </table>