Python 3.x 如何使用Python 3从S3获得的OpenCV读取图像?

Python 3.x 如何使用Python 3从S3获得的OpenCV读取图像?,python-3.x,amazon-web-services,opencv,amazon-s3,boto3,Python 3.x,Amazon Web Services,Opencv,Amazon S3,Boto3,我的S3 bucket文件夹中有一堆图像 我有一个S3的按键列表(img_list),我可以读取和显示图像: key = img_list[0] bucket = s3_resource.Bucket(bucket_name) img = bucket.Object(key).get().get('Body').read() 我有一个功能: def image_from_s3(bucket, key): bucket = s3_resource.Bucket(bucket)

我的S3 bucket文件夹中有一堆图像

我有一个S3的按键列表(
img_list
),我可以读取和显示图像:

key = img_list[0]
bucket = s3_resource.Bucket(bucket_name)
img = bucket.Object(key).get().get('Body').read()
我有一个功能:

def image_from_s3(bucket, key):

    bucket = s3_resource.Bucket(bucket)
    image = bucket.Object(key)
    img_data = image.get().get('Body').read()

    return Image.open(io.BytesIO(img_data))
现在我想使用OpenCV读取图像,但我得到一个错误:

key = img_list[0]
bucket = s3_resource.Bucket(bucket_name)
img = bucket.Object(key).get().get('Body').read()
cv2.imread(img)


SystemError                               Traceback (most recent call last)
<ipython-input-13-9561b5237a85> in <module>
      2 bucket = s3_resource.Bucket(bucket_name)
      3 img = bucket.Object(key).get().get('Body').read()
----> 4 cv2.imread(img)

SystemError: <built-in function imread> returned NULL without setting an error
key=img\u列表[0]
bucket=s3\u资源.bucket(bucket\u名称)
img=bucket.Object(key.get().get('Body').read()
cv2.imread(img)
系统错误回溯(最近一次调用上次)
在里面
2 bucket=s3_资源.bucket(bucket_名称)
3 img=bucket.Object(key.get().get('Body').read()
---->4 cv2.imread(img)
SystemError:返回NULL而未设置错误

请告知如何正确阅读?

对不起,我在评论中弄错了。此代码在内存缓冲区中设置一个PNG文件,以模拟从S3获得的内容:

#!/usr/bin/env python3

from PIL import Image, ImageDraw
import cv2

# Create new solid red image and save to disk as PNG
im = Image.new('RGB', (640, 480), (255, 0, 0))
im.save('image.png')

# Slurp entire contents, raw and uninterpreted, from disk to memory
with open('image.png', 'rb') as f:
   raw = f.read()

# "raw" should now be very similar to what you get from your S3 bucket
现在,我只需要这个:

nparray = cv2.imdecode(np.asarray(bytearray(raw)), cv2.IMREAD_COLOR)
因此,您需要:

bucket = s3_resource.Bucket(bucket_name)
img = bucket.Object(key).get().get('Body').read()
nparray = cv2.imdecode(np.asarray(bytearray(img)), cv2.IMREAD_COLOR)

希望这将是上述要求的最佳解决方案,使用URL读取s3存储桶中的图像

import os
import logging
import boto3
from botocore.client import Config
from botocore.exceptions import ClientError
import numpy as np
import urllib
import cv2

s3_signature ={
'v4':'s3v4',
'v2':'s3'
}



def create_presigned_url(bucket_name, bucket_key, expiration=3600, signature_version=s3_signature['v4']):

    s3_client = boto3.client('s3',
                         aws_access_key_id="AWS_ACCESS_KEY",
                         aws_secret_access_key="AWS_SECRET_ACCESS_KEY",
                         config=Config(signature_version=signature_version),
                         region_name='ap-south-1'
                         )
    try:
        response = s3_client.generate_presigned_url('get_object',
                                                Params={'Bucket': bucket_name,
                                                        'Key': bucket_key},
                                                ExpiresIn=expiration)
        print(s3_client.list_buckets()['Owner'])
        for key in s3_client.list_objects(Bucket=bucket_name,Prefix=bucket_key)['Contents']:
            print(key['Key'])
    except ClientError as e:
        logging.error(e)
        return None
        # The response contains the presigned URL
    return response

def url_to_image(URL):
    resp = urllib.request.urlopen(url)
    image = np.asarray(bytearray(resp.read()), dtype="uint8")
    image = cv2.imdecode(image, cv2.IMREAD_COLOR)

    return image


seven_days_as_seconds = 604800

generated_signed_url = create_presigned_url(you_bucket_name, bucket_key, 
seven_days_as_seconds, s3_signature['v4'])
print(generated_signed_url)
image_complete = url_to_image(generated_signed_url)

#just debugging Purpose to show the read Image
cv2.imshow('Final_Image',image_complete)
cv2.waitKey(0)
cv2.destroyAllWindows()

使用For循环迭代键列表中的所有键。在调用函数create\u presigned\u url之前。

当您不从磁盘读取时,您需要
img=cv2.imdecode(buffer)
。@MarkSetchell在这种情况下的缓冲区将是
bucket.Object(key.get().get('Body')。read()
?可能,我不知道您的bucket中有什么。。如果是JPEG,它应该以十六进制的
0xff0xd8
开头。@MarkSetchell我的bucket由文件夹组成,其中一个文件夹包含所有PNG图像。我也有PDF,但这是另一个问题。我想连接到S3(我已经这样做了),拿着钥匙把它传给cv2。下面是我得到的错误:TypeError:imdecode()缺少必需的参数“flags”(位置2)。这些标志与
cv2.imread()相同。
.Worked!!!如果我错了,你能纠正我吗:你正在用bytearray读取它,因为它是以字节形式给出的,然后传输到一个矩阵?
imdecode()
似乎需要一个Numpy数组和一个AFAIK,
np.asarray()
在不复制的情况下从
bytearray
准确地创建它,所以它应该相当快。可能还有其他方法(我不是专家),所以如果有人知道,请告诉我。顺便说一句,我想你可能无法更改你得到的Numpy图像,除非你用
myCopy=nparray.copy()
进行复制,或者你将原来的
np.asarray(…)
更改为
np.array(…)
。非常感谢!我已经给你发了一封电子邮件(在你的网站上)。我的荣幸@MarkSetchellNote:请在respVery-nice代码中将url更改为url,以便处理来自s3的图像。但是你能帮助我如何从s3到cv2读取多个图像吗?你可以在一行url=s3中完成。生成预签名的url('get_object',Params={'Bucket':s3BucketName,'Key':documentName})无需循环并列出对象