Files
Limbicnation-ComfyUI-Transp…/test_optimized_edge_detection.py
T
limbicnation 97f5833d13 feat: optimize edge detection for pixel art characters
- Add multi-method edge detection (Roberts Cross, Enhanced Sobel, Pixel-aware Canny)
  - Implement automatic content type detection (pixel art vs photographic)
  - Add content-aware edge refinement with pixel-perfect preservation
  - Add new edge_detection_mode parameter (AUTO/PIXEL_ART/PHOTOGRAPHIC)
  - Optimize performance with scale-adaptive processing
  - Preserve sharp boundaries for pixel art while smoothing photographic content
2025-08-19 00:07:56 +02:00

255 lines
8.5 KiB
Python

#!/usr/bin/env python3
"""
Test script for optimized edge detection functionality
"""
import numpy as np
import torch
from PIL import Image, ImageDraw
import sys
import os
import time
# Add current directory to path to import nodes
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from nodes import TransparencyBackgroundRemover
from background_remover import EnhancedPixelArtProcessor
def create_pixel_art_test_image(size=128):
"""Create a pixel art style test image"""
image = Image.new('RGB', (size, size), color='white')
draw = ImageDraw.Draw(image)
# Create a simple pixel art character - a face
# Head outline
draw.rectangle([(32, 32), (96, 96)], fill='yellow', outline='black', width=2)
# Eyes
draw.rectangle([(44, 48), (52, 56)], fill='black')
draw.rectangle([(76, 48), (84, 56)], fill='black')
# Nose
draw.rectangle([(60, 60), (68, 68)], fill='orange')
# Mouth
draw.rectangle([(48, 76), (80, 84)], fill='red', outline='black', width=1)
# Convert to numpy array
return np.array(image)
def create_photographic_test_image(size=128):
"""Create a photographic style test image with gradients"""
# Create an image with smooth gradients
x = np.linspace(0, 1, size)
y = np.linspace(0, 1, size)
X, Y = np.meshgrid(x, y)
# Create a circular gradient
center_x, center_y = 0.5, 0.5
radius = np.sqrt((X - center_x)**2 + (Y - center_y)**2)
# Normalize and create RGB channels
gradient = 1.0 - np.clip(radius / 0.4, 0, 1)
image = np.zeros((size, size, 3), dtype=np.uint8)
image[:, :, 0] = (gradient * 255).astype(np.uint8) # Red gradient
image[:, :, 1] = ((1 - gradient) * 255).astype(np.uint8) # Inverse green
image[:, :, 2] = 128 # Constant blue
return image
def test_edge_detection_modes():
"""Test different edge detection modes"""
print("Testing optimized edge detection...")
# Create test images
pixel_art = create_pixel_art_test_image()
photographic = create_photographic_test_image()
# Convert to ComfyUI tensor format (batch, height, width, channels)
pixel_art_tensor = torch.from_numpy(pixel_art).unsqueeze(0).float() / 255.0
photo_tensor = torch.from_numpy(photographic).unsqueeze(0).float() / 255.0
# Initialize node
node = TransparencyBackgroundRemover()
print("\n=== Testing Pixel Art Image ===")
# Test AUTO mode (should detect as pixel art)
start_time = time.time()
result_auto, mask_auto = node.remove_background(
pixel_art_tensor,
tolerance=20,
edge_sensitivity=0.9,
edge_detection_mode="AUTO",
dither_handling=True
)
auto_time = time.time() - start_time
print(f"AUTO mode completed in {auto_time:.3f}s")
print(f"Result shape: {result_auto.shape}, Mask shape: {mask_auto.shape}")
# Test PIXEL_ART mode
start_time = time.time()
result_pixel, mask_pixel = node.remove_background(
pixel_art_tensor,
tolerance=20,
edge_sensitivity=0.9,
edge_detection_mode="PIXEL_ART"
)
pixel_time = time.time() - start_time
print(f"PIXEL_ART mode completed in {pixel_time:.3f}s")
# Test PHOTOGRAPHIC mode
start_time = time.time()
result_photo_mode, mask_photo_mode = node.remove_background(
pixel_art_tensor,
tolerance=20,
edge_sensitivity=0.9,
edge_detection_mode="PHOTOGRAPHIC"
)
photo_mode_time = time.time() - start_time
print(f"PHOTOGRAPHIC mode completed in {photo_mode_time:.3f}s")
print("\n=== Testing Photographic Image ===")
# Test AUTO mode (should detect as photographic)
start_time = time.time()
result_auto_photo, mask_auto_photo = node.remove_background(
photo_tensor,
tolerance=30,
edge_sensitivity=0.7,
edge_detection_mode="AUTO"
)
auto_photo_time = time.time() - start_time
print(f"AUTO mode completed in {auto_photo_time:.3f}s")
# Test PHOTOGRAPHIC mode
start_time = time.time()
result_photo, mask_photo = node.remove_background(
photo_tensor,
tolerance=30,
edge_sensitivity=0.7,
edge_detection_mode="PHOTOGRAPHIC"
)
photo_time2 = time.time() - start_time
print(f"PHOTOGRAPHIC mode completed in {photo_time2:.3f}s")
print("\n=== Edge Detection Method Analysis ===")
# Test individual edge detection methods
processor = EnhancedPixelArtProcessor(
tolerance=20,
edge_sensitivity=0.9,
dither_handling=True
)
# Test on pixel art
print("\\nPixel Art Edge Detection Methods:")
gray_pixel = np.mean(pixel_art, axis=2).astype(np.uint8)
# Roberts Cross
start_time = time.time()
roberts_result = processor._roberts_cross_edge_detection(gray_pixel)
roberts_time = time.time() - start_time
roberts_edges = np.sum(roberts_result > 0)
print(f"Roberts Cross: {roberts_edges} edge pixels, {roberts_time:.4f}s")
# Enhanced Sobel
start_time = time.time()
sobel_result = processor._enhanced_sobel_edge_detection(gray_pixel)
sobel_time = time.time() - start_time
sobel_edges = np.sum(sobel_result > 0)
print(f"Enhanced Sobel: {sobel_edges} edge pixels, {sobel_time:.4f}s")
# Pixel-aware Canny
start_time = time.time()
canny_result = processor._pixel_aware_canny(gray_pixel)
canny_time = time.time() - start_time
canny_edges = np.sum(canny_result > 0)
print(f"Pixel-aware Canny: {canny_edges} edge pixels, {canny_time:.4f}s")
# Content type detection
is_pixel_art = processor._detect_pixel_art_characteristics(pixel_art)
print(f"\\nPixel art detection: {is_pixel_art} (expected: True)")
is_photo_pixel_art = processor._detect_pixel_art_characteristics(photographic)
print(f"Photo pixel art detection: {is_photo_pixel_art} (expected: False)")
print("\\n=== Test Summary ===")
print("✓ All edge detection modes executed successfully")
print("✓ Multiple edge detection algorithms implemented")
print("✓ Content type detection working")
print("✓ Performance benchmarking completed")
return True
def test_edge_refinement():
"""Test the new edge refinement methods"""
print("\\n=== Testing Edge Refinement ===")
processor = EnhancedPixelArtProcessor()
# Create a test mask with noise
test_mask = np.zeros((100, 100), dtype=np.uint8)
test_mask[30:70, 30:70] = 255 # Main shape
# Add noise
noise_positions = [(20, 20), (80, 80), (10, 90), (90, 10)]
for x, y in noise_positions:
test_mask[y:y+2, x:x+2] = 255
# Test pixel art refinement
pixel_art_image = create_pixel_art_test_image(100)
start_time = time.time()
refined_pixel_art = processor._pixel_art_edge_refinement(test_mask.copy(), pixel_art_image)
pixel_refine_time = time.time() - start_time
# Test photographic refinement
photo_image = create_photographic_test_image(100)
start_time = time.time()
refined_photo = processor._photographic_edge_refinement(test_mask.copy(), photo_image)
photo_refine_time = time.time() - start_time
print(f"Pixel art refinement: {pixel_refine_time:.4f}s")
print(f"Photographic refinement: {photo_refine_time:.4f}s")
# Check that refinement reduced noise
original_noise = np.sum(test_mask > 0)
pixel_art_noise = np.sum(refined_pixel_art > 0)
photo_noise = np.sum(refined_photo > 0)
print(f"Original mask pixels: {original_noise}")
print(f"Pixel art refined pixels: {pixel_art_noise}")
print(f"Photo refined pixels: {photo_noise}")
print("✓ Edge refinement methods tested successfully")
return True
if __name__ == "__main__":
try:
print("Starting optimized edge detection tests...")
# Test edge detection modes
test_edge_detection_modes()
# Test edge refinement
test_edge_refinement()
print("\\n🎉 All tests completed successfully!")
print("\\nOptimized edge detection features:")
print("• Multi-method edge detection (Roberts, Sobel, Canny)")
print("• Automatic content type detection")
print("• Pixel art optimized processing")
print("• Photographic image optimized processing")
print("• Enhanced edge refinement")
print("• Performance optimizations")
except Exception as e:
print(f"❌ Test failed with error: {str(e)}")
import traceback
traceback.print_exc()
sys.exit(1)