Przejdź do treści

Amazon Rekognition – wykrywanie obiektów i twarzy za pomocą AWS Lambda

blog wojciech lepczynski -amazon rekognition & lambda 2024

Amazon Rekognition to potężne narzędzie dostępne w chmurze AWS, zaprojektowane do analizy obrazów i filmów. Dzięki tej usłudze możesz wykrywać obiekty, twarze, emocje i wiele więcej. W tym artykule przedstawię podstawy Amazon Rekognition i pokażę, jak można go używać w połączeniu z AWS Lambda, aby tworzyć zautomatyzowane przepływy pracy do analizy obrazów. W tym artykule zamieszczę również link do mojego filmu, w którym pokazuję rzeczywiste przykłady działania tych funkcji.

Czym jest Amazon Rekognition?

Amazon Rekognition to usługa uczenia maszynowego świadczona przez AWS, która automatycznie analizuje treści wizualne, takie jak obrazy i filmy. Oferuje szereg funkcji, w tym wykrywanie obiektów, rozpoznawanie twarzy, rozpoznawanie tekstu i analizę scen. Rekognition jest używany w wielu branżach, takich jak bezpieczeństwo, marketing i analiza danych wizualnych na dużą skalę, dzięki swojej zdolności do przetwarzania i analizowania obrazów na dużą skalę.

Jedną z kluczowych zalet Rekognition jest bezproblemowa integracja z AWS Lambda, umożliwiająca automatyczne przetwarzanie obrazu natychmiast po przesłaniu pliku do Amazon S3. Ta integracja umożliwia w pełni zautomatyzowane przepływy pracy, pomagając firmom oszczędzać czas i zasoby dzięki automatycznemu tagowaniu, identyfikacji i analizie obrazu.

Przykład 1: Używanie funkcji Lambda do analizy obrazu i zwracania wykrytych obiektów

Using Lambda to Analyze an Image and Return Detected Objects

Prostym, ale bardzo skutecznym przypadkiem użycia jest skonfigurowanie funkcji AWS Lambda, która automatycznie analizuje obraz za pomocą Amazon Rekognition i zwraca szczegółowe informacje o wykrytych obiektach. Gdy obraz jest przesyłany do określonego bucketa S3, uruchamiana jest funkcja Lambda, która wywołuje Rekognition w celu analizy obrazu i zwraca listę obiektów wraz z ich poziomami rozpoznania. Ten rodzaj automatyzacji jest niezwykle przydatny w przypadku zadań takich jak moderowanie treści, katalogowanie obrazów i zarządzanie zapisanymi obrazami.

Poniżej znajduje się przykład kodu, którego użyłem w filmie. Zmieniając bucket i image_name , możesz łatwo dostosować go do swoich potrzeb i przetestować.

import json
import boto3

def lambda_handler(event, context):
    client = boto3.client('rekognition')


    bucket = 'rekognition-bucket-00235'
    image_name = 'dog-8448345_1280.jpg'


    response = client.detect_labels(
        Image={
            'S3Object': {
                'Bucket': bucket,
                'Name': image_name,
            }
        },
        MaxLabels=10,
        MinConfidence=80
    )

    labels = response['Labels']
    result = []
    for label in labels:
        result.append({
            'Name': label['Name'],
            'Confidence': label['Confidence']
        })

    return {
        'statusCode': 200,
        'body': result
    }

Przykład 2: Generowanie nowego obrazu z wykrytymi obiektami

Generating a New Image with Labeled Objects

Oprócz analizowania i zwracania danych obiektów, AWS Lambda może również służyć do tworzenia nowego obrazu z wykrytymi, zaznaczonymi i podpisanymi obiektami. Funkcja Lambda może pobrać obraz, przeanalizować go za pomocą Rekognition, a następnie wygenerować nową wersję obrazu z zaznaczonymi obektami i ich nazwami. Może to być przydatne do tworzenia raportów, wizualizacji wyników analizy lub wyróżniania określonych szczegółów na obrazach, na przykład w aplikacjach bezpieczeństwa lub marketingu.

import json
import boto3
from PIL import Image, ImageDraw, ImageFont
import random
import os

# Initialize S3 and Rekognition clients
s3_client = boto3.client('s3')
rekognition_client = boto3.client('rekognition')

def lambda_handler(event, context):
    # S3 parameters: bucket name and image key from the event input
    bucket_name = 'rekognition-bucket-00235' 
    image_key = 'fashion-2208045_1280.jpg'  
    
    # Download the image from S3 to the temporary directory in Lambda
    s3_client.download_file(bucket_name, image_key, '/tmp/image.png')
    
    # Open the downloaded image using PIL
    image = Image.open('/tmp/image.png')
    draw = ImageDraw.Draw(image)
    
    # Use Amazon Rekognition to detect labels in the image
    response = rekognition_client.detect_labels(
        Image={'S3Object': {'Bucket': bucket_name, 'Name': image_key}},
        MaxLabels=10  # Limit to 10 labels
    )
    
    # Set the font for the text to be drawn on the image
    try:
        # Use a larger font size for better visibility
        font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 50)
    except IOError:
        # Fallback to default font if the TTF font is not available
        font = ImageFont.load_default()
    
    # Iterate through detected labels and draw them on the image
    for label in response['Labels']:
        # Get bounding box coordinates
        for instance in label['Instances']:
            box = instance['BoundingBox']
            width, height = image.size
            
            # Calculate the actual bounding box coordinates
            left = box['Left'] * width
            top = box['Top'] * height
            right = left + (box['Width'] * width)
            bottom = top + (box['Height'] * height)
            
            # Generate a random color for the rectangle
            color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
            
            # Draw the rectangle around the detected object
            draw.rectangle([left, top, right, bottom], outline=color, width=4)
            
            # Create the label text with the name and confidence
            text = f"{label['Name']} - {label['Confidence']:.2f}%"
            
            # Create a background rectangle for better text visibility
            # Using textbbox to get the bounding box of the text
            text_bbox = draw.textbbox((left, top), text, font=font)
            background_box = [text_bbox[0] - 5, text_bbox[1] - 5, text_bbox[2] + 5, text_bbox[3] + 5]
            draw.rectangle(background_box, fill=(255, 255, 255, 128))  # White background with transparency
            
            # Draw the text at the top-left corner of the bounding box
            draw.text((left, top), text, fill=color, font=font)
    
    # Create the new file name with a prefix
    original_filename = os.path.splitext(image_key)[0]
    new_image_key = f"{original_filename}_labelled.jpg"
    
    # Save the updated image as JPEG with quality setting for better output
    image.save('/tmp/labelled_image.jpg', 'JPEG', quality=95)
    
    # Upload the labelled image back to the S3 bucket with the new name
    s3_client.upload_file('/tmp/labelled_image.jpg', bucket_name, new_image_key)
    
    # Return a success response with a link to the new image
    image_url = f"https://{bucket_name}.s3.amazonaws.com/{new_image_key}"
    
    return {
        'statusCode': 200,
        'body': json.dumps({'message': 'Image processed successfully!', 'image_url': image_url})
    }

Przykład 3: Analizowanie wszystkich obrazów twarzy w folderze

Batch Processing and Analyzing Images in a Folder

Inną potężną aplikacją jest możliwość przetwarzania wielu obrazów przechowywanych w określonym folderze S3. AWS Lambda można skonfigurować tak, aby skanowała wszystkie obrazy w folderze i analizowała każdy z nich, automatycznie generując raporty dotyczące wykrytych obiektów lub innych cech, takich jak identyfikacja, czy osoby na obrazach noszą okulary. Ta możliwość przetwarzania zbiorczego jest idealna w przypadkach, w których duża liczba obrazów musi zostać przetworzona jednocześnie, na przykład podczas analizy nagrań z kamer bezpieczeństwa lub organizowania bazy danych obrazów klientów.

import json
import boto3
from PIL import Image, ImageDraw, ImageFont
import os

# Initialize S3 and Rekognition clients
s3_client = boto3.client('s3')
rekognition_client = boto3.client('rekognition')

def lambda_handler(event, context):
    # S3 parameters: bucket name and folder prefix(directory)
    bucket_name = 'rekognition-bucket-00235'
    folder_prefix = 'faces'
    
    # List all objects in the specified folder (prefix)
    objects = s3_client.list_objects_v2(Bucket=bucket_name, Prefix=folder_prefix)
    
    # Check if the folder contains any objects
    if 'Contents' not in objects:
        return {
            'statusCode': 400,
            'body': json.dumps({'message': f'No images found in {folder_prefix}'}, indent=4)
        }
    
    processed_images = []
    
    # Iterate through all the objects (images) in the folder
    for obj in objects['Contents']:
        image_key = obj['Key']
        
        # Skip non-image files (you can add more file type filters as needed)
        if not image_key.lower().endswith(('.jpg', '.jpeg', '.png')):
            continue
        
        # Download the image from S3 to the temporary directory in Lambda
        s3_client.download_file(bucket_name, image_key, '/tmp/image.jpg')
        
        # Open the downloaded image using PIL
        image = Image.open('/tmp/image.jpg')
        draw = ImageDraw.Draw(image)
        
        # Use Amazon Rekognition to detect faces and check for glasses
        response = rekognition_client.detect_faces(
            Image={'S3Object': {'Bucket': bucket_name, 'Name': image_key}},
            Attributes=['ALL']
        )
        
        # Set the font for the text to be drawn on the image
        try:
            font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 40)
        except IOError:
            font = ImageFont.load_default()
        
        # Loop through detected faces and check for glasses
        for face_detail in response['FaceDetails']:
            # Get bounding box for each face
            box = face_detail['BoundingBox']
            width, height = image.size
            left = box['Left'] * width
            top = box['Top'] * height
            right = left + (box['Width'] * width)
            bottom = top + (box['Height'] * height)
            
            # Check if the person is wearing glasses
            if face_detail['Eyeglasses']['Value']:
                text = 'Glasses Detected'
                text_color = (0, 255, 0)  # Green for glasses
            else:
                text = 'No Glasses'
                text_color = (255, 0, 0)  # Red for no glasses
            
            # Draw a rectangle around the face
            draw.rectangle([left, top, right, bottom], outline=text_color, width=3)
            
            # Draw the text on the image
            text_bbox = draw.textbbox((left, bottom + 10), text, font=font)
            background_box = [text_bbox[0] - 5, text_bbox[1] - 5, text_bbox[2] + 5, text_bbox[3] + 5]
            draw.rectangle(background_box, fill=(255, 255, 255, 128))  # Background for better readability
            draw.text((left, bottom + 10), text, fill=text_color, font=font)
        
        # Create the new file name with a prefix indicating glasses detection
        if 'Glasses Detected' in text:
            new_image_key = f"glasses_{image_key}"
        else:
            new_image_key = f"no_glasses_{image_key}"
        
        # Save the modified image as a JPEG
        image.save('/tmp/labelled_image.jpg', 'JPEG', quality=95)
        
        # Upload the labelled image back to the S3 bucket with the new name
        s3_client.upload_file('/tmp/labelled_image.jpg', bucket_name, new_image_key)
        
        # Add the processed image to the list
        processed_images.append(new_image_key)
    
    # Return a success response with pretty JSON formatting
    return {
        'statusCode': 200,
        'body': {'processed_images': processed_images}
    }

Uprawnienia dla IAM Role

Aby wdrożyć te przykłady, Twoja funkcja Lambda będzie wymagać określonych uprawnień roli IAM. Funkcja będzie wymagać dostępu zarówno do Amazon S3, jak i Amazon Rekognition. Konkretnie, dla roli IAM powinny zostać przyznane uprawnienia do odczytu obiektów z kontenera S3 i wykonywania operacji analizy obrazu Rekognition. Prawidłowa konfiguracja tych uprawnień jest kluczowa dla zapewnienia prawidłowego działania​​funkcja Lambda.

To od Ciebie zależy, jakie uprawnienia przyznasz i co chcesz zrobić ze swoją funkcją lambda. Ja zalecam zawsze przyznawanie tylko niezbędnych uprawnień.

Wymagania dotyczące Lambda Layer dla przetwarzania obrazów

Domyślnie AWS Lambda nie obejmuje niezbędnych bibliotek do przetwarzania obrazu, takich jak Pillow (PIL) lub fonty do renderowania tekstu. Aby włączyć te możliwości, musisz dodać niestandardową warstwę Lambda, która obejmuje te zależności. Bez tej dodatkowej warstwy funkcja nie będzie w stanie manipulować obrazami ani prawidłowo rysować tekstu.

Podsumowanie

Amazon Rekognition to potężne narzędzie, które w połączeniu z innymi usługami AWS oferuje niesamowite możliwości wizualnej analizy danych. Zdecydowanie warto zbadać, w jaki sposób ta usługa może usprawnić różne procesy w Twojej firmie lub projektach. W moim kolejnym filmie pokażę Ci, jak używać funkcji OCR do odczytywania tekstu z obrazów – bądź na bieżąco, aby dowiedzieć się więcej!

How to Become a DevOps Engineer – A Roadmap for Beginners
Combining alarms in the AWS cloud – Composite Alarm

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *