Update app.py
Browse files
app.py
CHANGED
|
@@ -16,6 +16,19 @@ from kiui.op import recenter
|
|
| 16 |
import kiui
|
| 17 |
from gradio_litmodel3d import LitModel3D
|
| 18 |
import shutil
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
|
| 21 |
ACCESS = os.getenv("ACCESS")
|
|
@@ -246,67 +259,34 @@ def step_2_generate_video(image):
|
|
| 246 |
def step_3_display_3d_model(mesh_file):
|
| 247 |
return mesh_file
|
| 248 |
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
with gr.Row():
|
| 255 |
-
|
| 256 |
-
with gr.Column():
|
| 257 |
-
gr.Markdown("""
|
| 258 |
-
# Welcome to [VFusion3D](https://junlinhan.github.io/projects/vfusion3d.html) Demo
|
| 259 |
-
|
| 260 |
-
This demo allows you to upload an image and generate a 3D model or rendered videos from it.
|
| 261 |
-
|
| 262 |
-
## How to Use:
|
| 263 |
-
1. Click on "Click to Upload" to upload an image, or choose one example image.
|
| 264 |
-
|
| 265 |
-
2: Choose between "Generate and Download Mesh" or "Generate and Download Video", then click it.
|
| 266 |
-
|
| 267 |
-
3. Wait for the model to process; meshes should take approximately 10 seconds, and videos will take approximately 30 seconds.
|
| 268 |
-
|
| 269 |
-
4. Download the generated mesh or video.
|
| 270 |
-
|
| 271 |
-
This demo does not aim to provide optimal results but rather to provide a quick look. See our [GitHub](https://github.com/facebookresearch/vfusion3d) for more.
|
| 272 |
-
|
| 273 |
-
""")
|
| 274 |
-
img_input = gr.Image(type="pil", label="Input Image")
|
| 275 |
-
examples_component = gr.Examples(examples=examples, inputs=img_input, outputs=None, examples_per_page=3)
|
| 276 |
-
generate_mesh_button = gr.Button("Generate and Download Mesh")
|
| 277 |
-
generate_video_button = gr.Button("Generate and Download Video")
|
| 278 |
-
obj_file_output = gr.File(label="Download .obj File")
|
| 279 |
-
video_file_output = gr.File(label="Download Video")
|
| 280 |
-
|
| 281 |
-
with gr.Column():
|
| 282 |
-
model_output = LitModel3D(
|
| 283 |
-
clear_color=[0.1, 0.1, 0.1, 0], # can adjust background color for better contrast
|
| 284 |
-
label="3D Model Visualization",
|
| 285 |
-
scale=1.0,
|
| 286 |
-
tonemapping="aces", # can use aces tonemapping for more realistic lighting
|
| 287 |
-
exposure=1.0, # can adjust exposure to control brightness
|
| 288 |
-
contrast=1.1, # can slightly increase contrast for better depth
|
| 289 |
-
camera_position=(0, 0, 2), # will set initial camera position to center the model
|
| 290 |
-
zoom_speed=0.5, # will adjust zoom speed for better control
|
| 291 |
-
pan_speed=0.5, # will adjust pan speed for better control
|
| 292 |
-
interactive=True # this allow users to interact with the model
|
| 293 |
-
)
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
# clear outputs
|
| 297 |
-
def clear_model_viewer():
|
| 298 |
-
"""Reset the Model3D component before loading a new model."""
|
| 299 |
-
return gr.update(value=None)
|
| 300 |
|
| 301 |
-
def generate_and_visualize(image):
|
| 302 |
-
mesh_path = step_1_generate_obj(image)
|
| 303 |
-
return mesh_path, mesh_path
|
| 304 |
|
| 305 |
-
|
| 306 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
generate_video_button.click(step_2_generate_video, inputs=img_input, outputs=video_file_output)
|
| 311 |
|
| 312 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
import kiui
|
| 17 |
from gradio_litmodel3d import LitModel3D
|
| 18 |
import shutil
|
| 19 |
+
from fastapi import FastAPI, File, UploadFile, Form
|
| 20 |
+
from fastapi.responses import StreamingResponse
|
| 21 |
+
from pydantic import BaseModel
|
| 22 |
+
from pydantic import Field
|
| 23 |
+
from typing import Optional
|
| 24 |
+
import logging
|
| 25 |
+
import os
|
| 26 |
+
import boto3
|
| 27 |
+
import uuid
|
| 28 |
+
|
| 29 |
+
import datetime
|
| 30 |
+
|
| 31 |
+
app = FastAPI()
|
| 32 |
|
| 33 |
|
| 34 |
ACCESS = os.getenv("ACCESS")
|
|
|
|
| 259 |
def step_3_display_3d_model(mesh_file):
|
| 260 |
return mesh_file
|
| 261 |
|
| 262 |
+
def upload_file_to_s3(file_path, bucket_name, object_name):
|
| 263 |
+
try:
|
| 264 |
+
s3_client.upload_file(file_path, bucket_name, object_name)
|
| 265 |
+
except Exception as e:
|
| 266 |
+
raise HTTPException(status_code=500, detail=f"Failed to upload file to S3: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 267 |
|
|
|
|
|
|
|
|
|
|
| 268 |
|
| 269 |
+
@app.post("/upload/")
|
| 270 |
+
async def upload_image(file: UploadFile = File(...)):
|
| 271 |
+
try:
|
| 272 |
+
# Convert uploaded file to PIL Image
|
| 273 |
+
image = Image.open(io.BytesIO(await file.read()))
|
| 274 |
+
|
| 275 |
+
# Generate OBJ file
|
| 276 |
+
obj_file_path = step_1_generate_obj(image)
|
| 277 |
+
|
| 278 |
+
# Generate a unique name for the S3 object
|
| 279 |
+
obj_name = f"{uuid.uuid4()}.obj"
|
| 280 |
+
|
| 281 |
+
# Upload the OBJ file to S3
|
| 282 |
+
s3_url = save_file_to_s3(obj_file_path, bucket_name, obj_name)
|
| 283 |
+
|
| 284 |
+
return JSONResponse(content={"Output": s3_url})
|
| 285 |
|
| 286 |
+
except Exception as e:
|
| 287 |
+
raise HTTPException(status_code=500, detail=f"Error processing the image: {str(e)}")
|
|
|
|
| 288 |
|
| 289 |
+
# Run FastAPI
|
| 290 |
+
if __name__ == "__main__":
|
| 291 |
+
import uvicorn
|
| 292 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|