You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask人脸检测应用:如何将检测到的人脸动态渲染到HTML?

Hey there! Let's work through how to get those detected faces showing up dynamically in your HTML page. Here's a step-by-step approach that fits your Flask + frontend setup perfectly:

1. Update Your Flask Route to Return Usable Face Data

Right now your route returns an empty string—we need to send back data the frontend can render. The easiest way is to convert detected faces to base64-encoded image strings (so they can be directly used as img sources) and wrap them in a JSON response.

First, add these imports to your Flask file:

import base64
from io import BytesIO
from flask import jsonify

Then modify your route function:

@app.route('/image.jpeg', methods=['POST'])
def on_image_captured():
    image_file = request.files['image']
    image = Image.open(image_file)
    image_np = np.array(image)
    image_np = image_np[..., :3]  # Strip alpha channel if present

    faces_data = []
    faces = system.detect_faces(image_np)
    
    for face in faces:
        # Handle two common detection output cases:
        # Case 1: `system.detect_faces` returns cropped face numpy arrays
        if isinstance(face, np.ndarray):
            face_img = Image.fromarray(face)
        # Case 2: `system.detect_faces` returns bounding boxes (x1, y1, x2, y2)
        else:
            x1, y1, x2, y2 = face
            # Crop the face from the original image
            face_crop = image_np[y1:y2, x1:x2]
            face_img = Image.fromarray(face_crop)
        
        # Convert face image to base64 string for frontend rendering
        buffer = BytesIO()
        face_img.save(buffer, format='JPEG')
        face_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
        faces_data.append(f"data:image/jpeg;base64,{face_base64}")
    
    # Send the list of face images as JSON
    return jsonify({'faces': faces_data})

2. Frontend: Capture Frames, Send to Server, Render Faces

Your frontend needs three core pieces: access the camera, send frames to Flask, and dynamically update the face display. Here's a complete HTML/JS implementation:

<!DOCTYPE html>
<html>
<head>
    <title>Face Detection Demo</title>
    <style>
        .camera-wrapper { margin: 2rem; }
        .faces-grid { 
            display: flex; 
            flex-wrap: wrap; 
            gap: 1rem; 
            margin: 2rem;
        }
        .face-thumbnail {
            width: 150px;
            height: auto;
            border: 2px solid #2196F3;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
    </style>
</head>
<body>
    <div class="camera-wrapper">
        <video id="cameraFeed" width="640" height="480" autoplay playsinline></video>
        <canvas id="frameCapture" style="display: none;"></canvas>
    </div>
    <div class="faces-grid" id="facesContainer"></div>

    <script>
        const video = document.getElementById('cameraFeed');
        const canvas = document.getElementById('frameCapture');
        const facesContainer = document.getElementById('facesContainer');
        const ctx = canvas.getContext('2d');

        // Initialize camera access
        async function startCamera() {
            try {
                const stream = await navigator.mediaDevices.getUserMedia({ video: true });
                video.srcObject = stream;
                video.addEventListener('loadedmetadata', startFrameLoop);
            } catch (err) {
                console.error('Failed to access camera:', err);
                alert('Could not access your camera. Please check permissions.');
            }
        }

        // Capture and send frames at a regular interval
        function startFrameLoop() {
            canvas.width = video.videoWidth;
            canvas.height = video.videoHeight;
            // Adjust interval to balance performance and speed (100ms = 10fps)
            setInterval(captureAndSendFrame, 100);
        }

        // Capture a frame, send to Flask backend
        async function captureAndSendFrame() {
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
            
            canvas.toBlob(async (blob) => {
                const formData = new FormData();
                formData.append('image', blob, 'camera-frame.jpg');

                try {
                    const response = await fetch('/image.jpeg', {
                        method: 'POST',
                        body: formData
                    });
                    const result = await response.json();
                    updateFaceDisplay(result.faces);
                } catch (err) {
                    console.error('Error sending frame to server:', err);
                }
            }, 'image/jpeg');
        }

        // Dynamically render detected faces
        function updateFaceDisplay(faces) {
            // Clear existing faces to avoid duplicates
            facesContainer.innerHTML = '';
            
            // Add each face as a thumbnail image
            faces.forEach(faceSrc => {
                const img = document.createElement('img');
                img.src = faceSrc;
                img.className = 'face-thumbnail';
                facesContainer.appendChild(img);
            });
        }

        // Start everything when the page loads
        window.addEventListener('load', startCamera);
    </script>
</body>
</html>

3. Quick Tips for Smooth Performance

  • Adjust frame rate: The setInterval time (100ms in the example) controls how often frames are sent. Lower values mean faster updates but more server load—tweak based on your hardware.
  • Optimize face detection: If your system.detect_faces is slow, consider resizing the input image before processing to reduce computation time.
  • Error handling: Add checks for empty face lists (so the frontend doesn't break if no faces are detected) and server timeouts.

内容的提问来源于stack exchange,提问作者Junhong Xu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:03:45