将PIL图像传递到google cloud vision,无需保存和读取

2024-06-16 11:56:47 发布

您现在位置:Python中文网/ 问答频道 /正文

更新如下

有没有办法将PIL图像传递给google cloud vision

我试图使用io.Bytesio.StringImage.tobytes(),但我总是得到:

Traceback (most recent call last):
  "C:\Users\...\vision_api.py", line 20, in get_text
    image = vision.Image(content)
  File "C:\...\venv\lib\site-packages\proto\message.py", line 494, in __init__
    raise TypeError(
TypeError: Invalid constructor input for Image:b'Ma\x81Ma\x81La\x81Ma\x81Ma\x81Ma\x81Ma\x81Ma\x81Ma\x81Ma\x81Ma\x81La\x81Ma\x81Ma\x81Ma\x81Ma\x80Ma\x81La\x81Ma\x81Ma\x81Ma\x80Ma\x81Ma\x81Ma\x81Ma\x8 ...

或者,如果我直接传递PIL图像:

TypeError: Invalid constructor input for Image: <PIL.Image.Image image mode=RGB size=480x300 at 0x1D707131DC0>

这是我的代码:

image = Image.open(path).convert('RGB')   # Opening the saved image
cropped_image = image.crop((30, 900, 510, 1200))   # Cropping the image

vision_image = vision.Image(# I passed the different options)   # Here I need to pass the image, but I don't know how
client = vision.ImageAnnotatorClient()
response = client.text_detection(image=vision_image)   # Text detection using google-vision-api

为清晰起见:

我希望google文本检测只分析保存在我磁盘上的图像的某一部分。所以我的想法是使用PIL裁剪图像,然后将裁剪后的图像传递给google vision。但是不可能将PIL图像传递到vision.Image,因为我得到了上面的错误

来自谷歌的documentation

这可以在vision.Image类中找到:

Attributes:
        content (bytes):
            Image content, represented as a stream of bytes. Note: As
            with all ``bytes`` fields, protobuffers use a pure binary
            representation, whereas JSON representations use base64.

            Currently, this field only works for BatchAnnotateImages
            requests. It does not work for AsyncBatchAnnotateImages
            requests.

工作选项是将PIL图像保存为我的磁盘上的PNG/JPG,并使用以下方式加载:

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

vision_image = vision.Image(content=content)

但这是缓慢的,似乎没有必要。对我来说,使用google vision api背后的全部要点就是打开简历的速度

自2021年9月25日起更新

from PIL import Image
from io import BytesIO
from google.cloud import vision


with open('images/screenshots/screenshot.png', 'rb') as image_file:
    data = image_file.read()
    try:
        image = vision.Image(content=data)
        print('worked')

    except TypeError:
        print('failed')


im = Image.open('images/screenshots/screenshot.png')
buffer = BytesIO()
im.save(buffer, format='PNG')
try:
    image = vision.Image(buffer.getvalue())
    print('worked')

except TypeError:
    print('failed')

第一个版本按预期工作,但我无法让第二个版本按@Mark Setchell的建议工作。前几个字符(~50)是相同的,其余的完全不同

自2021年9月26日起更新

两个输入都属于<class 'bytes'>类型。在问题的顶部可以看到完整的错误堆栈

使用此代码:

print(input_data[:200])
print(type(input_data))

我得到以下输出:

b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x048\x00\x00\x07\x80\x08\x06\x00\x00\x00+a\xe7\n\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00 \x00IDATx\x9c\xec\xbdy\xd8-\xc7Y\x1f\xf8\xab\xea>\xe7\xdb\xef\xaa\xbbk\xb3%\xcb\x8b\x16[\x12\xc6\xc8\xbb,\x1b\x03\x06\xc6\x8111\x93@2y\xc2381\x8b1\x90\x10\x9e\xf18\x93\x10\x0811\x84\x192\x0c3\x9e\x1020\x03\x03\xc3\xb0\x04\xf0C0\xc6\x96m\xc9\x96m\xed\xb2dI\x96\xaetu\xf7\xed\xdb\xcf\xe9\xae\x9a?j\xe9\xea\xbd\xba\xbb\xbaO\x9f\xef\x9e\xd7\xd6\xfd\xfat\xbf\xf5Vu-o\xbd\xf5\xeb\xb7\xde"\xef\xff\xc7\'8\x1c\x13\x07\x00\xd2\x82\xcc6\xe5\xc6\xa8B&'
<class 'bytes'>

对于工作输入。 以及:

b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x048\x00\x00\x07\x80\x08\x06\x00\x00\x00+a\xe7\n\x00\x01\x00\x00IDATx\x9c\xec\xbdw\x80$\xc7u\x1f\xfc\xab\xea\xeeI\x9bw/\'\x1cr\xce\x04@\x10\x04A\x82`\x84\x95%J"\x95,\xcb\x1f%\x91T\xb0$*}\x1fM\xd9\x96\x95EY\x94(\xc9\xb6\x92i+\x90\x12\x83(3)0\x82\x08$rN\x07\\\xce\xb7\xb7yBw\xd5\xf7G\x85\xaeN3\xdd=\xdd\xb3\xb3{\xfb\xc8\xc3\xceLW\xbd\xca\xaf\xde\xfb\xf5\xabW\xe4{\xdeu\x84\xa3`\xe2\x00@J\xe0Y&\xdf\x00e($\x94\x94\'p\xcc\xc3\xda\xe7Y\x0c\xf1Te\x13\xbf\xcc>\xfa:]Y=x\x84\x7f\xe8\xc23u\x1f\x91l\xfd\x99'
<class 'bytes'>

对于失败的输入


Tags: io图像imagebytespilgooglecontentfile
2条回答

据我所知,您从一个PIL Image开始,希望在内存中获得一个PNG图像,而无需访问磁盘。所以你需要这个:

#!/usr/bin/env python3

from PIL import Image
from io import BytesIO

# Create PIL Image like you have - filled with red
im = Image.new('RGB', (320,240), (255,0,0))

# Create in-memory PNG - like you want for Google Cloud Vision
buffer = BytesIO()
im.save(buffer, format="PNG")

# Look at first few bytes
PNG = buffer.getvalue()
print(PNG[:20])

它会打印出来,如果您将图像以PNG格式写入磁盘,然后将其以二进制格式读回,则会得到这样的结果-除了这一点,它在内存中执行,而不进入磁盘:

b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01@'

最好有完整的错误堆栈和更准确的代码段。但形式呈现的信息似乎是两种不同“图像”的混淆。可能是复制/粘贴错误,因为tutorials有完全相同的行:

response = client.text_detection(image=image)

但是前面提到的教程image是由vision.Image()创建的,所以我认为在给出的代码中应该是:

response = client.text_detection(image=vision_image)

至少如果我正确理解了代码片段,image是PIL图像,而vision_image是应该传递给text_detection方法的视觉图像。因此,在vision.Image()中执行的任何操作都不会对错误消息产生影响

相关问题 更多 >