Spaces:
Running
on
Zero
Running
on
Zero
UI, 3D major updates
Browse files- README.md +19 -14
- app.py +290 -254
- style_20250314.css +21 -1
- trellis/pipelines/trellis_image_to_3d.py +12 -6
- utils/depth_estimation.py +1 -1
- utils/image_utils.py +19 -6
README.md
CHANGED
@@ -5,7 +5,7 @@ colorFrom: yellow
|
|
5 |
colorTo: purple
|
6 |
sdk: gradio
|
7 |
python_version: 3.10.13
|
8 |
-
sdk_version: 5.
|
9 |
app_file: app.py
|
10 |
pinned: true
|
11 |
short_description: Transform Your Images into Mesmerizing Hexagon Grids
|
@@ -36,15 +36,19 @@ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-
|
|
36 |
## Description
|
37 |
Welcome to HexaGrid Creator, the ultimate tool for transforming your images into mesmerizing hexagon grid masterpieces! Whether you're a tabletop game enthusiast, a digital artist, or just someone who loves unique patterns, HexaGrid Creator has something for you.
|
38 |
|
|
|
|
|
39 |
### What Can You Do?
|
40 |
-
- **Generate Hexagon Grids:** Create stunning hexagon
|
41 |
-
- **AI-Powered Image Generation:** Use AI to generate images
|
42 |
-
- **Color Exclusion:** Pick and exclude specific colors from your hexagon grid for
|
43 |
-
- **Interactive Customization:** Adjust
|
44 |
-
- **Depth
|
45 |
-
- **Image Filter [
|
46 |
-
- **Pre-rendered Maps:** Access a library of
|
47 |
-
- **Add Margins:** Add customizable margins around your images for a polished
|
|
|
|
|
48 |
|
49 |
### Why You'll Love It
|
50 |
- **Fun and Easy to Use:** With an intuitive interface and real-time previews, creating hexagon grids has never been this fun!
|
@@ -58,11 +62,12 @@ Welcome to HexaGrid Creator, the ultimate tool for transforming your images into
|
|
58 |
3. **Download and Share:** Once you're happy with your creation, download it and share it with the world!
|
59 |
|
60 |
### Advanced Features
|
61 |
-
- **Generative AI Integration:**
|
62 |
-
- **Pre-rendered Maps
|
63 |
-
- **Image Filter
|
64 |
-
- **TRELLIS Depth
|
65 |
-
- **Add Margins:**
|
|
|
66 |
|
67 |
Join the hive and start creating with HexaGrid Creator today!
|
68 |
|
|
|
5 |
colorTo: purple
|
6 |
sdk: gradio
|
7 |
python_version: 3.10.13
|
8 |
+
sdk_version: 5.23.1
|
9 |
app_file: app.py
|
10 |
pinned: true
|
11 |
short_description: Transform Your Images into Mesmerizing Hexagon Grids
|
|
|
36 |
## Description
|
37 |
Welcome to HexaGrid Creator, the ultimate tool for transforming your images into mesmerizing hexagon grid masterpieces! Whether you're a tabletop game enthusiast, a digital artist, or just someone who loves unique patterns, HexaGrid Creator has something for you.
|
38 |
|
39 |
+
### <span style='color: red; font-weight: bolder;'>ZeroGPU sometimes crashes or is not available.<br/Try Again in 10 seconds</span>
|
40 |
+
|
41 |
### What Can You Do?
|
42 |
+
- **Generate Hexagon Grids:** Create stunning hexagon, square, or triangle grid overlays with fully customizable parameters.
|
43 |
+
- **AI-Powered Image Generation:** Use advanced AI models and LoRA weights to generate images from your prompts and apply unique grid overlays.
|
44 |
+
- **Color Exclusion:** Pick and exclude specific colors from your hexagon grid for improved clarity.
|
45 |
+
- **Interactive Customization:** Adjust grid size, border size, rotation, background color, and more—all in real-time.
|
46 |
+
- **Depth & 3D Model Generation:** Generate depth maps and interactive 3D models (with GLB and Gaussian extraction) for enhanced visualization.
|
47 |
+
- **Image Filter [LUT] Application:** Apply advanced color grading filters with live previews using LUT files.
|
48 |
+
- **Pre-rendered Maps:** Access a library of ready-to-use hexagon maps for quick customization.
|
49 |
+
- **Add Margins:** Add customizable margins around your images for a polished print-ready look.
|
50 |
+
- **Sketch Pad Integration:** Directly sketch on images to modify or replace them before further processing.
|
51 |
+
|
52 |
|
53 |
### Why You'll Love It
|
54 |
- **Fun and Easy to Use:** With an intuitive interface and real-time previews, creating hexagon grids has never been this fun!
|
|
|
62 |
3. **Download and Share:** Once you're happy with your creation, download it and share it with the world!
|
63 |
|
64 |
### Advanced Features
|
65 |
+
- **Generative AI Integration:** Leverage models like `black-forest-labs/FLUX.1-dev` along with various LoRA weights for unique image generation.
|
66 |
+
- **Pre-rendered Maps & Templates:** Quickly select from our curated collection of hexagon map designs.
|
67 |
+
- **Image Filter (LUT) Application:** Fine-tune image color grading with advanced LUT support.
|
68 |
+
- **TRELLIS Depth & 3D Model Generation:** Create detailed depth maps and 3D models, complete with GLB and Gaussian file extraction.
|
69 |
+
- **Add Margins:** Fine-tune image margins for a professional finish.
|
70 |
+
- **Sketch Pad Integration:** Use the built-in sketch pad to edit images on the fly before processing.
|
71 |
|
72 |
Join the hive and start creating with HexaGrid Creator today!
|
73 |
|
app.py
CHANGED
@@ -1,4 +1,7 @@
|
|
|
|
|
|
1 |
import gradio as gr
|
|
|
2 |
import spaces
|
3 |
import os
|
4 |
import numpy as np
|
@@ -52,6 +55,7 @@ from utils.image_utils import (
|
|
52 |
lerp_imagemath,
|
53 |
shrink_and_paste_on_blank,
|
54 |
show_lut,
|
|
|
55 |
apply_lut_to_image_path,
|
56 |
multiply_and_blend_images,
|
57 |
alpha_composite_with_control,
|
@@ -62,7 +66,8 @@ from utils.image_utils import (
|
|
62 |
build_prerendered_images_by_quality,
|
63 |
get_image_from_dict,
|
64 |
calculate_optimal_fill_dimensions,
|
65 |
-
save_image_to_temp_png
|
|
|
66 |
)
|
67 |
|
68 |
from utils.hex_grid import (
|
@@ -111,12 +116,8 @@ PIPELINE_CLASSES = {
|
|
111 |
"FluxFillPipeline": FluxFillPipeline
|
112 |
}
|
113 |
|
114 |
-
|
115 |
-
|
116 |
-
#initialize_cuda,
|
117 |
-
#release_torch_resources,
|
118 |
-
#get_torch_info
|
119 |
-
)
|
120 |
#from utils.depth_estimation import (get_depth_map_from_state)
|
121 |
|
122 |
input_image_palette = []
|
@@ -125,6 +126,7 @@ current_lut_example_img = gr.State(constants.default_lut_example_img)
|
|
125 |
user_dir = constants.TMPDIR
|
126 |
lora_models = get_lora_models()
|
127 |
selected_index = gr.State(value=-1)
|
|
|
128 |
|
129 |
image_processor: Optional[DPTImageProcessor] = None
|
130 |
depth_model: Optional[DPTForDepthEstimation] = None
|
@@ -133,6 +135,7 @@ pipe: Optional[Union[FluxPipeline, FluxImg2ImgPipeline, FluxControlPipeline, Flu
|
|
133 |
|
134 |
def start_session(req: gr.Request):
|
135 |
print(f"Starting session with hash: {req.session_hash}")
|
|
|
136 |
user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
|
137 |
os.makedirs(user_dir, exist_ok=True)
|
138 |
|
@@ -140,7 +143,8 @@ def start_session(req: gr.Request):
|
|
140 |
def end_session(req: gr.Request):
|
141 |
print(f"Ending session with hash: {req.session_hash}")
|
142 |
user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
|
143 |
-
|
|
|
144 |
|
145 |
# Register the cleanup function
|
146 |
atexit.register(end_session)
|
@@ -777,7 +781,7 @@ def replace_with_sketch_image(sketch_image, replace_current_lut_example_img: boo
|
|
777 |
if replace_current_lut_example_img:
|
778 |
current_lut_example_img = sketch
|
779 |
return sketch
|
780 |
-
|
781 |
|
782 |
@spaces.GPU(progress=gr.Progress(track_tqdm=True))
|
783 |
def load_trellis_model():
|
@@ -790,7 +794,7 @@ def load_trellis_model():
|
|
790 |
TRELLIS_PIPELINE.cuda()
|
791 |
# Preload with a dummy image to finalize initialization
|
792 |
try:
|
793 |
-
TRELLIS_PIPELINE.preprocess_image(Image.fromarray(np.zeros((
|
794 |
except:
|
795 |
pass
|
796 |
print("TRELLIS_PIPELINE loaded\n")
|
@@ -961,7 +965,7 @@ def generate_3d_asset_part1(depth_image_source, randomize_seed, seed, input_imag
|
|
961 |
# Determine the final seed using default MAX_SEED from constants
|
962 |
final_seed = np.random.randint(0, constants.MAX_SEED) if randomize_seed else seed
|
963 |
# Process the image for depth estimation
|
964 |
-
depth_img = depth_process_image(image_path, resized_width=1536, z_scale=
|
965 |
#depth_img = resize_image_with_aspect_ratio(depth_img, 1536, 1536)
|
966 |
|
967 |
user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
|
@@ -970,11 +974,19 @@ def generate_3d_asset_part1(depth_image_source, randomize_seed, seed, input_imag
|
|
970 |
return depth_img, image_path, output_name, final_seed
|
971 |
|
972 |
@spaces.GPU(duration=150,progress=gr.Progress(track_tqdm=True))
|
973 |
-
def generate_3d_asset_part2(depth_img, image_path, output_name, seed, steps, model_resolution, video_resolution, req: gr.Request, progress=gr.Progress(track_tqdm=True)):
|
974 |
# Open image using standardized defaults
|
975 |
image_raw = Image.open(image_path).convert("RGB")
|
976 |
resized_image = resize_image_with_aspect_ratio(image_raw, model_resolution, model_resolution)
|
977 |
depth_img = Image.open(depth_img).convert("RGBA")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
978 |
|
979 |
if TRELLIS_PIPELINE is None:
|
980 |
gr.Warning(f"Trellis Pipeline is not initialized: {TRELLIS_PIPELINE.device()}")
|
@@ -983,21 +995,38 @@ def generate_3d_asset_part2(depth_img, image_path, output_name, seed, steps, mod
|
|
983 |
# Preprocess and run the Trellis pipeline with fixed sampler settings
|
984 |
try:
|
985 |
TRELLIS_PIPELINE.cuda()
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1001 |
|
1002 |
# Validate the mesh
|
1003 |
mesh = outputs['mesh'][0]
|
@@ -1035,6 +1064,7 @@ def generate_3d_asset_part2(depth_img, image_path, output_name, seed, steps, mod
|
|
1035 |
|
1036 |
video = render_utils.render_video(outputs['gaussian'][0], resolution=video_resolution, num_frames=64, r=1, fov=45)['color']
|
1037 |
try:
|
|
|
1038 |
video_geo = render_utils.render_video(outputs['mesh'][0], resolution=video_resolution, num_frames=64, r=1, fov=45)['normal']
|
1039 |
video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
|
1040 |
except Exception as e:
|
@@ -1043,7 +1073,7 @@ def generate_3d_asset_part2(depth_img, image_path, output_name, seed, steps, mod
|
|
1043 |
video_path = os.path.join(user_dir, f'{output_name}.mp4')
|
1044 |
imageio.mimsave(video_path, video, fps=8)
|
1045 |
|
1046 |
-
#snapshot_results = render_utils.render_snapshot_depth(outputs['
|
1047 |
#depth_snapshot = Image.fromarray(snapshot_results['normal'][0]).convert("L")
|
1048 |
depth_snapshot = depth_img
|
1049 |
|
@@ -1106,7 +1136,8 @@ def extract_gaussian(state: dict, req: gr.Request, progress=gr.Progress(track_tq
|
|
1106 |
|
1107 |
@spaces.GPU()
|
1108 |
def getVersions():
|
1109 |
-
return
|
|
|
1110 |
|
1111 |
#generate_input_image_click.zerogpu = True
|
1112 |
#generate_depth_button_click.zerogpu = True
|
@@ -1122,15 +1153,16 @@ with gr.Blocks(css_paths="style_20250314.css", title=title, theme='Surn/beeuty',
|
|
1122 |
with gr.Row():
|
1123 |
gr.Markdown("""
|
1124 |
# HexaGrid Creator
|
1125 |
-
## Transform Your Images into Mesmerizing Hexagon Grid Masterpieces! ⬢
|
1126 |
-
### <span style='color: red; font-
|
|
|
1127 |
with gr.Row():
|
1128 |
with gr.Accordion(" Welcome to HexaGrid Creator, the ultimate tool for transforming your images into stunning hexagon grid artworks. Whether you're a tabletop game enthusiast, a digital artist, or someone who loves unique patterns, HexaGrid Creator has something for you.", open=False, elem_classes="intro"):
|
1129 |
gr.Markdown ("""
|
1130 |
|
1131 |
## Drop an image into the Input Image and get started!
|
1132 |
|
1133 |
-
|
1134 |
|
1135 |
## What is HexaGrid Creator?
|
1136 |
HexaGrid Creator is a web-based application that allows you to apply a hexagon grid overlay to any image. You can customize the size, color, and opacity of the hexagons, as well as the background and border colors. The result is a visually striking image that looks like it was made from hexagonal tiles!
|
@@ -1165,7 +1197,7 @@ with gr.Blocks(css_paths="style_20250314.css", title=title, theme='Surn/beeuty',
|
|
1165 |
|
1166 |
Join the hive and start creating with HexaGrid Creator today!
|
1167 |
|
1168 |
-
""", elem_classes="intro")
|
1169 |
with gr.Row():
|
1170 |
with gr.Column(scale=2):
|
1171 |
input_image = gr.Image(
|
@@ -1273,234 +1305,239 @@ with gr.Blocks(css_paths="style_20250314.css", title=title, theme='Surn/beeuty',
|
|
1273 |
with gr.Row():
|
1274 |
blur_button = gr.Button("Blur Input Image", elem_classes="solid")
|
1275 |
blur_sketch_button = gr.Button("Blur Sketch", elem_classes="solid")
|
1276 |
-
with gr.
|
1277 |
-
with gr.
|
1278 |
-
with gr.
|
1279 |
-
with gr.
|
1280 |
-
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
# value="Cossale/Frames2-Flex.1",
|
1289 |
-
# elem_classes="solid"
|
1290 |
-
# )
|
1291 |
-
model_textbox = gr.Textbox(
|
1292 |
-
label="LORA/Model",
|
1293 |
-
value="Cossale/Frames2-Flex.1",
|
1294 |
-
elem_classes="solid",
|
1295 |
-
elem_id="inference_model",
|
1296 |
-
lines=2,
|
1297 |
-
visible=False
|
1298 |
-
)
|
1299 |
-
with gr.Accordion("Choose Image Style*", open=True):
|
1300 |
-
lora_gallery = gr.Gallery(
|
1301 |
-
[(open_image(image_path), title) for image_path, title in lora_models],
|
1302 |
-
label="Styles",
|
1303 |
-
allow_preview=False, preview=False ,
|
1304 |
-
columns=2,
|
1305 |
-
elem_id="lora_gallery",
|
1306 |
-
show_share_button=False,
|
1307 |
-
elem_classes="solid", type="filepath",
|
1308 |
-
object_fit="contain", height="auto", format="png",
|
1309 |
-
)
|
1310 |
-
# Update map_options to a Dropdown with choices from constants.PROMPTS keys
|
1311 |
with gr.Row():
|
1312 |
-
|
1313 |
-
|
1314 |
-
|
1315 |
-
|
1316 |
-
|
1317 |
-
|
1318 |
-
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
|
1336 |
-
visible=
|
1337 |
-
|
1338 |
-
|
1339 |
-
|
1340 |
-
|
1341 |
-
negative_prompt_textbox = gr.Textbox(
|
1342 |
-
label="Negative Prompt",
|
1343 |
-
visible=False,
|
1344 |
-
elem_classes="solid",
|
1345 |
-
value="Earth, low quality, bad anatomy, blurry, cropped, worst quality, shadows, people, humans, reflections, shadows, realistic map of the Earth, isometric, text, camera_angle"
|
1346 |
-
)
|
1347 |
-
prompt_notes_label = gr.Label(
|
1348 |
-
"You should use FRM$ as trigger words. @1.5 minutes",
|
1349 |
-
elem_classes="solid centered small",
|
1350 |
-
show_label=False,
|
1351 |
-
visible=False
|
1352 |
-
)
|
1353 |
-
# Keep the change event to maintain functionality
|
1354 |
-
map_options.change(
|
1355 |
-
fn=update_prompt_visibility,
|
1356 |
-
inputs=[map_options],
|
1357 |
-
outputs=[prompt_textbox, negative_prompt_textbox, prompt_notes_label]
|
1358 |
)
|
1359 |
-
with gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1360 |
with gr.Row():
|
1361 |
-
with gr.Column():
|
1362 |
-
|
1363 |
-
|
1364 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1365 |
elem_classes="solid"
|
1366 |
)
|
1367 |
-
|
1368 |
-
|
1369 |
-
|
1370 |
-
|
1371 |
-
|
1372 |
-
)
|
1373 |
-
|
1374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1375 |
with gr.Row():
|
1376 |
-
with gr.Column(
|
1377 |
-
|
1378 |
-
|
1379 |
-
|
1380 |
-
|
1381 |
-
|
1382 |
-
|
1383 |
-
|
1384 |
-
|
1385 |
-
|
1386 |
-
|
1387 |
-
|
1388 |
-
|
1389 |
-
|
1390 |
-
|
1391 |
-
|
1392 |
-
|
1393 |
-
|
1394 |
-
|
1395 |
-
|
1396 |
-
|
1397 |
-
|
1398 |
-
|
1399 |
-
|
1400 |
-
|
1401 |
-
|
1402 |
-
|
1403 |
-
|
1404 |
-
|
1405 |
-
|
1406 |
-
|
1407 |
-
|
1408 |
-
|
1409 |
-
|
1410 |
-
|
1411 |
-
|
1412 |
-
|
1413 |
-
|
1414 |
-
|
1415 |
-
|
1416 |
-
|
1417 |
-
|
1418 |
-
|
1419 |
-
|
1420 |
-
|
1421 |
-
|
1422 |
-
|
1423 |
-
|
1424 |
-
|
1425 |
-
|
1426 |
-
|
1427 |
-
|
1428 |
-
|
1429 |
-
|
1430 |
-
|
1431 |
-
|
1432 |
-
|
1433 |
-
|
1434 |
-
|
1435 |
-
|
1436 |
-
|
1437 |
-
|
1438 |
-
|
1439 |
-
|
1440 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1441 |
with gr.Row():
|
1442 |
-
|
1443 |
-
output_grid_tilt = gr.Slider(minimum=-90, maximum=90, value=0, step=0.05, label="Tilt Angle (degrees)")
|
1444 |
-
output_grid_rotation = gr.Slider(minimum=-180, maximum=180, value=0, step=0.05, label="Rotation Angle (degrees)")
|
1445 |
-
with gr.Column(scale=1):
|
1446 |
-
output_alpha_composite = gr.Slider(0,100,50,0.5, label="Alpha Composite Intensity*")
|
1447 |
-
output_blend_multiply_composite = gr.Slider(0,100,50,0.5, label="Multiply Intensity")
|
1448 |
-
output_overlay_composite = gr.Slider(0,100,50,0.5, label="Interpolate Intensity")
|
1449 |
-
with gr.Accordion("Add Margins (for printing)", open=False):
|
1450 |
-
with gr.Row():
|
1451 |
-
border_image_source = gr.Radio(label="Add Margins around which Image", choices=["Input Image", "Overlay Image"], value="Overlay Image")
|
1452 |
-
with gr.Row():
|
1453 |
-
mask_width = gr.Number(label="Margins Width", value=10, minimum=0, maximum=100, precision=0)
|
1454 |
-
mask_height = gr.Number(label="Margins Height", value=10, minimum=0, maximum=100, precision=0)
|
1455 |
-
with gr.Row():
|
1456 |
-
margin_color = gr.ColorPicker(label="Margin Color", value="#333333FF", interactive=True)
|
1457 |
-
margin_opacity = gr.Slider(0,100,95,0.5,label="Margin Opacity %")
|
1458 |
-
with gr.Row():
|
1459 |
-
add_border_button = gr.Button("Add Margins", elem_classes="solid", variant="secondary")
|
1460 |
-
with gr.Row():
|
1461 |
-
bordered_image_output = gr.Image(label="Image with Margins", image_mode="RGBA", elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgBordered",interactive=False, show_download_button=True, show_fullscreen_button=True, show_share_button=True)
|
1462 |
-
accordian_3d = gr.Accordion("Height Maps and 3D (optional, fun)", open=False, elem_id="accordian_3d")
|
1463 |
-
with accordian_3d:
|
1464 |
-
with gr.Row():
|
1465 |
-
depth_image_source = gr.Radio(
|
1466 |
-
label="Depth Image Source",
|
1467 |
-
choices=["Input Image", "Hexagon Grid Image", "Overlay Image", "Image with Margins"],
|
1468 |
-
value="Input Image"
|
1469 |
-
)
|
1470 |
-
with gr.Accordion("Advanced 3D Generation Settings", open=False):
|
1471 |
with gr.Row():
|
1472 |
-
|
1473 |
-
|
1474 |
-
seed_3d = gr.Slider(0, constants.MAX_SEED, label="Seed (3D Generation)", value=0, step=1, randomize=True)
|
1475 |
-
randomize_seed_3d = gr.Checkbox(label="Randomize Seed (3D Generation)", value=True)
|
1476 |
-
with gr.Column():
|
1477 |
-
steps = gr.Slider(6, 36, value=12, step=1, label="Image Sampling Steps", interactive=True)
|
1478 |
-
video_resolution = gr.Slider(384, 768, value=480, step=32, label="Video Resolution (*danger*)", interactive=True)
|
1479 |
-
model_resolution = gr.Slider(512, 2304, value=1024, step=64, label="3D Model Resolution", interactive=True)
|
1480 |
-
with gr.Row():
|
1481 |
-
generate_3d_asset_button = gr.Button("Generate 3D Asset", elem_classes="solid", variant="secondary", interactive=False)
|
1482 |
-
with gr.Row():
|
1483 |
-
depth_output = gr.Image(label="Depth Map", image_mode="L", elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="DepthOutput",interactive=False, show_download_button=True, show_fullscreen_button=True, show_share_button=True, height=400)
|
1484 |
-
with gr.Row():
|
1485 |
-
# For display: video output and 3D model preview (GLTF)
|
1486 |
-
video_output = gr.Video(label="3D Asset Video", autoplay=True, loop=True, height=400)
|
1487 |
-
with gr.Accordion("GLB Extraction Settings", open=False):
|
1488 |
with gr.Row():
|
1489 |
-
|
1490 |
-
|
1491 |
with gr.Row():
|
1492 |
-
|
1493 |
-
extract_gaussian_btn = gr.Button("Extract Gaussian", interactive=False)
|
1494 |
with gr.Row():
|
1495 |
-
|
1496 |
-
|
1497 |
-
|
1498 |
-
|
1499 |
-
|
1500 |
-
|
1501 |
-
|
1502 |
-
|
1503 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1504 |
|
1505 |
is_multiimage = gr.State(False)
|
1506 |
output_buf = gr.State()
|
@@ -1700,7 +1737,7 @@ with gr.Blocks(css_paths="style_20250314.css", title=title, theme='Surn/beeuty',
|
|
1700 |
scroll_to_output=True
|
1701 |
).then(
|
1702 |
fn=generate_3d_asset_part2,
|
1703 |
-
inputs=[depth_output, ddd_image_path, ddd_file_name, seed_3d, steps, model_resolution, video_resolution
|
1704 |
outputs=[output_buf, video_output, depth_output],
|
1705 |
scroll_to_output=True
|
1706 |
).then(
|
@@ -1762,9 +1799,8 @@ if __name__ == "__main__":
|
|
1762 |
TRELLIS_PIPELINE = TrellisImageTo3DPipeline.from_pretrained("JeffreyXiang/TRELLIS-image-large")
|
1763 |
TRELLIS_PIPELINE.to(device)
|
1764 |
try:
|
1765 |
-
TRELLIS_PIPELINE.preprocess_image(Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8)), 512) # Preload rembg
|
1766 |
except:
|
1767 |
pass
|
1768 |
hexaGrid.queue(default_concurrency_limit=1,max_size=12,api_open=False)
|
1769 |
-
hexaGrid.launch(allowed_paths=["assets","/","./assets","images","./images", "./images/prerendered", 'e:/TMP'], favicon_path="./assets/favicon.ico", max_file_size="10mb")
|
1770 |
-
|
|
|
1 |
+
from ast import Str
|
2 |
+
from tokenize import String
|
3 |
import gradio as gr
|
4 |
+
from numba.core.types import string
|
5 |
import spaces
|
6 |
import os
|
7 |
import numpy as np
|
|
|
55 |
lerp_imagemath,
|
56 |
shrink_and_paste_on_blank,
|
57 |
show_lut,
|
58 |
+
apply_lut,
|
59 |
apply_lut_to_image_path,
|
60 |
multiply_and_blend_images,
|
61 |
alpha_composite_with_control,
|
|
|
66 |
build_prerendered_images_by_quality,
|
67 |
get_image_from_dict,
|
68 |
calculate_optimal_fill_dimensions,
|
69 |
+
save_image_to_temp_png,
|
70 |
+
combine_depth_map_with_Image
|
71 |
)
|
72 |
|
73 |
from utils.hex_grid import (
|
|
|
116 |
"FluxFillPipeline": FluxFillPipeline
|
117 |
}
|
118 |
|
119 |
+
import utils.version_info as version_info
|
120 |
+
|
|
|
|
|
|
|
|
|
121 |
#from utils.depth_estimation import (get_depth_map_from_state)
|
122 |
|
123 |
input_image_palette = []
|
|
|
126 |
user_dir = constants.TMPDIR
|
127 |
lora_models = get_lora_models()
|
128 |
selected_index = gr.State(value=-1)
|
129 |
+
#html_versions = version_info.versions_html()
|
130 |
|
131 |
image_processor: Optional[DPTImageProcessor] = None
|
132 |
depth_model: Optional[DPTForDepthEstimation] = None
|
|
|
135 |
|
136 |
def start_session(req: gr.Request):
|
137 |
print(f"Starting session with hash: {req.session_hash}")
|
138 |
+
session_hash = str(req.session_hash)
|
139 |
user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
|
140 |
os.makedirs(user_dir, exist_ok=True)
|
141 |
|
|
|
143 |
def end_session(req: gr.Request):
|
144 |
print(f"Ending session with hash: {req.session_hash}")
|
145 |
user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
|
146 |
+
if os.path.exists(user_dir):
|
147 |
+
shutil.rmtree(user_dir)
|
148 |
|
149 |
# Register the cleanup function
|
150 |
atexit.register(end_session)
|
|
|
781 |
if replace_current_lut_example_img:
|
782 |
current_lut_example_img = sketch
|
783 |
return sketch
|
784 |
+
################################################################## DEPTH ESTIMATION ###############################################################################
|
785 |
|
786 |
@spaces.GPU(progress=gr.Progress(track_tqdm=True))
|
787 |
def load_trellis_model():
|
|
|
794 |
TRELLIS_PIPELINE.cuda()
|
795 |
# Preload with a dummy image to finalize initialization
|
796 |
try:
|
797 |
+
TRELLIS_PIPELINE.preprocess_image(Image.fromarray(np.zeros((518, 518, 4), dtype=np.uint8))) # Preload rembg
|
798 |
except:
|
799 |
pass
|
800 |
print("TRELLIS_PIPELINE loaded\n")
|
|
|
965 |
# Determine the final seed using default MAX_SEED from constants
|
966 |
final_seed = np.random.randint(0, constants.MAX_SEED) if randomize_seed else seed
|
967 |
# Process the image for depth estimation
|
968 |
+
depth_img = depth_process_image(image_path, resized_width=1536, z_scale=208)
|
969 |
#depth_img = resize_image_with_aspect_ratio(depth_img, 1536, 1536)
|
970 |
|
971 |
user_dir = os.path.join(constants.TMPDIR, str(req.session_hash))
|
|
|
974 |
return depth_img, image_path, output_name, final_seed
|
975 |
|
976 |
@spaces.GPU(duration=150,progress=gr.Progress(track_tqdm=True))
|
977 |
+
def generate_3d_asset_part2(depth_img, image_path, output_name, seed, steps, model_resolution, video_resolution, depth_alpha: int, multi_mode: str, req: gr.Request, progress=gr.Progress(track_tqdm=True)):
|
978 |
# Open image using standardized defaults
|
979 |
image_raw = Image.open(image_path).convert("RGB")
|
980 |
resized_image = resize_image_with_aspect_ratio(image_raw, model_resolution, model_resolution)
|
981 |
depth_img = Image.open(depth_img).convert("RGBA")
|
982 |
+
resized_depth_image = resize_image_with_aspect_ratio(depth_img, model_resolution, model_resolution)
|
983 |
+
resized_depth_image_enhanced = apply_lut(resized_depth_image, "./LUT/Contrast.cube", 100)
|
984 |
+
combined_depth_img = combine_depth_map_with_Image(resized_image, resized_depth_image_enhanced, model_resolution, model_resolution, depth_alpha)
|
985 |
+
|
986 |
+
use_multi = (multi_mode != "singleimage")
|
987 |
+
if use_multi:
|
988 |
+
images = [resized_image, combined_depth_img, resized_depth_image]
|
989 |
+
processed_images = [TRELLIS_PIPELINE.preprocess_image(image, max_resolution=model_resolution, remove_bg=False) for image in images]
|
990 |
|
991 |
if TRELLIS_PIPELINE is None:
|
992 |
gr.Warning(f"Trellis Pipeline is not initialized: {TRELLIS_PIPELINE.device()}")
|
|
|
995 |
# Preprocess and run the Trellis pipeline with fixed sampler settings
|
996 |
try:
|
997 |
TRELLIS_PIPELINE.cuda()
|
998 |
+
if not use_multi:
|
999 |
+
processed_image = TRELLIS_PIPELINE.preprocess_image(combined_depth_img, max_resolution=model_resolution, remove_bg = False)
|
1000 |
+
outputs = TRELLIS_PIPELINE.run(
|
1001 |
+
processed_image,
|
1002 |
+
seed=seed,
|
1003 |
+
formats=["gaussian", "mesh"],
|
1004 |
+
preprocess_image=False,
|
1005 |
+
sparse_structure_sampler_params={
|
1006 |
+
"steps": steps,
|
1007 |
+
"cfg_strength": 7.5,
|
1008 |
+
},
|
1009 |
+
slat_sampler_params={
|
1010 |
+
"steps": steps,
|
1011 |
+
"cfg_strength": 3.0,
|
1012 |
+
},
|
1013 |
+
)
|
1014 |
+
else:
|
1015 |
+
outputs = TRELLIS_PIPELINE.run_multi_image(
|
1016 |
+
processed_images,
|
1017 |
+
seed=seed,
|
1018 |
+
formats=["gaussian", "mesh"],
|
1019 |
+
preprocess_image=False,
|
1020 |
+
sparse_structure_sampler_params={
|
1021 |
+
"steps": steps,
|
1022 |
+
"cfg_strength": 7.5,
|
1023 |
+
},
|
1024 |
+
slat_sampler_params={
|
1025 |
+
"steps": steps,
|
1026 |
+
"cfg_strength": 3.0,
|
1027 |
+
},
|
1028 |
+
mode=multi_mode,
|
1029 |
+
)
|
1030 |
|
1031 |
# Validate the mesh
|
1032 |
mesh = outputs['mesh'][0]
|
|
|
1064 |
|
1065 |
video = render_utils.render_video(outputs['gaussian'][0], resolution=video_resolution, num_frames=64, r=1, fov=45)['color']
|
1066 |
try:
|
1067 |
+
#video_rf = render_utils.render_video(outputs['radiance_field'][0], resolution=video_resolution, num_frames=64, r=1, fov=45)['color']
|
1068 |
video_geo = render_utils.render_video(outputs['mesh'][0], resolution=video_resolution, num_frames=64, r=1, fov=45)['normal']
|
1069 |
video = [np.concatenate([video[i], video_geo[i]], axis=1) for i in range(len(video))]
|
1070 |
except Exception as e:
|
|
|
1073 |
video_path = os.path.join(user_dir, f'{output_name}.mp4')
|
1074 |
imageio.mimsave(video_path, video, fps=8)
|
1075 |
|
1076 |
+
#snapshot_results = render_utils.render_snapshot_depth(outputs['radiance_field'][0], resolution=1280, r=1, fov=80)
|
1077 |
#depth_snapshot = Image.fromarray(snapshot_results['normal'][0]).convert("L")
|
1078 |
depth_snapshot = depth_img
|
1079 |
|
|
|
1136 |
|
1137 |
@spaces.GPU()
|
1138 |
def getVersions():
|
1139 |
+
#return html_versions
|
1140 |
+
return version_info.versions_html()
|
1141 |
|
1142 |
#generate_input_image_click.zerogpu = True
|
1143 |
#generate_depth_button_click.zerogpu = True
|
|
|
1153 |
with gr.Row():
|
1154 |
gr.Markdown("""
|
1155 |
# HexaGrid Creator
|
1156 |
+
## Transform Your Images into Mesmerizing Hexagon Grid Masterpieces with Advanced AI, 3D Depth, and Interactive Filters! ⬢
|
1157 |
+
### <span style='color: red; font-weight: bolder;'>BEST VIEWED ON DESKTOP – New Sketch Pad, Image Filters, and 3D Features Enabled</span>
|
1158 |
+
""", elem_classes="intro", sanitize_html=False)
|
1159 |
with gr.Row():
|
1160 |
with gr.Accordion(" Welcome to HexaGrid Creator, the ultimate tool for transforming your images into stunning hexagon grid artworks. Whether you're a tabletop game enthusiast, a digital artist, or someone who loves unique patterns, HexaGrid Creator has something for you.", open=False, elem_classes="intro"):
|
1161 |
gr.Markdown ("""
|
1162 |
|
1163 |
## Drop an image into the Input Image and get started!
|
1164 |
|
1165 |
+
### <span style='color: red; font-weight: bolder;'>ZeroGPU sometimes crashes or is not available. It is not a code issue.</span>
|
1166 |
|
1167 |
## What is HexaGrid Creator?
|
1168 |
HexaGrid Creator is a web-based application that allows you to apply a hexagon grid overlay to any image. You can customize the size, color, and opacity of the hexagons, as well as the background and border colors. The result is a visually striking image that looks like it was made from hexagonal tiles!
|
|
|
1197 |
|
1198 |
Join the hive and start creating with HexaGrid Creator today!
|
1199 |
|
1200 |
+
""", elem_classes="intro", sanitize_html=False)
|
1201 |
with gr.Row():
|
1202 |
with gr.Column(scale=2):
|
1203 |
input_image = gr.Image(
|
|
|
1305 |
with gr.Row():
|
1306 |
blur_button = gr.Button("Blur Input Image", elem_classes="solid")
|
1307 |
blur_sketch_button = gr.Button("Blur Sketch", elem_classes="solid")
|
1308 |
+
with gr.Tabs(selected="hex_gen") as input_tabs:
|
1309 |
+
with gr.Tab("HexaGrid Generation", id="hex_gen") as hexa_gen_tab:
|
1310 |
+
with gr.Column(elem_classes="outline-important"):
|
1311 |
+
with gr.Accordion("Advanced Hexagon Settings", open = False):
|
1312 |
+
with gr.Accordion("Hex Coloring and Exclusion", open = True):
|
1313 |
+
with gr.Row():
|
1314 |
+
color_picker = gr.ColorPicker(label="Pick a color to exclude",value="#505050")
|
1315 |
+
filter_color = gr.Checkbox(label="Filter Excluded Colors from Sampling", value=False,)
|
1316 |
+
exclude_color_button = gr.Button("Exclude Color", elem_id="exlude_color_button", elem_classes="solid")
|
1317 |
+
color_display = gr.DataFrame(label="List of Excluded RGBA Colors", headers=["R", "G", "B", "A"], elem_id="excluded_colors", type="array", value=build_dataframe(excluded_color_list), interactive=True, elem_classes="solid centered")
|
1318 |
+
selected_row = gr.Number(0, label="Selected Row", visible=False)
|
1319 |
+
delete_button = gr.Button("Delete Row", elem_id="delete_exclusion_button", elem_classes="solid")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1320 |
with gr.Row():
|
1321 |
+
start_x = gr.Number(label="Start X", value=20, minimum=-512, maximum= 512, precision=0)
|
1322 |
+
start_y = gr.Number(label="Start Y", value=20, minimum=-512, maximum= 512, precision=0)
|
1323 |
+
end_x = gr.Number(label="End X", value=-20, minimum=-512, maximum= 512, precision=0)
|
1324 |
+
end_y = gr.Number(label="End Y", value=-20, minimum=-512, maximum= 512, precision=0)
|
1325 |
+
with gr.Row():
|
1326 |
+
rotation = gr.Slider(-90, 180, 0.0, 0.1, label="Hexagon Rotation (degree)")
|
1327 |
+
sides = gr.Dropdown(label="Grid Shapes", info="The shapes that form grids",choices=["triangle", "square", "hexagon"], value="hexagon", allow_custom_value=False)
|
1328 |
+
with gr.Row():
|
1329 |
+
add_hex_text = gr.Dropdown(label="Add Text to Hexagons", choices=[None, "Column-Row Coordinates", "Column(Letter)-Row Coordinates", "Column-Row(Letter) Coordinates", "Sequential Numbers", "Playing Cards Sequential", "Playing Cards Alternate Red and Black", "Custom List"], value=None, allow_custom_value=False)
|
1330 |
+
x_spacing = gr.Number(label="Adjust Horizontal spacing", value=-14, minimum=-200, maximum=200, precision=1)
|
1331 |
+
y_spacing = gr.Number(label="Adjust Vertical spacing", value=3, minimum=-200, maximum=200, precision=1)
|
1332 |
+
with gr.Row():
|
1333 |
+
custom_text_list = gr.TextArea(label="Custom Text List", value=constants.cards_alternating, visible=False,)
|
1334 |
+
custom_text_color_list = gr.TextArea(label="Custom Text Color List", value=constants.card_colors_alternating, visible=False)
|
1335 |
+
with gr.Row():
|
1336 |
+
hex_text_info = gr.Markdown("""
|
1337 |
+
### Text Color uses the Border Color and Border Opacity, unless you use a custom list.
|
1338 |
+
### The Custom Text List and Custom Text Color List are repeating comma separated lists.
|
1339 |
+
### The custom color list is a comma separated list of hex colors.
|
1340 |
+
#### Example: "A,2,3,4,5,6,7,8,9,10,J,Q,K", "red,#0000FF,#00FF00,red,#FFFF00,#00FFFF,#FF8000,#FF00FF,#FF0080,#FF8000,#FF0080,lightblue"
|
1341 |
+
""", elem_id="hex_text_info", visible=False)
|
1342 |
+
add_hex_text.change(
|
1343 |
+
fn=lambda x: (
|
1344 |
+
gr.update(visible=(x == "Custom List")),
|
1345 |
+
gr.update(visible=(x == "Custom List")),
|
1346 |
+
gr.update(visible=(x != None))
|
1347 |
+
),
|
1348 |
+
inputs=add_hex_text,
|
1349 |
+
outputs=[custom_text_list, custom_text_color_list, hex_text_info]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1350 |
)
|
1351 |
+
with gr.Row():
|
1352 |
+
hex_size = gr.Number(label="Hexagon Size", value=120, minimum=1, maximum=768)
|
1353 |
+
border_size = gr.Slider(-5,25,value=2,step=1,label="Border Size")
|
1354 |
+
fill_hex = gr.Checkbox(label="Fill Hex with color from Image", value=True)
|
1355 |
+
with gr.Row():
|
1356 |
+
background_color = gr.ColorPicker(label="Background Color", value="#000000", interactive=True)
|
1357 |
+
background_opacity = gr.Slider(0,100,0,1,label="Background Opacity %")
|
1358 |
+
border_color = gr.ColorPicker(label="Border Color", value="#7b7b7b", interactive=True)
|
1359 |
+
border_opacity = gr.Slider(0,100,50,1,label="Border Opacity %")
|
1360 |
+
with gr.Row():
|
1361 |
+
hex_button = gr.Button("Generate Hex Grid!", elem_classes="solid", elem_id="btn-generate")
|
1362 |
+
with gr.Row():
|
1363 |
+
output_image = gr.Image(label="Hexagon Grid Image", image_mode = "RGBA", elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgOutput",interactive=True)
|
1364 |
+
overlay_image = gr.Image(label="Hexagon Overlay Image", image_mode = "RGBA", elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgOverlay",interactive=True)
|
1365 |
+
with gr.Accordion("Grid adjustments", open=True):
|
1366 |
with gr.Row():
|
1367 |
+
with gr.Column(scale=1):
|
1368 |
+
output_grid_tilt = gr.Slider(minimum=-90, maximum=90, value=0, step=0.05, label="Tilt Angle (degrees)")
|
1369 |
+
output_grid_rotation = gr.Slider(minimum=-180, maximum=180, value=0, step=0.05, label="Rotation Angle (degrees)")
|
1370 |
+
with gr.Column(scale=1):
|
1371 |
+
output_alpha_composite = gr.Slider(0,100,50,0.5, label="Alpha Composite Intensity*")
|
1372 |
+
output_blend_multiply_composite = gr.Slider(0,100,50,0.5, label="Multiply Intensity")
|
1373 |
+
output_overlay_composite = gr.Slider(0,100,50,0.5, label="Interpolate Intensity")
|
1374 |
+
|
1375 |
+
with gr.Tab("Image Generation (AI)", id="image_gen") as image_gen_tab:
|
1376 |
+
with gr.Row(elem_id="image_gen"):
|
1377 |
+
with gr.Accordion("Generate AI Image (optional, fun)", open = False):
|
1378 |
+
with gr.Row():
|
1379 |
+
with gr.Column(scale=1):
|
1380 |
+
generate_input_image = gr.Button(
|
1381 |
+
"Generate from Input Image & Options ",
|
1382 |
+
elem_id="generate_input_image",
|
1383 |
elem_classes="solid"
|
1384 |
)
|
1385 |
+
# model_options = gr.Dropdown(
|
1386 |
+
# label="Choose an AI Model*",
|
1387 |
+
# choices=constants.MODELS + constants.LORA_WEIGHTS + ["Manual Entry"],
|
1388 |
+
# value="Cossale/Frames2-Flex.1",
|
1389 |
+
# elem_classes="solid", allow_custom_value=False
|
1390 |
+
# )
|
1391 |
+
model_textbox = gr.Textbox(
|
1392 |
+
label="LORA/Model",
|
1393 |
+
value="Cossale/Frames2-Flex.1",
|
1394 |
+
elem_classes="solid",
|
1395 |
+
elem_id="inference_model",
|
1396 |
+
lines=2,
|
1397 |
+
visible=False
|
1398 |
+
)
|
1399 |
+
with gr.Accordion("Choose Image Style*", open=True):
|
1400 |
+
lora_gallery = gr.Gallery(
|
1401 |
+
[(open_image(image_path), title) for image_path, title in lora_models],
|
1402 |
+
label="Styles",
|
1403 |
+
allow_preview=False, preview=False ,
|
1404 |
+
columns=2,
|
1405 |
+
elem_id="lora_gallery",
|
1406 |
+
show_share_button=False,
|
1407 |
+
elem_classes="solid", type="filepath",
|
1408 |
+
object_fit="contain", height="auto", format="png",
|
1409 |
+
)
|
1410 |
+
# Update map_options to a Dropdown with choices from constants.PROMPTS keys
|
1411 |
with gr.Row():
|
1412 |
+
with gr.Column():
|
1413 |
+
map_options = gr.Dropdown(
|
1414 |
+
label="Map Options*",
|
1415 |
+
choices=list(constants.PROMPTS.keys()),
|
1416 |
+
value="Alien Landscape",
|
1417 |
+
elem_classes="solid",
|
1418 |
+
scale=0, allow_custom_value=False
|
1419 |
+
)
|
1420 |
+
# Add Dropdown for sizing of Images, height and width based on selection. Options are 16x9, 16x10, 4x5, 1x1
|
1421 |
+
# The values of height and width are based on common resolutions for each aspect ratio
|
1422 |
+
# Default to 16x9, 912x512
|
1423 |
+
image_size_ratio = gr.Dropdown(label="Image Aspect Ratio", choices=["16:9", "16:10", "4:5", "4:3", "2:1","3:2","1:1", "9:16", "10:16", "5:4", "3:4","1:2", "2:3"], value="16:9", elem_classes="solid", type="value", scale=0, interactive=True, allow_custom_value=False)
|
1424 |
+
with gr.Column():
|
1425 |
+
seed_slider = gr.Slider(
|
1426 |
+
label="Seed",
|
1427 |
+
minimum=0,
|
1428 |
+
maximum=constants.MAX_SEED,
|
1429 |
+
step=1,
|
1430 |
+
value=0,
|
1431 |
+
scale=0, randomize=True, elem_id="rnd_seed"
|
1432 |
+
)
|
1433 |
+
randomize_seed = gr.Checkbox(label="Randomize seed", value=False, scale=0, interactive=True)
|
1434 |
+
prompt_textbox = gr.Textbox(
|
1435 |
+
label="Prompt",
|
1436 |
+
visible=False,
|
1437 |
+
elem_classes="solid",
|
1438 |
+
value="Planetary overhead view, directly from above, centered on the planet’s surface, orthographic (rectangular tabletop_map) alien planet map, Battletech_boardgame scifi world with forests, lakes, oceans, continents and snow at the top and bottom, (middle is dark, no_reflections, no_shadows), looking straight down.",
|
1439 |
+
lines=4
|
1440 |
+
)
|
1441 |
+
negative_prompt_textbox = gr.Textbox(
|
1442 |
+
label="Negative Prompt",
|
1443 |
+
visible=False,
|
1444 |
+
elem_classes="solid",
|
1445 |
+
value="Earth, low quality, bad anatomy, blurry, cropped, worst quality, shadows, people, humans, reflections, shadows, realistic map of the Earth, isometric, text, camera_angle"
|
1446 |
+
)
|
1447 |
+
prompt_notes_label = gr.Label(
|
1448 |
+
"You should use FRM$ as trigger words. @1.5 minutes",
|
1449 |
+
elem_classes="solid centered small",
|
1450 |
+
show_label=False,
|
1451 |
+
visible=False
|
1452 |
+
)
|
1453 |
+
# Keep the change event to maintain functionality
|
1454 |
+
map_options.change(
|
1455 |
+
fn=update_prompt_visibility,
|
1456 |
+
inputs=[map_options],
|
1457 |
+
outputs=[prompt_textbox, negative_prompt_textbox, prompt_notes_label]
|
1458 |
+
)
|
1459 |
+
with gr.Column(scale=2):
|
1460 |
+
with gr.Row():
|
1461 |
+
with gr.Column():
|
1462 |
+
generate_input_image_from_gallery = gr.Button(
|
1463 |
+
"Generate AI Image from Template Options",
|
1464 |
+
elem_id="generate_input_image_from_gallery",
|
1465 |
+
elem_classes="solid"
|
1466 |
+
)
|
1467 |
+
with gr.Column():
|
1468 |
+
replace_input_image_button = gr.Button(
|
1469 |
+
"Replace Input Image with Template",
|
1470 |
+
elem_id="prerendered_replace_input_image_button",
|
1471 |
+
elem_classes="solid"
|
1472 |
+
)
|
1473 |
+
with gr.Row():
|
1474 |
+
with gr.Accordion("Template Images", open = False):
|
1475 |
+
with gr.Row():
|
1476 |
+
with gr.Column(scale=2):
|
1477 |
+
# Gallery from PRE_RENDERED_IMAGES GOES HERE
|
1478 |
+
prerendered_image_gallery = gr.Gallery(label="Image Gallery", show_label=True, value=build_prerendered_images_by_quality(3,'thumbnail'), elem_id="gallery",
|
1479 |
+
elem_classes="solid", type="filepath", columns=[3], rows=[3], preview=False ,object_fit="contain", height="auto", format="png",allow_preview=False)
|
1480 |
+
with gr.Row():
|
1481 |
+
image_guidance_stength = gr.Slider(label="Image Guidance Strength (prompt percentage)", info="applies to Input, Sketch and Template Image",minimum=0, maximum=1.0, value=0.85, step=0.01, interactive=True)
|
1482 |
+
|
1483 |
+
with gr.Tab("Add Margins", id="margins") as margins_tab:
|
1484 |
with gr.Row():
|
1485 |
+
border_image_source = gr.Radio(label="Add Margins around which Image", choices=["Input Image", "Overlay Image"], value="Overlay Image")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1486 |
with gr.Row():
|
1487 |
+
mask_width = gr.Number(label="Margins Width", value=10, minimum=0, maximum=100, precision=0)
|
1488 |
+
mask_height = gr.Number(label="Margins Height", value=10, minimum=0, maximum=100, precision=0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1489 |
with gr.Row():
|
1490 |
+
margin_color = gr.ColorPicker(label="Margin Color", value="#333333FF", interactive=True)
|
1491 |
+
margin_opacity = gr.Slider(0,100,95,0.5,label="Margin Opacity %")
|
1492 |
with gr.Row():
|
1493 |
+
add_border_button = gr.Button("Add Margins", elem_classes="solid", variant="secondary")
|
|
|
1494 |
with gr.Row():
|
1495 |
+
bordered_image_output = gr.Image(label="Image with Margins", image_mode="RGBA", elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="ImgBordered",interactive=False, show_download_button=True, show_fullscreen_button=True, show_share_button=True)
|
1496 |
+
with gr.Tab("3D and Depth (fun)", id="3D") as depth_tab:
|
1497 |
+
accordian_3d = gr.Accordion("Clicking here to toggle between Image Generation and 3D models", open=False, elem_id="accordian_3d")
|
1498 |
+
with accordian_3d:
|
1499 |
+
with gr.Row():
|
1500 |
+
depth_image_source = gr.Radio(
|
1501 |
+
label="Depth Image Source",
|
1502 |
+
choices=["Input Image", "Hexagon Grid Image", "Overlay Image", "Image with Margins"],
|
1503 |
+
value="Input Image"
|
1504 |
+
)
|
1505 |
+
with gr.Accordion("Advanced 3D Generation Settings", open=False):
|
1506 |
+
with gr.Row():
|
1507 |
+
with gr.Column():
|
1508 |
+
# Use standard seed settings only
|
1509 |
+
seed_3d = gr.Slider(0, constants.MAX_SEED, label="Seed (3D Generation)", value=0, step=1, randomize=True)
|
1510 |
+
randomize_seed_3d = gr.Checkbox(label="Randomize Seed (3D Generation)", value=True)
|
1511 |
+
depth_alpha = gr.Slider(-200,200,0, step=5, label="Amount of Depth Image to apply to main Image", interactive=True)
|
1512 |
+
multiimage_algo = gr.Radio(["singleimage","stochastic", "multidiffusion"], label="Multi-image Algorithm", value="singleimage")
|
1513 |
+
with gr.Column():
|
1514 |
+
steps = gr.Slider(6, 100, value=25, step=1, label="Image Sampling Steps", interactive=True)
|
1515 |
+
video_resolution = gr.Slider(384, 768, value=480, step=32, label="Video Resolution (*danger*)", interactive=True)
|
1516 |
+
model_resolution = gr.Slider(518, 2520, value=1540, step=28, label="3D Model Resolution", interactive=True)
|
1517 |
+
with gr.Row():
|
1518 |
+
generate_3d_asset_button = gr.Button("Generate 3D Asset", elem_classes="solid", variant="secondary", interactive=False)
|
1519 |
+
with gr.Row():
|
1520 |
+
depth_output = gr.Image(label="Depth Map", image_mode="L", elem_classes="centered solid imgcontainer", format="PNG", type="filepath", key="DepthOutput",interactive=False, show_download_button=True, show_fullscreen_button=True, show_share_button=True, height=400)
|
1521 |
+
with gr.Row():
|
1522 |
+
# For display: video output and 3D model preview (GLTF)
|
1523 |
+
video_output = gr.Video(label="3D Asset Video", autoplay=True, loop=True, height=400)
|
1524 |
+
with gr.Accordion("GLB Extraction Settings", open=False):
|
1525 |
+
with gr.Row():
|
1526 |
+
mesh_simplify = gr.Slider(0.9, 0.98, label="Simplify", value=0.95, step=0.01)
|
1527 |
+
texture_size = gr.Slider(512, 2048, label="Texture Size", value=1024, step=512)
|
1528 |
+
with gr.Row():
|
1529 |
+
extract_glb_btn = gr.Button("Extract GLB", interactive=False)
|
1530 |
+
extract_gaussian_btn = gr.Button("Extract Gaussian", interactive=False)
|
1531 |
+
with gr.Row():
|
1532 |
+
with gr.Column(scale=2):
|
1533 |
+
model_output = gr.Model3D(label="Extracted 3D Model", clear_color=[1.0, 1.0, 1.0, 1.0],
|
1534 |
+
elem_classes="centered solid imgcontainer", interactive=True)
|
1535 |
+
with gr.Column(scale=1):
|
1536 |
+
glb_file = gr.File(label="3D GLTF", elem_classes="solid small centered", height=250)
|
1537 |
+
gaussian_file = gr.File(label="Gaussian", elem_classes="solid small centered", height=250)
|
1538 |
+
gr.Markdown("""
|
1539 |
+
### Files over 10 MB may not display in the 3D model viewer
|
1540 |
+
""", elem_id="file_size_info", elem_classes="intro" )
|
1541 |
|
1542 |
is_multiimage = gr.State(False)
|
1543 |
output_buf = gr.State()
|
|
|
1737 |
scroll_to_output=True
|
1738 |
).then(
|
1739 |
fn=generate_3d_asset_part2,
|
1740 |
+
inputs=[depth_output, ddd_image_path, ddd_file_name, seed_3d, steps, model_resolution, video_resolution, depth_alpha, multiimage_algo],
|
1741 |
outputs=[output_buf, video_output, depth_output],
|
1742 |
scroll_to_output=True
|
1743 |
).then(
|
|
|
1799 |
TRELLIS_PIPELINE = TrellisImageTo3DPipeline.from_pretrained("JeffreyXiang/TRELLIS-image-large")
|
1800 |
TRELLIS_PIPELINE.to(device)
|
1801 |
try:
|
1802 |
+
TRELLIS_PIPELINE.preprocess_image(Image.fromarray(np.zeros((512, 512, 3), dtype=np.uint8)), 512, True) # Preload rembg
|
1803 |
except:
|
1804 |
pass
|
1805 |
hexaGrid.queue(default_concurrency_limit=1,max_size=12,api_open=False)
|
1806 |
+
hexaGrid.launch(allowed_paths=["assets","/","./assets","images","./images", "./images/prerendered", 'e:/TMP'], favicon_path="./assets/favicon.ico", max_file_size="10mb")
|
|
style_20250314.css
CHANGED
@@ -21,7 +21,7 @@
|
|
21 |
background-color: rgba(242, 218, 163, 0.62);
|
22 |
}
|
23 |
|
24 |
-
.dark .gradio-container.gradio-container-5-
|
25 |
background-color: rgba(41, 18, 5, 0.38) !important;
|
26 |
}
|
27 |
.toast-body.info {
|
@@ -165,3 +165,23 @@ a {
|
|
165 |
padding: 2px;
|
166 |
border-radius: 6px;
|
167 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
background-color: rgba(242, 218, 163, 0.62);
|
22 |
}
|
23 |
|
24 |
+
.dark .gradio-container.gradio-container-5-23-1 .contain .intro .prose {
|
25 |
background-color: rgba(41, 18, 5, 0.38) !important;
|
26 |
}
|
27 |
.toast-body.info {
|
|
|
165 |
padding: 2px;
|
166 |
border-radius: 6px;
|
167 |
}
|
168 |
+
.selected.svelte-1tcem6n.svelte-1tcem6n {
|
169 |
+
font-size: large;
|
170 |
+
font-weight: bold;
|
171 |
+
color: var(--body-text-color);
|
172 |
+
}
|
173 |
+
.tab-wrapper.svelte-1tcem6n.svelte-1tcem6n {
|
174 |
+
height: var(--size-12);
|
175 |
+
padding-bottom: var(--size-1);
|
176 |
+
text-align: center;
|
177 |
+
background-blend-mode: multiply;
|
178 |
+
border-radius: var(--block-radius);
|
179 |
+
background-color: var(--block-background-fill);
|
180 |
+
|
181 |
+
outline-color: var(--accordion-text-color);
|
182 |
+
outline-style: solid;
|
183 |
+
outline-width: 2px;
|
184 |
+
outline-offset: 2px;
|
185 |
+
padding: 2px;
|
186 |
+
border-radius: 6px;
|
187 |
+
}
|
trellis/pipelines/trellis_image_to_3d.py
CHANGED
@@ -87,6 +87,7 @@ class TrellisImageTo3DPipeline(Pipeline):
|
|
87 |
Preprocess the input image.
|
88 |
"""
|
89 |
# if has alpha channel, use it directly; otherwise, remove background
|
|
|
90 |
has_alpha = False
|
91 |
if input.mode == 'RGBA':
|
92 |
alpha = np.array(input)[:, :, 3]
|
@@ -114,8 +115,9 @@ class TrellisImageTo3DPipeline(Pipeline):
|
|
114 |
size = max(bbox[2] - bbox[0], bbox[3] - bbox[1])
|
115 |
size = int(size * 1.2)
|
116 |
bbox = center[0] - size // 2, center[1] - size // 2, center[0] + size // 2, center[1] + size // 2
|
117 |
-
output = output.crop(bbox) # type: ignore
|
118 |
-
|
|
|
119 |
output = np.array(output).astype(np.float32) / 255
|
120 |
output = output[:, :, :3] * output[:, :, 3:4]
|
121 |
output = Image.fromarray((output * 255).astype(np.uint8))
|
@@ -136,13 +138,15 @@ class TrellisImageTo3DPipeline(Pipeline):
|
|
136 |
assert image.ndim == 4, "Image tensor should be batched (B, C, H, W)"
|
137 |
elif isinstance(image, list):
|
138 |
assert all(isinstance(i, Image.Image) for i in image), "Image list should be list of PIL images"
|
139 |
-
|
|
|
|
|
140 |
image = [np.array(i.convert('RGB')).astype(np.float32) / 255 for i in image]
|
141 |
image = [torch.from_numpy(i).permute(2, 0, 1).float() for i in image]
|
142 |
image = torch.stack(image).to(self.device)
|
143 |
else:
|
144 |
raise ValueError(f"Unsupported type of image: {type(image)}")
|
145 |
-
|
146 |
image = self.image_cond_model_transform(image).to(self.device)
|
147 |
features = self.models['image_cond_model'](image, is_training=True)['x_prenorm']
|
148 |
patchtokens = F.layer_norm(features, features.shape[-1:])
|
@@ -267,6 +271,7 @@ class TrellisImageTo3DPipeline(Pipeline):
|
|
267 |
slat_sampler_params: dict = {},
|
268 |
formats: List[str] = ['mesh', 'gaussian', 'radiance_field'],
|
269 |
preprocess_image: bool = True,
|
|
|
270 |
remove_bg: bool = True,
|
271 |
) -> dict:
|
272 |
"""
|
@@ -280,7 +285,7 @@ class TrellisImageTo3DPipeline(Pipeline):
|
|
280 |
preprocess_image (bool): Whether to preprocess the image.
|
281 |
"""
|
282 |
if preprocess_image:
|
283 |
-
image = self.preprocess_image(image, remove_bg=remove_bg)
|
284 |
cond = self.get_cond([image])
|
285 |
torch.manual_seed(seed)
|
286 |
coords = self.sample_sparse_structure(cond, num_samples, sparse_structure_sampler_params)
|
@@ -355,6 +360,7 @@ class TrellisImageTo3DPipeline(Pipeline):
|
|
355 |
formats: List[str] = ['mesh', 'gaussian', 'radiance_field'],
|
356 |
preprocess_image: bool = True,
|
357 |
mode: Literal['stochastic', 'multidiffusion'] = 'stochastic',
|
|
|
358 |
remove_bg: bool = True,
|
359 |
) -> dict:
|
360 |
"""
|
@@ -368,7 +374,7 @@ class TrellisImageTo3DPipeline(Pipeline):
|
|
368 |
preprocess_image (bool): Whether to preprocess the image.
|
369 |
"""
|
370 |
if preprocess_image:
|
371 |
-
images = [self.preprocess_image(image,remove_bg=remove_bg) for image in images]
|
372 |
cond = self.get_cond(images)
|
373 |
cond['neg_cond'] = cond['neg_cond'][:1]
|
374 |
torch.manual_seed(seed)
|
|
|
87 |
Preprocess the input image.
|
88 |
"""
|
89 |
# if has alpha channel, use it directly; otherwise, remove background
|
90 |
+
aspect_ratio = int(input.width / input.height)
|
91 |
has_alpha = False
|
92 |
if input.mode == 'RGBA':
|
93 |
alpha = np.array(input)[:, :, 3]
|
|
|
115 |
size = max(bbox[2] - bbox[0], bbox[3] - bbox[1])
|
116 |
size = int(size * 1.2)
|
117 |
bbox = center[0] - size // 2, center[1] - size // 2, center[0] + size // 2, center[1] + size // 2
|
118 |
+
output = output.crop(bbox) # type: ignore
|
119 |
+
new_width = round((588 * aspect_ratio) / 14) * 14
|
120 |
+
output = output.resize((new_width, 588), Image.Resampling.LANCZOS)
|
121 |
output = np.array(output).astype(np.float32) / 255
|
122 |
output = output[:, :, :3] * output[:, :, 3:4]
|
123 |
output = Image.fromarray((output * 255).astype(np.uint8))
|
|
|
138 |
assert image.ndim == 4, "Image tensor should be batched (B, C, H, W)"
|
139 |
elif isinstance(image, list):
|
140 |
assert all(isinstance(i, Image.Image) for i in image), "Image list should be list of PIL images"
|
141 |
+
aspect_ratio = int(image[0].width / image[0].height)
|
142 |
+
new_width = round((588 * aspect_ratio) / 14) * 14
|
143 |
+
image = [i.resize((new_width, 588), Image.LANCZOS) for i in image]
|
144 |
image = [np.array(i.convert('RGB')).astype(np.float32) / 255 for i in image]
|
145 |
image = [torch.from_numpy(i).permute(2, 0, 1).float() for i in image]
|
146 |
image = torch.stack(image).to(self.device)
|
147 |
else:
|
148 |
raise ValueError(f"Unsupported type of image: {type(image)}")
|
149 |
+
|
150 |
image = self.image_cond_model_transform(image).to(self.device)
|
151 |
features = self.models['image_cond_model'](image, is_training=True)['x_prenorm']
|
152 |
patchtokens = F.layer_norm(features, features.shape[-1:])
|
|
|
271 |
slat_sampler_params: dict = {},
|
272 |
formats: List[str] = ['mesh', 'gaussian', 'radiance_field'],
|
273 |
preprocess_image: bool = True,
|
274 |
+
max_resolution: int =1024,
|
275 |
remove_bg: bool = True,
|
276 |
) -> dict:
|
277 |
"""
|
|
|
285 |
preprocess_image (bool): Whether to preprocess the image.
|
286 |
"""
|
287 |
if preprocess_image:
|
288 |
+
image = self.preprocess_image(image, max_resolution, remove_bg=remove_bg)
|
289 |
cond = self.get_cond([image])
|
290 |
torch.manual_seed(seed)
|
291 |
coords = self.sample_sparse_structure(cond, num_samples, sparse_structure_sampler_params)
|
|
|
360 |
formats: List[str] = ['mesh', 'gaussian', 'radiance_field'],
|
361 |
preprocess_image: bool = True,
|
362 |
mode: Literal['stochastic', 'multidiffusion'] = 'stochastic',
|
363 |
+
max_resolution: int =1024,
|
364 |
remove_bg: bool = True,
|
365 |
) -> dict:
|
366 |
"""
|
|
|
374 |
preprocess_image (bool): Whether to preprocess the image.
|
375 |
"""
|
376 |
if preprocess_image:
|
377 |
+
images = [self.preprocess_image(image, max_resolution, remove_bg=remove_bg) for image in images]
|
378 |
cond = self.get_cond(images)
|
379 |
cond['neg_cond'] = cond['neg_cond'][:1]
|
380 |
torch.manual_seed(seed)
|
utils/depth_estimation.py
CHANGED
@@ -9,7 +9,7 @@ from pathlib import Path
|
|
9 |
import logging
|
10 |
logging.getLogger("transformers.modeling_utils").setLevel(logging.ERROR)
|
11 |
from utils.image_utils import (
|
12 |
-
resize_image_with_aspect_ratio
|
13 |
)
|
14 |
from utils.constants import TMPDIR
|
15 |
from easydict import EasyDict as edict
|
|
|
9 |
import logging
|
10 |
logging.getLogger("transformers.modeling_utils").setLevel(logging.ERROR)
|
11 |
from utils.image_utils import (
|
12 |
+
resize_image_with_aspect_ratio, multiply_and_blend_images, open_image
|
13 |
)
|
14 |
from utils.constants import TMPDIR
|
15 |
from easydict import EasyDict as edict
|
utils/image_utils.py
CHANGED
@@ -4,6 +4,7 @@ from io import BytesIO
|
|
4 |
import cairosvg
|
5 |
import base64
|
6 |
import numpy as np
|
|
|
7 |
#from decimal import ROUND_CEILING
|
8 |
from PIL import Image, ImageChops, ImageDraw, ImageEnhance, ImageFilter, ImageDraw, ImageOps, ImageMath
|
9 |
from typing import List, Union, is_typeddict
|
@@ -363,18 +364,15 @@ def resize_image_with_aspect_ratio(image, target_width, target_height):
|
|
363 |
# Image is taller than target aspect ratio
|
364 |
new_height = target_height
|
365 |
new_width = int(target_height * original_aspect)
|
366 |
-
|
367 |
# Resize the image
|
368 |
resized_image = image.resize((new_width, new_height), Image.LANCZOS)
|
369 |
#print(f"Resized size: {resized_image.size}\n")
|
370 |
-
|
371 |
# Create a new image with target dimensions and black background
|
372 |
new_image = Image.new("RGB", (target_width, target_height), (0, 0, 0))
|
373 |
# Paste the resized image onto the center of the new image
|
374 |
paste_x = (target_width - new_width) // 2
|
375 |
paste_y = (target_height - new_height) // 2
|
376 |
new_image.paste(resized_image, (paste_x, paste_y))
|
377 |
-
|
378 |
return new_image
|
379 |
|
380 |
def lerp_imagemath(img1, img2, alpha_percent: int = 50):
|
@@ -463,10 +461,8 @@ def multiply_and_blend_images(base_image, image2, alpha_percent=50):
|
|
463 |
base_image = base_image.convert('RGBA')
|
464 |
image2 = image2.convert('RGBA')
|
465 |
image2 = image2.resize(base_image.size)
|
466 |
-
|
467 |
# Multiply the images
|
468 |
multiplied_image = ImageChops.multiply(base_image, image2)
|
469 |
-
|
470 |
# Blend the multiplied result with the original
|
471 |
blended_image = Image.blend(base_image, multiplied_image, alpha)
|
472 |
if name is not None:
|
@@ -1369,4 +1365,21 @@ def calculate_optimal_fill_dimensions(image: Image.Image):
|
|
1369 |
width = max(width, BASE_HEIGHT) if width == FIXED_DIMENSION else width
|
1370 |
height = max(height, BASE_HEIGHT) if height == FIXED_DIMENSION else height
|
1371 |
|
1372 |
-
return width, height
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
import cairosvg
|
5 |
import base64
|
6 |
import numpy as np
|
7 |
+
import rembg
|
8 |
#from decimal import ROUND_CEILING
|
9 |
from PIL import Image, ImageChops, ImageDraw, ImageEnhance, ImageFilter, ImageDraw, ImageOps, ImageMath
|
10 |
from typing import List, Union, is_typeddict
|
|
|
364 |
# Image is taller than target aspect ratio
|
365 |
new_height = target_height
|
366 |
new_width = int(target_height * original_aspect)
|
|
|
367 |
# Resize the image
|
368 |
resized_image = image.resize((new_width, new_height), Image.LANCZOS)
|
369 |
#print(f"Resized size: {resized_image.size}\n")
|
|
|
370 |
# Create a new image with target dimensions and black background
|
371 |
new_image = Image.new("RGB", (target_width, target_height), (0, 0, 0))
|
372 |
# Paste the resized image onto the center of the new image
|
373 |
paste_x = (target_width - new_width) // 2
|
374 |
paste_y = (target_height - new_height) // 2
|
375 |
new_image.paste(resized_image, (paste_x, paste_y))
|
|
|
376 |
return new_image
|
377 |
|
378 |
def lerp_imagemath(img1, img2, alpha_percent: int = 50):
|
|
|
461 |
base_image = base_image.convert('RGBA')
|
462 |
image2 = image2.convert('RGBA')
|
463 |
image2 = image2.resize(base_image.size)
|
|
|
464 |
# Multiply the images
|
465 |
multiplied_image = ImageChops.multiply(base_image, image2)
|
|
|
466 |
# Blend the multiplied result with the original
|
467 |
blended_image = Image.blend(base_image, multiplied_image, alpha)
|
468 |
if name is not None:
|
|
|
1365 |
width = max(width, BASE_HEIGHT) if width == FIXED_DIMENSION else width
|
1366 |
height = max(height, BASE_HEIGHT) if height == FIXED_DIMENSION else height
|
1367 |
|
1368 |
+
return width, height
|
1369 |
+
|
1370 |
+
|
1371 |
+
def combine_depth_map_with_image_path(image_path, depth_map_path, output_path, alpha: int= 95) -> str:
|
1372 |
+
image =open_image(image_path)
|
1373 |
+
depth_map = open_image(depth_map_path)
|
1374 |
+
image = image.resize(depth_map.size)
|
1375 |
+
depth_map = depth_map.convert("RGBA")
|
1376 |
+
depth_no_background = rembg.remove(depth_map, session = rembg.new_session('u2net'))
|
1377 |
+
overlay = Image.blend(image,depth_no_background, alpha= (alpha / 100))
|
1378 |
+
overlay.save(output_path)
|
1379 |
+
return output_path
|
1380 |
+
|
1381 |
+
def combine_depth_map_with_Image(image:Image, depth_img:Image, width:int, height:int, alpha: int= 95, rembg_session_name: str ='u2net') -> Image:
|
1382 |
+
resized_depth_image = resize_image_with_aspect_ratio(depth_img, width, height)
|
1383 |
+
depth_no_background = rembg.remove(resized_depth_image, session = rembg.new_session(rembg_session_name))
|
1384 |
+
combined_depth_img = multiply_and_blend_images(image, depth_no_background, (alpha / 100))
|
1385 |
+
return combined_depth_img
|