实话说,我是绝对没有学过前端的,所以就在网上淘了几个样例然后拼接在一起,无法保证我写的是不是对的,至少跑起来是符合预期的,但是否有隐患我无法保证。
本画板是魔改自@zhoushuozh的画板。我希望画板拥有如下几个功能:
所以,UI界面与画板的功能应该如下图所示:
前4个按钮沿用了@zhoushuozh的画板中的内容,从左至右分别是绘制按钮,顾名思义就是可以在画布上绘制线条;橡皮擦按钮,当选择橡皮擦后,可以再次选择绘制按钮后切换成绘笔;清屏按钮,点了就可以清空屏幕;撤回按钮,撤销上一笔画;保存按钮,点了的话就可以将绘制的草图上传到后端;最后一个按钮是上传按钮,用于用户本地上传已绘制好的草图。
当用户在画板页面绘制好草图后,点击这个按钮就可以把绘制好的草图上传至服务端。在html代码中,我使用保存按钮下方再叠一层文本的方式
<form action="" enctype='multipart/form-data' method='POST'>
<button id="save" title="保存"><i class="iconfont icon-fuzhi">i>button>
<input type="text" name="sketchUpload" id="sketchUpload" value="" style="display:none"/>
form>
把文本的id设为id="sketchUpload"
,然后在后端controller.py
处得到绑定的这个id,它会将绘制的草图按base64进行编码,不要问我原理,问就是不知道,我没学过无法解释。
@app.route('/canvas', methods=['POST', 'GET'])
def upload():
if request.method == 'POST':
sketch_src = request.form.get("sketchUpload")
# ...
basepath = os.path.dirname(__file__)
upload_path = os.path.join(basepath, 'static/sketch_tmp', 'upload.png')
if flag == 1:
# base64 image decode
sketch = base64.b64decode(sketch_src[22:])
user_input = request.form.get("name")
file = open(upload_path, "wb")
file.write(sketch)
file.close()
在后端,通过base64.b64decode
把传来的代码解码,得到手绘图像,然后再保存下来。
用户不想亲自画,刚好本地就有画好的草图,那么就可以通过这个按钮进行本地上传。同样地,这里我先建立了一个button属性的图标,然后参考网上教程,在下面绑定了一个action?学过html的一定觉得这是小儿科,对于我来说就比较难了。
<button id="upload" title="upload">
<div align="center" style="margin:10px 0px 0px 3px">
<embed src="static/css/upload.svg" type="image/svg+xml" width="30" height="30"/>
div>
button>
<form action="" enctype='multipart/form-data' method='POST' id="upload_form">
<input type="file" name="uploadSketch" id="uploadSketch" style="display:none" accept="image/png, image/jpg">
<input type="text" name="uploadFlag" id="uploadFlag" value="0" style="display:none"/>
form>
在后端,就通过下列代码获取这个uploadSketch
的动作id
sketch_src_2 = request.files["uploadSketch"]
sketch_src_2.save(upload_path)
user_input = request.form.get("name")
这是我从网上扒的一个gallery代码,然后根据自己的需求进行了修改。我希望能够在左侧显示草图,右侧显示检索内容,并且按每行6张、每页3行、共5页的规则进行展示,如下图所示。
调整图像的位置折腾了我很久很久。
我们在后端拿到了用户上传的图像后,就可以像一般pytorch模型的inference过程来得到检索结果了,例如下面的代码,得到了检索结果后,我们需要将这些东西都回传给前端,这里我使用了json来保存,在retrieval
这个函数里,就已经将路径集合处理成了json格式,使用json.dumps
就可以进行解析了。
# for retrieval
retrieval_list, real_path = retrieval(retrieval_net, upload_path)
real_path = json.dumps(real_path)
return render_template('panel.html', userinput=user_input, val1=time.time(), upload_src=sketch_src,
retrieval_list=retrieval_list,
json_info=real_path)
最后通过render_template
命令将路径、输入草图等数据传给前端的panel.html
,整个链路就打通了。
我将整份代码已经上传到了github中,整个项目是可以在cpu下跑的,我测试的版本是pytorch1.4.1+cpu、python3.6、flask 0.12.2,通过运行download_prerequisites.sh
应该就可以将项目的所有依赖全部下载下来了。
执行python controller.py
,然后在浏览器中输入http://localhost:5000/canvas
,就可以进入到本系统中了。
解释前端部分完全是噩梦,因为我没学过,很多地方都无从下手,我只能把我想要的功能、行为写下来,实际上还有js和css需要讲的,但我实在说不清楚,所以就把后面的内容全砍掉了,直接看我的代码要好些吧。拖了这么久,终于可以把这个坑填掉了,万幸。