HyperLPR车牌识别程序本地中能进行正常识别,但将其放到flask搭建的网站中进行识别,不能运行,并报错「Tensor Tensor(*) is not an element of this graph」
HyperLPR中的识别模型采用的是Keras搭建的,定位发现该错误发生在Keras加载模型的时候出问题,错误如下:
TypeError: Cannot interpret feed_dict key as Tensor: Tensor Tensor(“Placeholder:0”, shape=(5, 5, 3, 16), dtype=float32) is not an element of this graph.
flask中的代码如下:
@app.route('/lpr')
def lpr():
file_name = './static/1.JPG'
image = cv2.imread(file_name)
result = pp.SimpleRecognizePlateByE2E(image)
return render_template('test.html', ret_lpr = result)
Solution
【原因分析】
经过查找发现是flask默认情况下使用的是多线程模式,出现问题的原因是TensorFlow在不同线程中加载和使用模型的原因导致的。
可以使用全局默认graph方法解决,如下所示:
-
在加载模型后,增加下面的代码
global graph
graph = tf.get_default_graph()
-
采用下面的方法使用预测函数:
with graph.as_default():
y_hat = keras_model_loaded.predict(predict_request,
batch_size=1, verbose=1)
具体解决办法可以参考 Not An Element Of Tensor Graph
【问题解决】
上述方法是提到最多的解决办法,但是由于我使用的是HyperLPR这个开源库,在开源库中使用的Keras的时候出错,HyperLPR中有好几个加载模型的地方,结构相对较复杂,几经尝试都不能解决该问题。只有另寻他法。
上面提到了出现该问题的原因是flask使用的是多线程,我直接采用单线程是否该问题就解决了,事实证明是这样的。使用flask的单线程方法,问题解决。
- 解决方法:
- 设置flask环境变量:
export FLASK_ENV=production
- 以单线程启动flask:
flask run --without-threads
这里有几个坑需要注意,如下。
【注意】
-
flask在development模式使用单线程启动问题仍然存在,需要在production模式下使用单线程才能成效。
设置flask环境为development/ production的方法,在命令行中,键入
export FLASK_ENV=development
export FLASK_ENV=production
-
flask 以单线程启动的方法:
flask run --without-threads
参考
- from stackoverfkow :flask中直接使用Keras出现该问题(Tensor(*) is not an element of this graph) 的解决方法
-
Not An Element Of Tensor Graph :解决该问题的该问题的实例
-
Keras - issue #14356:该issue的解决方法文中有提到。