it-swarm.com.de

Wie lese ich eine Bilddatei aus dem S3-Bucket direkt in den Speicher?

Ich habe den folgenden Code

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import boto3
s3 = boto3.resource('s3', region_name='us-east-2')
bucket = s3.Bucket('sentinel-s2-l1c')
object = bucket.Object('tiles/10/S/DG/2015/12/7/0/B01.jp2')
object.download_file('B01.jp2')
img=mpimg.imread('B01.jp2')
imgplot = plt.imshow(img)
plt.show(imgplot)

und es funktioniert. Das Problem ist jedoch, dass die Datei zuerst in das aktuelle Verzeichnis heruntergeladen wird. Kann man eine Datei lesen und als Bild direkt im RAM dekodieren?

7
Dims

Greg Merritts Antwort unten ist eine bessere Methode.

Ich möchte die Verwendung von Python's NamedTemporaryFile im Modul tempfile vorschlagen. Es erstellt temporäre Dateien, die beim Schließen der Datei gelöscht werden (Danke an @NoamG)

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import boto3
import tempfile

s3 = boto3.resource('s3', region_name='us-east-2')
bucket = s3.Bucket('sentinel-s2-l1c')
object = bucket.Object('tiles/10/S/DG/2015/12/7/0/B01.jp2')
tmp = tempfile.NamedTemporaryFile()

with open(tmp.name, 'wb') as f:
    object.download_fileobj(f)
    img=mpimg.imread(tmp.name)
    # ...Do jobs using img
9
Hyeungshik Jung

Ich würde vorschlagen, io module zu verwenden, um die Datei direkt in den Speicher zu lesen, ohne eine temporäre Datei verwenden zu müssen.

Zum Beispiel:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import boto3
import io

s3 = boto3.resource('s3', region_name='us-east-2')
bucket = s3.Bucket('sentinel-s2-l1c')
object = bucket.Object('tiles/10/S/DG/2015/12/7/0/B01.jp2')

file_stream = io.StringIO()
object.download_fileobj(file_stream)
img = mpimg.imread(file_stream)
# whatever you need to do

Sie können auch io.BytesIO verwenden, wenn Ihre Daten binär sind.

11
Greg Merritt

Das Streaming des Bildes ist durch Angabe des Dateiformats in imread() möglich.

import boto3
from io import BytesIO
import matplotlib.image as mpimg
import matplotlib.pyplot as plt

resource = boto3.resource('s3', region_name='us-east-2')
bucket = resource.Bucket('sentinel-s2-l1c')

image_object = bucket.Object('tiles/10/S/DG/2015/12/7/0/B01.jp2')
image = mpimg.imread(BytesIO(image_object.get()['Body'].read()), 'jp2')

plt.figure(0)
plt.imshow(image)
5
Adrian Tofting

Weiterentwicklung der Antwort von Greg Merritt, um alle Fehler im Kommentarbereich zu beheben. Verwenden Sie BytesIO anstelle von StringIO, und verwenden Sie PIL Image anstelle von matplotlib.image.

Die folgende Funktion funktioniert für python3 und boto3. Ebenso write_image_to_s3 Funktion ist ein Bonus.

from PIL import Image
from io import BytesIO
import numpy as np

def read_image_from_s3(bucket, key, region_name='ap-southeast-1'):
    """Load image file from s3.

    Parameters
    ----------
    bucket: string
        Bucket name
    key : string
        Path in s3

    Returns
    -------
    np array
        Image array
    """
    s3 = boto3.resource('s3', region_name='ap-southeast-1')
    bucket = s3.Bucket(bucket)
    object = bucket.Object(key)
    response = object.get()
    file_stream = response['Body']
    im = Image.open(file_stream)
    return np.array(im)

def write_image_to_s3(img_array, bucket, key, region_name='ap-southeast-1'):
    """Write an image array into S3 bucket

    Parameters
    ----------
    bucket: string
        Bucket name
    key : string
        Path in s3

    Returns
    -------
    None
    """
    s3 = boto3.resource('s3', region_name)
    bucket = s3.Bucket(bucket)
    object = bucket.Object(key)
    file_stream = BytesIO()
    im = Image.fromarray(img_array)
    im.save(file_stream, format='jpeg')
    object.put(Body=file_stream.getvalue())
4
beahacker
object = bucket.Object('tiles/10/S/DG/2015/12/7/0/B01.jp2')
img_data = object.get().get('Body').read()
0
Evgeniy