# Run OpenCV face detection on an image | Modal Docs

- **URL:** https://modal.com/docs/examples/count_faces
- **Summary:** This example shows how you can use OpenCV on Modal to detect faces in an image. We use the opencv-python package to load the image and the opencv library to detect faces. The function count_faces takes an image as input and returns the number of faces detected in the image.

[View on GitHub](https://github.com/modal-labs/modal-examples/blob/main/07_web/count_faces.py)

Copy page

Run OpenCV face detection on an image
=====================================

This example shows how you can use OpenCV on Modal to detect faces in an image. We use the `opencv-python` package to load the image and the `opencv` library to detect faces. The function `count_faces` takes an image as input and returns the number of faces detected in the image.

The code below also shows how you can create wrap this function in a simple FastAPI server to create a web interface.

    import os
    
    import modal
    
    app = modal.App("example-count-faces")
    
    
    open_cv_image = (
        modal.Image.debian_slim(python_version="3.11")
        .apt_install("python3-opencv")
        .uv_pip_install(
            "fastapi[standard]==0.115.4",
            "opencv-python~=4.10.0",
            "numpy<2",
        )
    )
    
    
    @app.function(image=open_cv_image)
    def count_faces(image_bytes: bytes) -> int:
        import cv2
        import numpy as np
    
        # Example borrowed from https://towardsdatascience.com/face-detection-in-2-minutes-using-opencv-python-90f89d7c0f81
        # Load the cascade
        face_cascade = cv2.CascadeClassifier(
            os.path.join(cv2.data.haarcascades, "haarcascade_frontalface_default.xml")
        )
        # Read the input image
        np_bytes = np.frombuffer(image_bytes, dtype=np.uint8)
        img = cv2.imdecode(np_bytes, cv2.IMREAD_COLOR)
        # Convert into grayscale
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # Detect faces
        faces = face_cascade.detectMultiScale(gray, 1.1, 4)
        return len(faces)
    
    
    @app.function(
        image=modal.Image.debian_slim(python_version="3.11").uv_pip_install("inflect")
    )
    @modal.asgi_app()
    def web():
        import inflect
        from fastapi import FastAPI, File, HTTPException, UploadFile
        from fastapi.responses import HTMLResponse
    
        app = FastAPI()
    
        @app.get("/", response_class=HTMLResponse)
        async def index():
            """
            Render an HTML form for file upload.
            """
            return """
            <html>
                <head>
                    <title>Face Counter</title>
                </head>
                <body>
                    <h1>Upload an Image to Count Faces</h1>
                    <form action="/process" method="post" enctype="multipart/form-data">
                        <input type="file" name="file" id="file" accept="image/*" required />
                        <button type="submit">Upload</button>
                    </form>
                </body>
            </html>
            """
    
        @app.post("/process", response_class=HTMLResponse)
        async def process(file: UploadFile = File(...)):
            """
            Process the uploaded image and return the number of faces detected.
            """
            try:
                file_content = await file.read()
                num_faces = await count_faces.remote.aio(file_content)
                return f"""
                <html>
                    <head>
                        <title>Face Counter Result</title>
                    </head>
                    <body>
                        <h1>{inflect.engine().number_to_words(num_faces).title()} {"Face" if num_faces == 1 else "Faces"} Detected</h1>
                        <h2>{"😀" * num_faces}</h2>
                        <a href="/">Go back</a>
                    </body>
                </html>
                """
            except Exception as e:
                raise HTTPException(
                    status_code=400, detail=f"Error processing image: {str(e)}"
                )
    
        return app

[Run OpenCV face detection on an image](https://modal.com/docs/examples/count_faces#run-opencv-face-detection-on-an-image)
> Common reference appendix (shared error/status catalog): see [../_shared-appendix.md](../_shared-appendix.md).
    modal serve 07_web/count_faces.py
