SpacelyJohn commited on
Commit
042bccd
Β·
verified Β·
1 Parent(s): 3cd786b

Upload 14 files

Browse files
__pycache__/app_gradio.cpython-313.pyc CHANGED
Binary files a/__pycache__/app_gradio.cpython-313.pyc and b/__pycache__/app_gradio.cpython-313.pyc differ
 
app_gradio.py CHANGED
@@ -521,14 +521,107 @@ def create_layered_furniture_mask(image):
521
 
522
  # Keep the old function for compatibility
523
  def create_precise_furniture_mask(image):
524
- """Legacy function - redirects to layered approach"""
525
- return create_layered_furniture_mask(image)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
527
  def get_prompt_preview(room_type, design_style, inpainting_mode):
528
  """Generate preview of prompt and negative prompt that will be used"""
529
 
530
  # Create positive prompt based on mode
531
- if inpainting_mode == "smart":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
532
  # Simple, direct furniture prompt for smart mode
533
  if room_type == "Living Room":
534
  furniture_items = "sofa, coffee table, side tables, floor lamp, dining table with chairs"
@@ -545,18 +638,185 @@ def get_prompt_preview(room_type, design_style, inpainting_mode):
545
  else:
546
  furniture_items = "appropriate furniture"
547
 
548
- positive_prompt = f"LAYERED FURNITURE DESIGN: add {furniture_items}, {design_style.lower()} style, photorealistic, place furniture naturally on floor and against walls, add wall decorations like artwork and shelves, preserve existing room structure, no structural changes to walls windows or ceiling, layer furniture over existing surfaces, professional interior design, ultra-realistic lighting and shadows"
549
  else:
550
  # Get detailed template-based prompt for full mode
551
  detailed_prompt = DETAILED_PROMPTS.get((room_type, design_style),
552
  DETAILED_PROMPTS[("Living Room", "Modern")])
553
  positive_prompt = f"photorealistic interior design, {detailed_prompt}, keep existing windows unchanged, preserve original window placement, professionally photographed, architectural photography, natural lighting, ultra-realistic, high resolution, sharp focus, interior design magazine quality, realistic textures, realistic materials"
554
 
555
- # LAYERED DESIGN negative prompt
556
- negative_prompt = "STRUCTURAL REPLACEMENT FORBIDDEN: changing wall color, different wall texture, new walls, removing walls, changing ceiling, different ceiling, new windows, different windows, removing windows, changing floor material, different floor, PRESERVE STRUCTURE: keep original room architecture, floating furniture, unrealistic placement, furniture in ceiling, lowres, watermark, banner, logo, contactinfo, text, deformed, blurry, blur, out of focus, surreal, ugly"
 
 
 
 
 
557
 
558
  return positive_prompt, negative_prompt
559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  def post_process_blend(original, generated):
561
  """Post-process to reduce seam artifacts between original and generated areas"""
562
  from PIL import ImageFilter
@@ -642,7 +902,15 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
642
  mlsd_image = resized_image.copy()
643
 
644
  # Create mask based on selected mode
645
- if inpainting_mode == "smart":
 
 
 
 
 
 
 
 
646
  # Use precise smart mask for furniture-only placement
647
  mask_image = create_precise_furniture_mask(resized_image)
648
 
@@ -662,7 +930,7 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
662
  else:
663
  furniture_items = "appropriate furniture"
664
 
665
- prompt = f"add {furniture_items} to this room, {design_style.lower()} style furniture, photorealistic, keep all walls ceiling floor windows unchanged, preserve all existing room structure, only add furniture objects on the floor, do not modify room architecture, professional interior design, ultra-realistic, high quality"
666
  print(f"Smart mode prompt: {prompt}")
667
  else:
668
  mask_image = create_full_mask(resized_image)
@@ -671,8 +939,8 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
671
 
672
  # Generate image with optimized strength for furniture generation
673
  if inpainting_mode == "smart":
674
- # Higher strength for better furniture generation in smart mode
675
- actual_strength = min(0.85, float(strength) * 1.1) # Boost by 10%, cap at 0.85
676
  else:
677
  actual_strength = float(strength)
678
 
@@ -685,16 +953,16 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
685
 
686
  result = pipe(
687
  prompt=prompt,
688
- negative_prompt="lowres, watermark, banner, logo, watermark, contactinfo, text, deformed, blurry, blur, out of focus, out of frame, surreal, extra, ugly, upholstered walls, fabric walls, plush walls, mirror, mirrored, functional, realistic, new windows, extra windows, additional windows, changing windows, modifying windows, different windows, window alterations, removing windows, changing walls, modifying walls, different walls, new walls, changing ceiling, modifying ceiling, different ceiling, changing floor, modifying floor, different floor, structural changes, architectural changes, room alterations",
689
  num_inference_steps=int(num_steps),
690
  strength=actual_strength,
691
  guidance_scale=float(guidance_scale),
692
  image=resized_image,
693
  mask_image=mask_image,
694
  control_image=[seg_control, mlsd_image],
695
- controlnet_conditioning_scale=[0.4, 0.2],
696
- control_guidance_start=[0, 0.1],
697
- control_guidance_end=[0.5, 0.25],
698
  ).images[0]
699
 
700
  # Restore original size
@@ -745,9 +1013,10 @@ def create_interface():
745
  inpainting_mode = gr.Radio(
746
  choices=[
747
  ("Complete Room Redesign", "full"),
748
- ("Add Furniture Only (Preserve Walls)", "smart")
 
749
  ],
750
- value="smart",
751
  label="🎨 Design Mode",
752
  info="Choose how to modify your image"
753
  )
@@ -758,12 +1027,12 @@ def create_interface():
758
  label="Number of denoising steps"
759
  )
760
  guidance_scale = gr.Slider(
761
- minimum=1, maximum=50, value=18, step=0.5,
762
- label="Scale for classifier-free guidance"
763
  )
764
  strength = gr.Slider(
765
- minimum=0, maximum=1, value=0.8, step=0.05,
766
- label="Prompt strength for inpainting"
767
  )
768
 
769
  generate_btn = gr.Button("🎨 Generate Design", variant="primary", size="lg")
 
521
 
522
  # Keep the old function for compatibility
523
  def create_precise_furniture_mask(image):
524
+ """Create ultra-conservative mask that ONLY targets floor center - preserves ALL walls and windows"""
525
+ import cv2
526
+
527
+ print("🎯 Creating ULTRA-CONSERVATIVE furniture mask...")
528
+
529
+ img_array = np.array(image)
530
+ h, w = img_array.shape[:2]
531
+ gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
532
+
533
+ # Create conservative mask - ONLY center floor area
534
+ mask = np.zeros((h, w), dtype=np.uint8)
535
+
536
+ # ULTRA CONSERVATIVE: Only center 30% of image, bottom 40% (floor only)
537
+ safe_x_start = int(w * 0.35) # 35% from left
538
+ safe_x_end = int(w * 0.65) # 35% from right
539
+ safe_y_start = int(h * 0.6) # 60% from top (avoid walls/windows)
540
+ safe_y_end = int(h * 0.85) # 15% from bottom
541
+
542
+ # Create small circular mask in safe center floor area
543
+ center_x, center_y = w // 2, int(h * 0.72) # Lower center for floor
544
+
545
+ # SMALL ellipse parameters - very conservative
546
+ ellipse_w = int(w * 0.18) # Only 18% of width (very small area)
547
+ ellipse_h = int(h * 0.15) # Only 15% of height (very small area)
548
+
549
+ # Draw small ellipse mask
550
+ Y, X = np.ogrid[:h, :w]
551
+ ellipse_mask = ((X - center_x) / ellipse_w) ** 2 + ((Y - center_y) / ellipse_h) ** 2 <= 1
552
+
553
+ # Apply soft gradient within ellipse - strong at center, fade at edges
554
+ for y in range(h):
555
+ for x in range(w):
556
+ if ellipse_mask[y, x]:
557
+ # Distance from center
558
+ dist = np.sqrt(((x - center_x) / ellipse_w) ** 2 + ((y - center_y) / ellipse_h) ** 2)
559
+ # Very conservative gradient
560
+ strength = max(0, (1 - dist) ** 2) * 200 # Softer, max 200 not 255
561
+ mask[y, x] = int(strength)
562
+
563
+ # HARD EXCLUSIONS - absolutely no modification near walls/windows
564
+
565
+ # Exclude all bright areas (windows) completely
566
+ windows = gray > 180 # Lower threshold to catch more window areas
567
+ mask[windows] = 0
568
+
569
+ # Exclude all dark areas (corners/shadows)
570
+ dark_areas = gray < 60
571
+ mask[dark_areas] = 0
572
+
573
+ # Exclude outer 25% of image (wall areas)
574
+ wall_margin = 0.25
575
+ mask[:int(h*wall_margin), :] = 0 # Top 25%
576
+ mask[-int(h*wall_margin):, :] = 0 # Bottom 25%
577
+ mask[:, :int(w*wall_margin)] = 0 # Left 25%
578
+ mask[:, -int(w*wall_margin):] = 0 # Right 25%
579
+
580
+ # Exclude top 50% completely (ceiling/wall area)
581
+ mask[:int(h*0.5), :] = 0
582
+
583
+ # Apply strong blur for very smooth transitions
584
+ mask = cv2.GaussianBlur(mask, (31, 31), 0)
585
+
586
+ # Final safety check - make sure mask is very conservative
587
+ mask = np.clip(mask, 0, 150) # Lower maximum intensity
588
+
589
+ # Statistics
590
+ furniture_pixels = np.count_nonzero(mask)
591
+ coverage = (furniture_pixels / (h * w)) * 100
592
+
593
+ print(f"πŸ›‘οΈ ULTRA-CONSERVATIVE mask stats:")
594
+ print(f" - Total coverage: {furniture_pixels} pixels ({coverage:.1f}%)")
595
+ print(f" - Max intensity: {mask.max()}")
596
+ print(f" - Center: ({center_x}, {center_y}), Size: {ellipse_w}x{ellipse_h}")
597
+ print(f" - Coverage should be < 15% for wall preservation")
598
+
599
+ return Image.fromarray(mask).convert("RGB")
600
 
601
  def get_prompt_preview(room_type, design_style, inpainting_mode):
602
  """Generate preview of prompt and negative prompt that will be used"""
603
 
604
  # Create positive prompt based on mode
605
+ if inpainting_mode == "layered":
606
+ # Layered furniture generation
607
+ if room_type == "Living Room":
608
+ furniture_items = "modern sofa, coffee table, side table, floor lamp"
609
+ elif room_type == "Bedroom" or room_type == "Master Bedroom":
610
+ furniture_items = "bed with headboard, two nightstands, dresser"
611
+ elif room_type == "Kitchen":
612
+ furniture_items = "kitchen island, bar stools"
613
+ elif room_type == "Dining Room":
614
+ furniture_items = "dining table, dining chairs"
615
+ elif room_type == "Home Office":
616
+ furniture_items = "desk, office chair, bookshelf"
617
+ elif room_type == "Bathroom":
618
+ furniture_items = "vanity, mirror, storage cabinet"
619
+ else:
620
+ furniture_items = "appropriate furniture"
621
+
622
+ positive_prompt = f"LAYERED APPROACH: same room layout, preserve perspective, layout preserving realistic interior design - Generate realistic {furniture_items}, {design_style.lower()} style, photorealistic furniture placement, maintain room proportions, professional furniture photography, clean lighting, realistic materials and shadows"
623
+
624
+ elif inpainting_mode == "smart":
625
  # Simple, direct furniture prompt for smart mode
626
  if room_type == "Living Room":
627
  furniture_items = "sofa, coffee table, side tables, floor lamp, dining table with chairs"
 
638
  else:
639
  furniture_items = "appropriate furniture"
640
 
641
+ positive_prompt = f"FURNITURE ONLY: add {furniture_items} on floor center, {design_style.lower()} style, photorealistic furniture objects, PRESERVE: keep all walls unchanged, keep ceiling unchanged, keep floor color unchanged, keep window unchanged, no structural changes, no wall modifications, only place furniture objects in room center, professional furniture placement, realistic shadows"
642
  else:
643
  # Get detailed template-based prompt for full mode
644
  detailed_prompt = DETAILED_PROMPTS.get((room_type, design_style),
645
  DETAILED_PROMPTS[("Living Room", "Modern")])
646
  positive_prompt = f"photorealistic interior design, {detailed_prompt}, keep existing windows unchanged, preserve original window placement, professionally photographed, architectural photography, natural lighting, ultra-realistic, high resolution, sharp focus, interior design magazine quality, realistic textures, realistic materials"
647
 
648
+ # Updated negative prompt
649
+ if inpainting_mode == "layered":
650
+ negative_prompt = "distortion, warped structure, perspective distortion, room layout changes, architectural changes, structural modifications, empty room, no furniture, floating furniture, unrealistic placement, bad proportions, distorted furniture, warped perspective, gray background, neutral background, plain background, lowres, watermark, blurry, deformed"
651
+ elif inpainting_mode == "smart":
652
+ negative_prompt = "FORBIDDEN CHANGES: changing walls, different wall color, wall texture changes, new wall paint, different walls, wall modifications, changing windows, different window, new windows, window alterations, changing ceiling, different ceiling, ceiling changes, changing floor, different floor material, floor changes, structural modifications, architectural changes, room alterations, wall decorations, wall art, curtains, blinds, wall shelves, wall mounted items, lowres, watermark, blurry, deformed, floating furniture, unrealistic placement"
653
+ else:
654
+ negative_prompt = "STRUCTURAL REPLACEMENT FORBIDDEN: changing wall color, different wall texture, new walls, removing walls, changing ceiling, different ceiling, new windows, different windows, removing windows, changing floor material, different floor, PRESERVE STRUCTURE: keep original room architecture, floating furniture, unrealistic placement, furniture in ceiling, lowres, watermark, banner, logo, contactinfo, text, deformed, blurry, blur, out of focus, surreal, ugly"
655
 
656
  return positive_prompt, negative_prompt
657
 
658
+ def generate_furniture_layer(original_image, room_type, design_style, num_steps, guidance_scale, strength):
659
+ """Generate furniture objects using neutral background, then extract for layering"""
660
+ global pipe, seg_processor, seg_model, mlsd_processor
661
+
662
+ print("πŸͺ‘ Generating furniture layer...")
663
+
664
+ # Create neutral gray background same size as original for furniture generation
665
+ w, h = original_image.size
666
+ neutral_bg = Image.new('RGB', (w, h), (128, 128, 128)) # Neutral gray
667
+
668
+ # Create furniture mask (center area only)
669
+ furniture_mask = create_precise_furniture_mask(neutral_bg)
670
+
671
+ # Create furniture prompt
672
+ if room_type == "Living Room":
673
+ furniture_items = "modern sofa, coffee table, side table, floor lamp"
674
+ elif room_type == "Bedroom":
675
+ furniture_items = "bed with headboard, two nightstands, dresser"
676
+ elif room_type == "Kitchen":
677
+ furniture_items = "kitchen island, bar stools"
678
+ elif room_type == "Dining Room":
679
+ furniture_items = "dining table, dining chairs"
680
+ elif room_type == "Home Office":
681
+ furniture_items = "desk, office chair, bookshelf"
682
+ else:
683
+ furniture_items = "appropriate furniture"
684
+
685
+ furniture_prompt = f"same room layout, preserve perspective, layout preserving realistic interior design: {furniture_items}, {design_style.lower()} style, photorealistic furniture placement, natural floor positioning, professional furniture photography, clean professional lighting, realistic materials and textures, high quality furniture catalog, maintain room proportions, realistic shadows and reflections"
686
+
687
+ # Generate furniture on neutral background
688
+ try:
689
+ if pipe is None:
690
+ print("❌ Pipeline not loaded")
691
+ return Image.new('RGBA', (w, h), (0, 0, 0, 0))
692
+
693
+ # Resize for processing
694
+ max_size = 768
695
+ if max(w, h) > max_size:
696
+ if w > h:
697
+ new_w, new_h = max_size, int(max_size * h / w)
698
+ else:
699
+ new_w, new_h = int(max_size * w / h), max_size
700
+ else:
701
+ new_w, new_h = w, h
702
+
703
+ resized_neutral = neutral_bg.resize((new_w, new_h))
704
+ resized_mask = furniture_mask.resize((new_w, new_h))
705
+
706
+ # Generate furniture with inpainting
707
+ seg_control = resized_neutral.copy()
708
+ mlsd_image = resized_neutral.copy()
709
+
710
+ # Optimized parameters based on user feedback
711
+ optimized_guidance = max(7.0, min(10.0, float(guidance_scale))) # Clamp 7-10
712
+ optimized_strength = max(0.4, min(0.6, float(strength))) # Clamp 0.4-0.6
713
+
714
+ result = pipe(
715
+ prompt=furniture_prompt,
716
+ negative_prompt="distortion, warped structure, perspective distortion, room layout changes, architectural changes, structural modifications, empty room, no furniture, floating furniture, unrealistic placement, bad proportions, distorted furniture, warped perspective",
717
+ num_inference_steps=int(num_steps),
718
+ strength=optimized_strength, # Optimized strength range
719
+ guidance_scale=optimized_guidance, # Optimized guidance range
720
+ image=resized_neutral,
721
+ mask_image=resized_mask,
722
+ control_image=[seg_control, mlsd_image],
723
+ controlnet_conditioning_scale=[0.5, 0.3], # Stronger control for layout preservation
724
+ control_guidance_start=[0, 0],
725
+ control_guidance_end=[0.7, 0.5], # Extended guidance for better control
726
+ ).images[0]
727
+
728
+ # Restore original size
729
+ furniture_generated = result.resize((w, h), Image.Resampling.LANCZOS)
730
+
731
+ print("βœ… Furniture generated on neutral background")
732
+ return furniture_generated
733
+
734
+ except Exception as e:
735
+ print(f"❌ Furniture layer generation failed: {e}")
736
+ return Image.new('RGBA', (w, h), (0, 0, 0, 0))
737
+
738
+ def extract_furniture_from_generated(furniture_generated, original_neutral_bg):
739
+ """Extract furniture from generated image by removing neutral background"""
740
+ import cv2
741
+
742
+ print("βœ‚οΈ Extracting furniture from generated image...")
743
+
744
+ # Convert to numpy arrays
745
+ furniture_array = np.array(furniture_generated)
746
+ neutral_array = np.array(original_neutral_bg)
747
+
748
+ h, w = furniture_array.shape[:2]
749
+
750
+ # Create mask for furniture areas (areas that changed from neutral gray)
751
+ # Neutral gray is (128, 128, 128)
752
+ gray_tolerance = 30
753
+
754
+ # Calculate difference from neutral gray
755
+ diff = np.abs(furniture_array.astype(np.float32) - 128.0)
756
+ diff_magnitude = np.sqrt(np.sum(diff**2, axis=2))
757
+
758
+ # Create furniture mask - areas significantly different from gray
759
+ furniture_mask = diff_magnitude > gray_tolerance
760
+
761
+ # Refine mask - remove small noise
762
+ kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
763
+ furniture_mask = cv2.morphologyEx(furniture_mask.astype(np.uint8), cv2.MORPH_OPEN, kernel)
764
+ furniture_mask = cv2.morphologyEx(furniture_mask, cv2.MORPH_CLOSE, kernel)
765
+
766
+ # Create RGBA image with transparency
767
+ furniture_rgba = np.zeros((h, w, 4), dtype=np.uint8)
768
+ furniture_rgba[:, :, :3] = furniture_array # Copy RGB
769
+ furniture_rgba[:, :, 3] = furniture_mask * 255 # Alpha channel
770
+
771
+ # Apply gaussian blur to alpha for smoother edges
772
+ furniture_rgba[:, :, 3] = cv2.GaussianBlur(furniture_rgba[:, :, 3], (3, 3), 0)
773
+
774
+ furniture_layer = Image.fromarray(furniture_rgba, 'RGBA')
775
+
776
+ print(f"βœ… Extracted furniture layer with {np.count_nonzero(furniture_mask)} furniture pixels")
777
+
778
+ return furniture_layer
779
+
780
+ def composite_layers(background, furniture_generated, furniture_mask=None):
781
+ """Composite furniture layer onto background with realistic placement"""
782
+ print("🎨 Compositing layers...")
783
+
784
+ # Step 1: Extract furniture from generated image
785
+ neutral_bg = Image.new('RGB', background.size, (128, 128, 128))
786
+ furniture_layer = extract_furniture_from_generated(furniture_generated, neutral_bg)
787
+
788
+ # Step 2: Composite furniture onto original background
789
+ if background.mode != 'RGBA':
790
+ background = background.convert('RGBA')
791
+
792
+ # Alpha composite
793
+ result = Image.alpha_composite(background, furniture_layer)
794
+
795
+ # Convert back to RGB
796
+ final = Image.new('RGB', result.size, (255, 255, 255))
797
+ final.paste(result, mask=result.split()[-1])
798
+
799
+ return final
800
+
801
+ def create_layered_design(input_image, room_type, design_style, num_steps, guidance_scale, strength):
802
+ """LAYERED APPROACH: Generate furniture separately and composite onto preserved background"""
803
+ print("πŸ—οΈ Starting layered design generation...")
804
+ print(f"πŸ“Š Optimized parameters - Guidance: {guidance_scale} β†’ {max(7.0, min(10.0, float(guidance_scale)))}, Strength: {strength} β†’ {max(0.4, min(0.6, float(strength)))}")
805
+
806
+ # Step 1: Preserve original background completely
807
+ background_layer = input_image.copy()
808
+ print("βœ… Background layer preserved")
809
+
810
+ # Step 2: Generate furniture objects separately
811
+ furniture_layer = generate_furniture_layer(input_image, room_type, design_style, num_steps, guidance_scale, strength)
812
+ print("βœ… Furniture layer generated")
813
+
814
+ # Step 3: Composite layers
815
+ final_image = composite_layers(background_layer, furniture_layer)
816
+ print("βœ… Layers composited")
817
+
818
+ return final_image
819
+
820
  def post_process_blend(original, generated):
821
  """Post-process to reduce seam artifacts between original and generated areas"""
822
  from PIL import ImageFilter
 
902
  mlsd_image = resized_image.copy()
903
 
904
  # Create mask based on selected mode
905
+ if inpainting_mode == "layered":
906
+ # Use new layered approach
907
+ final_image = create_layered_design(resized_image, room_type, design_style, num_steps, guidance_scale, strength)
908
+ # Restore original size
909
+ final_image = final_image.resize((orig_w, orig_h), Image.Resampling.LANCZOS)
910
+ success_msg = f"βœ… Layered {room_type} in {design_style} style completed!"
911
+ return final_image, success_msg
912
+
913
+ elif inpainting_mode == "smart":
914
  # Use precise smart mask for furniture-only placement
915
  mask_image = create_precise_furniture_mask(resized_image)
916
 
 
930
  else:
931
  furniture_items = "appropriate furniture"
932
 
933
+ prompt = f"FURNITURE ONLY: add {furniture_items} on floor center, {design_style.lower()} style, photorealistic furniture objects, PRESERVE: keep all walls unchanged, keep ceiling unchanged, keep floor color unchanged, keep window unchanged, no structural changes, no wall modifications, only place furniture objects in room center, professional furniture placement, realistic shadows"
934
  print(f"Smart mode prompt: {prompt}")
935
  else:
936
  mask_image = create_full_mask(resized_image)
 
939
 
940
  # Generate image with optimized strength for furniture generation
941
  if inpainting_mode == "smart":
942
+ # Lower strength for better structure preservation in smart mode
943
+ actual_strength = min(0.65, float(strength) * 0.8) # Reduce by 20%, cap at 0.65
944
  else:
945
  actual_strength = float(strength)
946
 
 
953
 
954
  result = pipe(
955
  prompt=prompt,
956
+ negative_prompt="FORBIDDEN CHANGES: changing walls, different wall color, wall texture changes, new wall paint, different walls, wall modifications, changing windows, different window, new windows, window alterations, changing ceiling, different ceiling, ceiling changes, changing floor, different floor material, floor changes, structural modifications, architectural changes, room alterations, wall decorations, wall art, curtains, blinds, wall shelves, wall mounted items, lowres, watermark, blurry, deformed, floating furniture, unrealistic placement",
957
  num_inference_steps=int(num_steps),
958
  strength=actual_strength,
959
  guidance_scale=float(guidance_scale),
960
  image=resized_image,
961
  mask_image=mask_image,
962
  control_image=[seg_control, mlsd_image],
963
+ controlnet_conditioning_scale=[0.8, 0.6] if inpainting_mode == "smart" else [0.4, 0.2],
964
+ control_guidance_start=[0, 0] if inpainting_mode == "smart" else [0, 0.1],
965
+ control_guidance_end=[0.9, 0.8] if inpainting_mode == "smart" else [0.5, 0.25],
966
  ).images[0]
967
 
968
  # Restore original size
 
1013
  inpainting_mode = gr.Radio(
1014
  choices=[
1015
  ("Complete Room Redesign", "full"),
1016
+ ("Add Furniture Only (Preserve Walls)", "smart"),
1017
+ ("πŸ†• Layered Furniture (Background + Furniture Overlay)", "layered")
1018
  ],
1019
+ value="layered",
1020
  label="🎨 Design Mode",
1021
  info="Choose how to modify your image"
1022
  )
 
1027
  label="Number of denoising steps"
1028
  )
1029
  guidance_scale = gr.Slider(
1030
+ minimum=1, maximum=50, value=8, step=0.5,
1031
+ label="Scale for classifier-free guidance (7-10 optimal for Layered mode)"
1032
  )
1033
  strength = gr.Slider(
1034
+ minimum=0, maximum=1, value=0.5, step=0.05,
1035
+ label="Prompt strength for inpainting (0.4-0.6 optimal for Layered mode)"
1036
  )
1037
 
1038
  generate_btn = gr.Button("🎨 Generate Design", variant="primary", size="lg")