【问题标题】:How to process images from telegram bot without saving to file如何处理来自电报机器人的图像而不保存到文件
【发布时间】:2020-01-23 10:22:59
【问题描述】:

我的电报机器人旨在进行图像分类,因此我需要首先从用户那里读取图像,例如,在进行任何处理并在其上运行我的模型之前使用cv2.imread(telegram_image.jpeg, 1)。有没有办法做到这一点,而无需从电报机器人下载图像文件?

这是我目前的代码:

bot = telegram.Bot(token=TOKEN)
@app.route('/{}'.format(TOKEN), methods=['POST'])
def start():
    # retrieve the message in JSON and then transform it to Telegram object
    update = telegram.Update.de_json(request.get_json(force=True), bot)
    chat_id = update.message.chat.id
    msg_id = update.message.message_id
    imageId = update.message.photo[len(update.message.photo)-1].file_id

我正在尝试在 Heroku 上进行部署(使用 Flask),但之前尝试使用 update.message.photo[-1].get_file().download() 下载文件时遇到了问题。代码运行没有错误,但我在任何地方都找不到图像文件。

对不起,我对此很陌生,非常感谢任何帮助或建议,谢谢!

【问题讨论】:

    标签: python heroku flask computer-vision telegram-bot


    【解决方案1】:

    如果您还没有,我建议使用python-telegram-bot。 wiki 很棒,并且避免使用 Flask。

    您可以避免将文件保存到磁盘,而是使用BytesIO 将其存储在内存中。处理消息的函数可能如下所示:

    from io import BytesIO
    
    def photo(update: Update, context: CallbackContext):
        file = context.bot.get_file(update.message.photo[-1].file_id)
        f =  BytesIO(file.download_as_bytearray())
    
        # f is now a file object you can do something with
    
        result = somefunction(f)
    
        response = 'I procsseed that and the result was %s' % (result,)
    
        context.bot.send_message(chat_id=update.message.chat_id, text=response)
    

    然后将处理程序添加到调度程序。请注意,使用Filters.photo 只有照片消息才能到达此处理程序:

    photo_handler = MessageHandler(Filters.photo, photo)
    dispatcher.add_handler(photo_handler)
    

    这支持 API 的最新版本 (v12)。

    您可能还想看看我整理的脚本:tg_client.py。这是通过Yolov3 库进行图像处理的更大存储库的一部分。它还支持将机器人通信锁定到您自己的电报用户 ID(有关更多信息,请参阅我的 wiki page)。

    您可以根据自己的需要修改它,方法是将upload 函数换成调用您自己的处理脚本的东西。


    编辑:我想我部分误读了你的问题,所以我会回答这部分:

    在进行任何处理并在其上运行我的模型之前使用cv2.imread(telegram_image.jpeg, 1)。有没有办法做到这一点,而无需从电报机器人下载图像文件?

    感谢this answer,我已经在我的代码中处理了这个问题,它建议使用cv2.imdecode 代替cv2.imread

    所以上面的somefunction 可以这样处理:

    def somefunction(input_stream):
        image = cv2.imdecode(numpy.fromstring(input_stream, numpy.uint8), 1)
    
        # image is now what cv2.imread('filename.jpg',1) would have returned.
    
        # rest of your code.
    
        return 'the result of the processing'
    

    这避免了将文件写入磁盘,因为它全部在内存中处理。

    【讨论】:

      【解决方案2】:

      这对我有帮助:

      def get_image(update, context):
          from io import BytesIO
          photo = update.message.photo[-1].get_file()
          # photo.download('img.jpg')
          # img = cv2.imread('img.jpg')
          img = cv2.imdecode(np.fromstring(BytesIO(photo.download_as_bytearray()).getvalue(), np.uint8), 1)
          ...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-31
        • 2015-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-19
        • 2017-08-18
        • 2018-03-31
        相关资源
        最近更新 更多