基于AWS Rekognition人脸边界框裁剪图片并检索人脸集的技术问询
刚好我之前在Lambda里实现过一模一样的流程,给你整理了Python和Node.js两种版本的代码,直接就能用,还附带了关键步骤的说明:
Python 实现方案
前置准备
Lambda默认环境没有图片处理库,所以需要把Pillow打包成Lambda层(或者本地打包后和代码一起上传)。如果用层的话,在本地执行pip install pillow -t python/lib/python3.x/site-packages(替换成你Lambda用的Python版本),然后压缩成zip上传为Lambda层即可。
完整代码示例
import boto3 from PIL import Image import io # 初始化客户端 rekognition = boto3.client('rekognition') s3 = boto3.client('s3') def lambda_handler(event, context): # 假设输入是S3的桶名和文件名,你也可以改成处理base64图片的逻辑 bucket = event['bucket'] image_key = event['image_key'] collection_id = '你的人脸集合ID' # 第一步:调用DetectFaces获取人脸边界框 detect_response = rekognition.detect_faces( Image={'S3Object': {'Bucket': bucket, 'Name': image_key}}, Attributes=['DEFAULT'] ) if not detect_response['FaceDetails']: return {'message': '未检测到人脸'} # 获取第一张人脸的边界框(如果有多张可以循环处理) face_box = detect_response['FaceDetails'][0]['BoundingBox'] # 第二步:下载原始图片并裁剪 # 从S3下载图片到内存 s3_response = s3.get_object(Bucket=bucket, Key=image_key) image_bytes = s3_response['Body'].read() img = Image.open(io.BytesIO(image_bytes)) img_width, img_height = img.size # 把相对比例的边界框转成像素坐标 left = int(face_box['Left'] * img_width) top = int(face_box['Top'] * img_height) width = int(face_box['Width'] * img_width) height = int(face_box['Height'] * img_height) # 裁剪人脸区域 cropped_img = img.crop((left, top, left + width, top + height)) # 把裁剪后的图片转成字节流 buffer = io.BytesIO() cropped_img.save(buffer, format='JPEG') cropped_bytes = buffer.getvalue() # 第三步:调用SearchFacesByImage检索人脸集合 search_response = rekognition.search_faces_by_image( CollectionId=collection_id, Image={'Bytes': cropped_bytes}, MaxFaces=5, FaceMatchThreshold=80.0 ) return { 'face_matches': search_response['FaceMatches'], 'original_face_count': len(detect_response['FaceDetails']) }
关键注意点
- 边界框转换:
DetectFaces返回的是相对比例值,必须乘以图片实际宽高才能得到像素坐标,不然裁剪出来的区域会完全不对 - 权限配置:Lambda角色需要添加
RekognitionDetectFaces、RekognitionSearchFacesByImage权限,如果图片存在S3,还要加上s3:GetObject权限 - 内存/超时:建议给Lambda分配至少256MB内存,超时设置为10-15秒,避免处理大图片时超时
Node.js 实现方案
前置准备
我们用sharp来处理图片(比jimp更高效,适合Lambda环境),需要把依赖打包。本地执行npm install sharp,然后把node_modules和代码一起压缩上传,或者做成Lambda层。
完整代码示例
const AWS = require('aws-sdk'); const sharp = require('sharp'); // 初始化客户端 const rekognition = new AWS.Rekognition(); const s3 = new AWS.S3(); exports.handler = async (event) => { // 同样假设输入是S3桶名和文件名,可自行修改为base64处理逻辑 const { bucket, image_key, collection_id = '你的人脸集合ID' } = event; try { // 第一步:调用DetectFaces获取人脸边界框 const detectParams = { Image: { S3Object: { Bucket: bucket, Name: image_key } }, Attributes: ['DEFAULT'] }; const detectResponse = await rekognition.detectFaces(detectParams).promise(); if (!detectResponse.FaceDetails || detectResponse.FaceDetails.length === 0) { return { message: '未检测到人脸' }; } // 获取第一张人脸的边界框 const faceBox = detectResponse.FaceDetails[0].BoundingBox; // 第二步:下载图片并裁剪 const s3Response = await s3.getObject({ Bucket: bucket, Key: image_key }).promise(); const imageBuffer = s3Response.Body; // 获取图片实际尺寸 const metadata = await sharp(imageBuffer).metadata(); const imgWidth = metadata.width; const imgHeight = metadata.height; // 转换边界框为像素坐标 const left = Math.floor(faceBox.Left * imgWidth); const top = Math.floor(faceBox.Top * imgHeight); const width = Math.floor(faceBox.Width * imgWidth); const height = Math.floor(faceBox.Height * imgHeight); // 裁剪人脸区域 const croppedBuffer = await sharp(imageBuffer) .extract({ left, top, width, height }) .jpeg() .toBuffer(); // 第三步:调用SearchFacesByImage检索集合 const searchParams = { CollectionId: collection_id, Image: { Bytes: croppedBuffer }, MaxFaces: 5, FaceMatchThreshold: 80.0 }; const searchResponse = await rekognition.searchFacesByImage(searchParams).promise(); return { face_matches: searchResponse.FaceMatches, original_face_count: detectResponse.FaceDetails.length }; } catch (error) { console.error('处理出错:', error); return { error: error.message }; } };
关键注意点
sharp的extract方法接受的是像素坐标,所以必须做好比例转换- Lambda环境需要Node.js 16+版本来兼容最新的
sharp版本 - 同样要确保Lambda角色拥有对应的Rekognition和S3权限
内容的提问来源于stack exchange,提问作者db46
相关产品推荐
相关产品推荐

