说说具体技术之前的一些曲折吧,如果想看技术直接向后翻即可。

车牌识别项目的大致功能我们已经完成:手动读取一张图片最终输出图中的车牌号。接着就是搭建一个网页,我们小组目标的功能是:用户可以向该网页上传图片,一经上传,我们的程序就开始工作,最终输出识别出的车牌号。计划用python flask实现。说得很理想,但是其实我们小组的成员python flask的知识储备基本为0。

Web的搭建由我和周延霖负责,周延霖认为上述功能要求过高,应该做成静态网页输出识别结果即可。其实一开始想的也比较难,做出一个可以上传图片的网页,把图片存储到本地文件夹确实没什么问题,但是怎么让我们的pyhton程序能够主动调用这张图片进行识别呢,这个逻辑说起来很简单但是其实我们不知道怎么实现。林筠皓建议设置一个控件用于启动python程序,这似乎可行。

关于Web搭建的准备,系统地学习Python Flask不仅没有必要(在人工智能的项目里面学习Web知识?)而且也很难实现(基本课时都在八小时以上),看老师给的PPT也很不好学。只好直接看别人的代码了。

正式开始Web的搭建之路,还请读者注意,本篇文章不是系统地教学,只是记录自己短期内在完全没有相关知识储备的情况下,怎么利用Python Flask迅速搭建起一个满足需求的网页。

刚开始只是打算一点一点地实现目标功能罢,先从上传图片做起,这个的参考资源的获取也是比较容易的。此处参考bilibili网站【谷雨课堂】Python干货实战【030】 网站开发之-上传图片或文件,链接:https://www.bilibili.com/video/BV1Rh41117yy?share_source=copy_web&vd_source=a903512a82ff2959ba4cac987f40e02a。

1.先介绍一下基本的工作环境配置:

配置文件夹

  • app.py文件就是网页的运行程序。

  • templates文件夹需要有一个upload(其他名字也行).html文件,主要是网页的前端代码,app.py文件会调用该html文件。

  • static文件夹底下有个upload文件夹用于存放用户上传的文件。

  • 这个upload文件夹我全程似乎没有用到。

2.先看upload.html文件,这个主要就是相当于设计你的网页要长什么样。

1
2
3
4
5
6
7
8
9
10
11
<html>
<head>
<title>File Upload</title>
</head>
<body>
<form action="/api/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value='上传' />
</form>
</body>
</html>

title就是网页的名称了,只需要一个上传文件的表单即可,非常简单,不必赘述。效果如图所示。

网页效果

3.app.py文件,运行网页的根本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from flask import Flask, url_for, redirect, render_template, request
import time
import os
import character # 字符切割的API所在文件
import my_cnn_predict # 字符识别的API所在文件

app = Flask(__name__)

# 基础路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# static路径
STATIC_DIR = os.path.join(BASE_DIR, 'static')

# 上传路径(static文件夹下的upload文件夹)
UPLOAD_DIR = os.path.join(STATIC_DIR, 'upload')

# 上传文件处理,自动找上传的参数名
def upfile(field='', dir=''):

if len(request.files) < 1:
return ""

if field == '':
for k in request.files:
field = k
break

f = request.files[field]
if f == None:
print("没有上传的字段" + field)
return ""
fname = f.filename

if fname == '':
return ''

ext = fname.rsplit('.', 1)[1]
unix_time = int(time.time())
new_filename = str(unix_time) + '.' + ext
now = int(time.time())

timeStruct = time.localtime(now)
str_ymd = time.strftime("%Y-%m-%d", timeStruct)
if dir == '':
dir = str_ymd
if not os.path.exists(UPLOAD_DIR+'/'+dir):
os.makedirs(UPLOAD_DIR+'/'+dir)
print(UPLOAD_DIR+'/'+dir+'/'+new_filename)
f.save(UPLOAD_DIR+'/'+dir+'/'+new_filename)
return dir+'/'+new_filename, new_filename

@app.route("/")
def index():
return render_template('upload.html')


@app.route("/api/upload", methods=['POST'])

# 上传文件的函数,修改的关键所在,其他地方不动
'''
网页原本的思路是:
上传一个文件|图片,一个if-else语句,如果没有上传文件则提示没有上传文件,否则创建一个文件夹(根据时间)存储该文件

那么修改的可能就出现了,完全不需要实现之前想的那么复杂的逻辑
只需要在有上传文件的情况下调用存储好的图片和车牌识别的API即可

首先修改张龑的API,原本是以文件夹为单位处理(逐个处理该文件夹下所有图片),现在只需要以图片为单位处理即可,怎么修改下一小节再描述
切分的结果存储在results文件夹下,以该图片命名的文件夹
接着向字符识别网络传输切分后的图片存储路径,识别结果作为字符串直接打印即可
'''
def uploader():
upload_file, new_filename = upfile()
if upload_file == '':
return "您没有上传文件 <a href='/'>返回</a>"
else:
character.split("static/upload/2022-07-18", new_filename, "results")
result = my_cnn_predict.predict("results/" + new_filename.rstrip(".jpg"))
return "<a href='/static/upload/" + upload_file + "'>" + result + "</a> <a href='/'>返回</a>"

if __name__ == '__main__':
app.run()

图片存储情况如下图所示。

图片存储

4.最后就是修改切分字符的API了

原本是一个文件夹下遍历所有图片,现在只需要对传入的图片做处理即可,取消循环,比较简单。

最后让大家看看效果吧

网页效果

image

image

image

可以重复多次上传图片进行识别,这里不过多进行演示,完美。