You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用LineBot开发目标检测应用遇类型错误:expected bytes, HTTPResponse found

LineBot目标检测应用HTTP图片URL报错处理

报错信息

[2022-11-23 19:13:12,335] ERROR in app: Exception on /callback [POST]
Traceback (most recent call last):
  File "C:\officiallandprice\myproject\myenv\lib\site-packages\flask\app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\officiallandprice\myproject\myenv\lib\site-packages\flask\app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\officiallandprice\myproject\myenv\lib\site-packages\flask\app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\officiallandprice\myproject\myenv\lib\site-packages\flask\app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "part1deploy_3.py", line 55, in callback
    handler.handle(body, signature)
  File "C:\officiallandprice\myproject\myenv\lib\site-packages\linebot\webhook.py", line 259, in handle
    self.__invoke_func(func, event, payload)
  File "C:\officiallandprice\myproject\myenv\lib\site-packages\linebot\webhook.py", line 271, in __invoke_func
    func(event)
  File "part1deploy_3.py", line 201, in handle_content_message
    text_detected1=text_detected(user.user_id)
  File "part1deploy_3.py", line 81, in text_detected
    image = vision.Image(content=input_file)
  File "C:\officiallandprice\myproject\myenv\lib\site-packages\proto\message.py", line 604, in __init__
    super().__setattr__("_pb", self._meta.pb(**params))
TypeError: expected bytes, HTTPResponse found
127.0.0.1 - - [23/Nov/2022 19:13:12] "POST /callback HTTP/1.1" 500 -

问题根源

  1. Google Cloud Vision API的参数要求:vision.Image(content=...)的content参数必须传入字节类型的图片原始数据,而urllib.request.urlopen()返回的是HTTPResponse响应对象,并非字节数据,这是触发报错的直接原因。
  2. PIL读取的潜在问题:即使Vision API不报错,后续Image.open(input_file)也会失败——HTTPResponse的数据流在第一次读取后指针会移到末尾,第二次读取时无法获取有效内容。

修正后的代码

修改text_detected函数,先将URL对应的图片读取为字节数据,再分别用于Vision API和PIL处理:

def text_detected(user_id):
    # 读取图片为字节数据
    url = 'https://storage.googleapis.com/img_platecapture/{}.jpg'.format(user_id)
    with urllib.request.urlopen(url) as response:
        img_bytes = response.read()

    # 传入字节数据给Vision API
    image = vision.Image(content=img_bytes)
    response = vision_client.text_detection(image=image)

    if response.error.message:
        raise Exception(
            '{}\nFor more info on error messages, check: '
            'https://cloud.google.com/apis/design/errors'.format(
                response.error.message))

    # 用字节数据创建PIL Image对象(需用BytesIO包装)
    from io import BytesIO
    img = Image.open(BytesIO(img_bytes))
    draw = ImageDraw.Draw(img)
    font = ImageFont.truetype("simsun.ttc", 18)

    # 补充原代码遗漏的bound变量定义
    for text in response.text_annotations[1::]:
        ocr = text.description
        bound = text.bounding_poly
        draw.text((bound.vertices[0].x-25, bound.vertices[0].y-25), ocr, fill=(255,0,0), font=font)
        
        draw.polygon(
            [
                bound.vertices[0].x,
                bound.vertices[0].y,
                bound.vertices[1].x,
                bound.vertices[1].y,
                bound.vertices[2].x,
                bound.vertices[2].y,
                bound.vertices[3].x,
                bound.vertices[3].y,
            ],
            None,
            'yellow',
        )

    texts=response.text_annotations
    a=str(texts[0].description.split())

    b=re.sub(u"([^\u4e00-\u9fa5\u0030-u0039])","",a)
    b1="".join(b)
    print("偵測到的地址為:",b1)
    return b1

关键说明

  • Vision API必须用字节数据:这是Google Cloud Vision API的硬性规定,content参数需要直接传入图片的原始字节流,用于API解析图片内容。
  • PIL的处理方式:PIL的Image.open()可以接受字节流,但需要用BytesIO将字节数据包装成类文件对象,才能被PIL正确识别读取。
  • 原代码的其他问题:原循环中使用了未定义的bound变量,需补充bound = text.bounding_poly,否则会触发NameError。

内容的提问来源于stack exchange,提问作者april

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 04:40:41