gpt4 book ai didi

python-3.x - Python-Keras API服务器在经过训练的自定义模型上处理图像

转载 作者:行者123 更新时间:2023-12-03 17:45:44 25 4
gpt4 key购买 nike

我遵循了这个教程,创建了一个自定义对象YoloV3 Keras模型:
https://momoky.space/pythonlessons/YOLOv3-object-detection-tutorial/tree/master/YOLOv3-custom-training

模型工作正常,我的下一个目标是创建一个能够在上传图片后处理Image的Python Flask API。
我已经开始修改Code here for image detection

那是我添加的代码:

@app.route('/api/test', methods=['POST'])
def main():
img = request.files["image"].read()
img = Image.open(io.BytesIO(img))
npimg=np.array(img)
image=npimg.copy()
image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#cv2.imshow("Image", image)
#cv2.waitKey()
cv2.imwrite('c:\\yolo\\temp.jpg', image)
image = 'c:\\yolo\\temp.jpg'
yolo = YOLO()
r_image, ObjectsList = yolo.detect_img(image)
#response = {ObjectsList}
response_pikled = jsonpickle.encode(ObjectsList)
#yolo.close_session()
return Response(response=response_pikled, status=200, mimetype="application/json")
app.run(host="localhost", port=5000)


所以我的问题是,它仅在第一次迭代时起作用,当我上传新图像时,我收到以下错误:

File "C:\Users\xxx\Anaconda3\envs\yolo\lib\site-packages\tensorflow\python\client\session.py", line 929, in run
run_metadata_ptr)
File "C:\Users\xxx\Anaconda3\envs\yolo\lib\site-packages\tensorflow\python\client\session.py", line 1095, in _run
'Cannot interpret feed_dict key as Tensor: ' + e.args[0])
TypeError: Cannot interpret feed_dict key as Tensor: Tensor Tensor("Placeholder:0", shape=(3, 3, 3, 32), dtype=float32) is not an element of this graph.


这是代码的原始静态部分:

if __name__=="__main__":
yolo = YOLO()
image = 'test.png'
r_image, ObjectsList = yolo.detect_img(image)
print(ObjectsList)
#cv2.imshow(image, r_image)
cv2.imwrite('detect.png', r_image)

yolo.close_session()


真正令我困惑的是如何在应用程序启动时加载模型,并在每次发布新图像时执行检测。
谢谢

更新

在构造器部分,有一个引用的Keras后端会话:

 **def __init__(self, **kwargs):
self.__dict__.update(self._defaults) # set up default values
self.__dict__.update(kwargs) # and update with user overrides
self.class_names = self._get_class()
self.anchors = self._get_anchors()
self.sess = K.get_session()
self.boxes, self.scores, self.classes = self.generate()**


添加K.clear_session后,它可用于多个系列请求:

 @app.route('/api/test', methods=['POST'])
def main():
img = request.files["image"].read()
img = Image.open(io.BytesIO(img))
npimg=np.array(img)
image=npimg.copy()
image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#cv2.imshow("Image", image)
#cv2.waitKey()
cv2.imwrite('c:\\yolo\\temp.jpg', image)
image = 'c:\\yolo\\temp.jpg'
yolo = YOLO()
r_image, ObjectsList = yolo.detect_img(image)
#response = {ObjectsList}
response_pikled = jsonpickle.encode(ObjectsList)
#yolo.close_session()
K.clear_session()
return Response(response=response_pikled, status=200, mimetype="application/json")


可以避免模型,在每次计算时都需要加载锚点和类,从而避免这种情况:

ogs/000/trained_weights_final.h5 model, anchors, and classes loaded.
127.0.0.1 - - [27/Dec/2019 22:58:49] "?[37mPOST /api/test HTTP/1.1?[0m" 200 -
logs/000/trained_weights_final.h5 model, anchors, and classes loaded.
127.0.0.1 - - [27/Dec/2019 22:59:08] "?[37mPOST /api/test HTTP/1.1?[0m" 200 -
logs/000/trained_weights_final.h5 model, anchors, and classes loaded.
127.0.0.1 - - [27/Dec/2019 22:59:33] "?[37mPOST /api/test HTTP/1.1?[0m" 200


--

最佳答案

我设法将其作为原型运行。我上传了一个仓库:vulcan25/image_processor来实现所有这一切。

我研究的第一件事是本教程中的代码中YOLO.detect_img方法的功能。此方法采用文件名,该文件名将由原始代码#L152-L153中的cv2.imread立即处理。然后从其中返回的数据由self.detect_image在内部进行处理(请注意拼写上的差异),并用cv2.show显示结果。

这种行为对webapp不利,我想将所有内容都保留在内存中,因此想出改变功能的最佳方法是将YOLO子类化并覆盖detect_img方法,以使其表现不同。因此,在processor/my_yolo.py中,我执行以下操作:

from image_detect import YOLO as stock_yolo

class custom_yolo(stock_yolo):
def detect_img(self, input_stream):

image = cv2.imdecode(numpy.fromstring(input_stream, numpy.uint8), 1)

original_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
original_image_color = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)

r_image, ObjectsList = self.detect_image(original_image_color)
is_success, output_stream = cv2.imencode(".jpg", r_image)

return is_success, output_stream




注意:在以后的决定中,我将 image_detect.py拉到了 append K.clear_session()的仓库中。也可以将上面的mod放在该文件中,但是我一直坚持该部分的子类化。


这接受一个流,然后分别使用 cv2.imencode (source)cv2.imdecode (source)代替 imshowimread

现在,我们可以定义单个单个函数,该函数将依次运行所有图像处理程序。这会将代码部分(和依赖项)与flask应用程序分开,这很不错:


yolo = custom_yolo() # create an object from the custom class defined above.

def process(intput_stream):

start_time = time.time()

is_success, output_stream = yolo.detect_img(input_stream)
io_buf = io.BytesIO(output_stream)

print("--- %s seconds ---" % (time.time() - start_time))

return is_success, io_buf.read()



在Flask中,我们可以用相同的方式调用此方法,在该方法中,我们已经可以通过以下方式获得上载文件的流: request.files['file'].read()(实际上是 werkzeug.datastructures.FileStorage对象的方法,就像我已经 documented elsewhere一样) 。

作为附带说明,可以从终端运行此功能。如果要启动我的存储库,则需要在 processor容器中执行此操作(请参阅自述文件结尾的 docker exec语法)...

from my_yolo import process
with f.open('image.jpg', 'rb') as f:
is_sucess, processed_data = process(f.read())


然后将结果写入文件:

with f.open('processed_image.jpg', 'wb' as f):    
f.write(processed_data)


请注意,我的仓库实际上有两个单独的flask应用程序(基于我放在一起的另一个 upload script,它在前端实现了dropzone.js)。

我可以在两种模式下运行:


processor/src/app.py:可在端口5001上访问,直接运行 process(传入请求阻止,直到返回已处理的数据)。
flask/src/app.py:可在端口5000上访问,这为每个传入请求创建一个 rq作业,然后 processor容器作为工作程序运行以处理来自队列的这些请求。


每个应用程序都有自己的 index.html,该 process在前端执行自己的独特实现。模式(1)将图像直接写到页面上,模式(2)将链接添加到页面上,单击该链接会指向一个单独的终结点,该终结点可为该图像提供服务(处理时)。

主要区别在于 processor/src/app.py的调用方式。在模式(1) ~1.6s per image下:

from my_yolo import process

if file and allowed_file(file.filename):
# process the upload immediately
input_data = file.read()
complete, data = process(input_data)


正如评论中提到的,我在这种模式下看到了非常快速的转换:CPU上的 view。该脚本还使用redis集来维护上载文件的列表,该列表可用于进一步在 flask/src/app.py端点上进行验证。

在模式(2) flask/src/qu.py中:

from qu import image_enqueue

if file and allowed_file(file.filename):
input_data = file.read()

job = img_enqueue(input_data)
return jsonify({'url': url_for('view', job_id=job.id)})


我实现了一个单独的文件 img_enqueue,该文件实现了此 process函数,该文件最终从 flask/src/my_yolo.py加载 rq函数,该函数的定义为:

def process(data): pass


这是一个重要的目标。通常,使用 flask时,将在与 processor/src/my_yolo.py服务相同的代码库中定义此函数的内容。实际上,我实际上已将业务逻辑放入 redis中,这使我们能够与图像处理依赖项分离容器,并最终将其托管在其他地方,只要它与 flask共享 processor/Dockerfile连接服务。

请查看回购中的代码以获取更多信息,并随时通过任何进一步的查询(或如果遇到问题)针对该回购记录问题。请注意,我可能会引入重大更改,因此您不妨分叉。

我试图保持这一点很简单。从理论上讲,可以对其进行少量编辑以支持处理任何处理工作量的不同 ~17.s,但是同一前端允许您从流中提交任何类型的数据:图像,CSV,其他文本等。


真正令我困惑的是如何在应用程序启动时加载模型,并在每次发布新图像时执行检测。谢谢


您会注意到,当您运行此模式(1)时,它是完美的,因为烧瓶服务器启动( ~1s)并且单个图像处理占用 rq时,依赖项就会加载。这是理想的,尽管可能会导致服务器上的整体内存使用率更高,因为每个WSGI工作者都需要加载所有依赖项。

在模式(2)中运行-将处理传递给rq worker时,每次处理图像时都会加载库,因此速度要慢得多。我将尝试解决此问题,我只需要研究如何在 K.clear_session()部署中预加载库;我以前很接近这个问题,但是那是在我偶然发现 问题的时候,所以还没有时间重新测试此问题的修复程序(尚未)。

关于python-3.x - Python-Keras API服务器在经过训练的自定义模型上处理图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59482473/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com