arcsu1 commited on
Commit
06e799e
·
1 Parent(s): 368841d
Files changed (6) hide show
  1. .dockerignore +20 -0
  2. Dockerfile +37 -0
  3. README.md +115 -10
  4. app.py +126 -0
  5. models/face-gen-gan/generator_model_100.h5 +3 -0
  6. requirements.txt +7 -0
.dockerignore ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ .Python
6
+ *.so
7
+ *.egg
8
+ *.egg-info
9
+ dist
10
+ build
11
+ .git
12
+ .gitignore
13
+ .vscode
14
+ .idea
15
+ *.swp
16
+ *.swo
17
+ *~
18
+ .DS_Store
19
+ README.md
20
+ .dockerignore
Dockerfile ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Install system dependencies
6
+ RUN apt-get update && apt-get install -y \
7
+ gcc \
8
+ g++ \
9
+ libhdf5-dev \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Upgrade pip first
13
+ RUN pip install --upgrade pip
14
+
15
+ # Copy requirements and install lightweight packages first
16
+ COPY requirements.txt .
17
+
18
+ # Install packages separately to handle large downloads better
19
+ RUN pip install --default-timeout=1000 --no-cache-dir fastapi[all] uvicorn[standard] pydantic
20
+
21
+ # Install TensorFlow CPU (smaller and faster to download than GPU version)
22
+ RUN pip install --default-timeout=1000 --no-cache-dir tensorflow-cpu==2.15.0
23
+
24
+ # Install remaining packages
25
+ RUN pip install --default-timeout=1000 --no-cache-dir keras==2.15.0 numpy==1.26.4 pillow
26
+
27
+ # Copy application code
28
+ COPY app.py .
29
+
30
+ # Copy model files
31
+ COPY models/ ./models/
32
+
33
+ # Expose port
34
+ EXPOSE 8002
35
+
36
+ # Run the application
37
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8002"]
README.md CHANGED
@@ -1,10 +1,115 @@
1
- ---
2
- title: Basic Face Generator
3
- emoji: 🐠
4
- colorFrom: purple
5
- colorTo: yellow
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Face Generator FastAPI
2
+
3
+ FastAPI service for the GAN-based face generation model.
4
+
5
+ ## Setup
6
+
7
+ ### Local Development
8
+
9
+ 1. Install dependencies:
10
+ ```bash
11
+ pip install -r requirements.txt
12
+ ```
13
+
14
+ 2. Run the app:
15
+ ```bash
16
+ python app.py
17
+ # or
18
+ uvicorn app:app --host 0.0.0.0 --port 8002 --reload
19
+ ```
20
+
21
+ 3. Access the API:
22
+ - API: http://localhost:8002
23
+ - Interactive docs: http://localhost:8002/docs
24
+ - ReDoc: http://localhost:8002/redoc
25
+
26
+ ### Docker
27
+
28
+ 1. Build the image:
29
+ ```bash
30
+ docker build -t facegen-api .
31
+ ```
32
+
33
+ 2. Run the container:
34
+ ```bash
35
+ docker run -p 8002:8002 facegen-api
36
+ ```
37
+
38
+ ## API Endpoints
39
+
40
+ ### GET `/`
41
+ Health check and info
42
+ ```bash
43
+ curl http://localhost:8002/
44
+ ```
45
+
46
+ ### GET `/health`
47
+ Detailed health status
48
+ ```bash
49
+ curl http://localhost:8002/health
50
+ ```
51
+
52
+ ### POST `/generate`
53
+ Generate face images (returns PNG image)
54
+
55
+ Request body:
56
+ ```json
57
+ {
58
+ "n_samples": 4,
59
+ "seed": 42
60
+ }
61
+ ```
62
+
63
+ Example:
64
+ ```bash
65
+ # Generate single face
66
+ curl -X POST http://localhost:8002/generate \
67
+ -H "Content-Type: application/json" \
68
+ -d '{"n_samples": 1, "seed": 42}' \
69
+ --output face.png
70
+
71
+ # Generate 4 faces in a grid
72
+ curl -X POST http://localhost:8002/generate \
73
+ -H "Content-Type: application/json" \
74
+ -d '{"n_samples": 4, "seed": 123}' \
75
+ --output faces_grid.png
76
+ ```
77
+
78
+ ### GET `/generate-single`
79
+ Quick endpoint to generate a single face
80
+
81
+ Example:
82
+ ```bash
83
+ # Random face
84
+ curl http://localhost:8002/generate-single --output face.png
85
+
86
+ # With seed
87
+ curl "http://localhost:8002/generate-single?seed=42" --output face.png
88
+ ```
89
+
90
+ ## Model
91
+
92
+ - **Model**: Face Generation GAN
93
+ - **Location**: `./models/face-gen-gan`
94
+ - **Type**: Generative Adversarial Network
95
+ - **Port**: 8002
96
+
97
+ ## Parameters
98
+
99
+ - **n_samples**: Number of faces to generate (1-16, default: 1)
100
+ - **seed**: Random seed for reproducibility (optional)
101
+
102
+ ## Response Format
103
+
104
+ - Returns PNG image
105
+ - Single face: Original resolution
106
+ - Multiple faces: Grid layout (auto-calculated)
107
+
108
+ ## Features
109
+
110
+ - CORS enabled for all origins
111
+ - Returns images as PNG
112
+ - Grid layout for multiple faces
113
+ - Reproducible generation with seeds
114
+ - FastAPI automatic documentation
115
+ - Health check endpoints
app.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.responses import StreamingResponse
4
+ from pydantic import BaseModel
5
+ import numpy as np
6
+ from keras.models import load_model
7
+ from PIL import Image
8
+ import io
9
+ from typing import Optional
10
+
11
+ app = FastAPI(title="Face Generator API", version="1.0.0")
12
+
13
+ # Add CORS middleware
14
+ app.add_middleware(
15
+ CORSMiddleware,
16
+ allow_origins=["*"],
17
+ allow_credentials=True,
18
+ allow_methods=["*"],
19
+ allow_headers=["*"],
20
+ )
21
+
22
+ # Global variables for model
23
+ MODEL_PATH = "./models/face-gen-gan"
24
+ model = None
25
+ latent_dim = None
26
+
27
+ # Request models
28
+ class FaceGenRequest(BaseModel):
29
+ n_samples: Optional[int] = 1
30
+ seed: Optional[int] = None
31
+
32
+ @app.on_event("startup")
33
+ async def load_gan_model():
34
+ """Load the GAN model on startup"""
35
+ global model, latent_dim
36
+ print(f"Loading face generation GAN model from {MODEL_PATH}...")
37
+
38
+ model = load_model(MODEL_PATH)
39
+ latent_dim = model.input_shape[1]
40
+
41
+ print(f"Model loaded successfully! Latent dimension: {latent_dim}")
42
+
43
+ @app.get("/")
44
+ def root():
45
+ return {
46
+ "message": "Face Generator API",
47
+ "status": "running",
48
+ "model": "face-gen-gan",
49
+ "latent_dim": latent_dim
50
+ }
51
+
52
+ @app.get("/health")
53
+ def health():
54
+ return {
55
+ "status": "healthy",
56
+ "model_loaded": model is not None,
57
+ "latent_dim": latent_dim
58
+ }
59
+
60
+ @app.post("/generate")
61
+ async def generate_faces(request: FaceGenRequest):
62
+ """
63
+ Generate face images using the GAN model
64
+ Returns a PNG image (single face or grid of faces)
65
+ """
66
+ if model is None:
67
+ return {"error": "Model not loaded"}
68
+
69
+ try:
70
+ # Validate n_samples
71
+ n_samples = max(1, min(request.n_samples, 16)) # Limit to 1-16
72
+
73
+ # Set seed if provided
74
+ if request.seed is not None:
75
+ np.random.seed(request.seed)
76
+
77
+ # Generate random latent points
78
+ latent_points = np.random.randn(n_samples, latent_dim)
79
+
80
+ # Generate images
81
+ generated_images = model.predict(latent_points, verbose=0)
82
+
83
+ # Scale from [-1, 1] to [0, 255]
84
+ generated_images = ((generated_images + 1) / 2.0 * 255).astype(np.uint8)
85
+
86
+ if n_samples == 1:
87
+ # Single image
88
+ img = Image.fromarray(generated_images[0])
89
+ else:
90
+ # Create a grid
91
+ grid_size = int(np.ceil(np.sqrt(n_samples)))
92
+ img_height, img_width = generated_images.shape[1:3]
93
+
94
+ # Create blank canvas
95
+ grid_img = np.ones((grid_size * img_height, grid_size * img_width, 3), dtype=np.uint8) * 255
96
+
97
+ # Fill grid with generated images
98
+ for i in range(n_samples):
99
+ row = i // grid_size
100
+ col = i % grid_size
101
+ grid_img[row*img_height:(row+1)*img_height,
102
+ col*img_width:(col+1)*img_width] = generated_images[i]
103
+
104
+ img = Image.fromarray(grid_img)
105
+
106
+ # Convert to bytes
107
+ buf = io.BytesIO()
108
+ img.save(buf, format='PNG')
109
+ buf.seek(0)
110
+
111
+ return StreamingResponse(buf, media_type="image/png")
112
+
113
+ except Exception as e:
114
+ return {"error": str(e)}
115
+
116
+ @app.get("/generate-single")
117
+ async def generate_single_face(seed: Optional[int] = None):
118
+ """
119
+ Quick endpoint to generate a single face
120
+ """
121
+ request = FaceGenRequest(n_samples=1, seed=seed)
122
+ return await generate_faces(request)
123
+
124
+ if __name__ == "__main__":
125
+ import uvicorn
126
+ uvicorn.run(app, host="0.0.0.0", port=8002)
models/face-gen-gan/generator_model_100.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd167921ef33931acace69054326314197b8bc340bd702503f167710f21f7235
3
+ size 5563784
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi[all]
2
+ uvicorn[standard]
3
+ tensorflow-cpu==2.15.0
4
+ keras==2.15.0
5
+ numpy==1.26.4
6
+ pillow
7
+ pydantic