jbilcke-hf HF Staff commited on
Commit
74087f2
·
verified ·
1 Parent(s): 52b0587

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -37
app.py CHANGED
@@ -82,24 +82,30 @@ class GPUSatelliteModelGenerator:
82
 
83
  @staticmethod
84
  def gpu_color_distance_hsv(pixel_hsv, reference_hsv, tolerance):
85
- """GPU-accelerated HSV color distance calculation"""
86
  pixel_h = pixel_hsv[0] * 2
87
  pixel_s = pixel_hsv[1] / 255
88
  pixel_v = pixel_hsv[2] / 255
89
 
 
90
  hue_diff = cp.minimum(cp.abs(pixel_h - reference_hsv[0]),
91
- 360 - cp.abs(pixel_h - reference_hsv[0]))
 
 
92
  sat_diff = cp.abs(pixel_s - reference_hsv[1])
93
  val_diff = cp.abs(pixel_v - reference_hsv[2])
94
 
 
95
  return cp.logical_and(
96
- cp.logical_and(hue_diff <= tolerance['hue'],
97
- sat_diff <= tolerance['sat']),
 
 
98
  val_diff <= tolerance['val']
99
  )
100
 
101
  def segment_image_gpu(self, img):
102
- """GPU-accelerated image segmentation"""
103
  # Transfer image to GPU
104
  gpu_img = cp.asarray(img)
105
  gpu_hsv = cp.asarray(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))
@@ -107,38 +113,65 @@ class GPUSatelliteModelGenerator:
107
  height, width = img.shape[:2]
108
  output = cp.zeros_like(gpu_img)
109
 
110
- # Vectorized color matching on GPU
 
 
 
 
111
  hsv_pixels = gpu_hsv.reshape(-1, 3)
112
 
113
- # Create masks for each category
114
  shadow_mask = cp.zeros((height * width,), dtype=bool)
115
  road_mask = cp.zeros((height * width,), dtype=bool)
116
  water_mask = cp.zeros((height * width,), dtype=bool)
117
 
118
- # Vectorized color matching for predefined colors
119
  for ref_hsv in self.shadow_colors_hsv:
120
- shadow_mask |= self.gpu_color_distance_hsv(hsv_pixels.T, ref_hsv, self.shadow_tolerance)
121
-
 
 
 
 
 
 
122
  for ref_hsv in self.road_colors_hsv:
123
- road_mask |= self.gpu_color_distance_hsv(hsv_pixels.T, ref_hsv, self.road_tolerance)
124
-
 
 
 
 
 
 
125
  for ref_hsv in self.water_colors_hsv:
126
  water_mask |= self.gpu_color_distance_hsv(hsv_pixels.T, ref_hsv, self.water_tolerance)
127
 
128
- # Convert HSV to normalized values for vegetation and terrain detection
129
  h, s, v = hsv_pixels.T
130
  h = h * 2 # Convert to 0-360 range
131
  s = s / 255
132
  v = v / 255
133
 
134
- # Create masks for vegetation and terrain
135
- vegetation_mask = (h >= 40) & (h <= 150) & (s >= 0.15)
136
- terrain_mask = (h >= 10) & (h <= 30) & (s >= 0.15)
 
 
 
 
 
 
 
 
 
 
 
137
 
138
  # Building mask (everything that's not another category)
139
  building_mask = ~(shadow_mask | water_mask | road_mask | vegetation_mask | terrain_mask)
140
 
141
- # Apply all masks to create final output
142
  output_flat = output.reshape(-1, 3)
143
  output_flat[shadow_mask] = self.colors['black']
144
  output_flat[water_mask] = self.colors['blue']
@@ -147,30 +180,31 @@ class GPUSatelliteModelGenerator:
147
  output_flat[terrain_mask] = self.colors['brown']
148
  output_flat[building_mask] = self.colors['white']
149
 
150
- # Reshape back to image dimensions
151
  segmented = output.reshape(height, width, 3)
152
 
153
- # Handle isolated building pixels using GPU operations
154
  kernel = cp.ones((3, 3), dtype=bool)
155
  kernel[1, 1] = False
156
 
157
- # For each color except white (buildings)
158
- for color_name, color_value in self.colors.items():
159
- if cp.array_equal(color_value, self.colors['white']):
160
- continue
 
161
 
162
- # Create mask for current color
163
- color_mask = cp.all(segmented == color_value, axis=2)
164
-
165
- # Dilate the mask
166
- dilated = binary_dilation(color_mask, structure=kernel)
167
-
168
- # Find building pixels that are mostly surrounded by this color
169
- building_pixels = cp.all(segmented == self.colors['white'], axis=2)
170
- surrounded = dilated & building_pixels
171
-
172
- # Update those pixels to the current color
173
- segmented[surrounded] = color_value
 
174
 
175
  return segmented
176
 
@@ -324,8 +358,8 @@ def generate_and_process_map(prompt: str) -> tuple[str | None, np.ndarray | None
324
 
325
  # Create Gradio interface
326
  with gr.Blocks() as demo:
327
- gr.Markdown("# GPU-Accelerated Text to Map")
328
- gr.Markdown("Generate 3D maps and segmentation maps from text descriptions using FLUX and GPU-accelerated processing.")
329
 
330
  with gr.Row():
331
  prompt_input = gr.Text(
 
82
 
83
  @staticmethod
84
  def gpu_color_distance_hsv(pixel_hsv, reference_hsv, tolerance):
85
+ """HSV color distance calculation"""
86
  pixel_h = pixel_hsv[0] * 2
87
  pixel_s = pixel_hsv[1] / 255
88
  pixel_v = pixel_hsv[2] / 255
89
 
90
+ # Calculate circular hue difference
91
  hue_diff = cp.minimum(cp.abs(pixel_h - reference_hsv[0]),
92
+ 360 - cp.abs(pixel_h - reference_hsv[0]))
93
+
94
+ # Calculate saturation and value differences with weighted importance
95
  sat_diff = cp.abs(pixel_s - reference_hsv[1])
96
  val_diff = cp.abs(pixel_v - reference_hsv[2])
97
 
98
+ # Combined distance check with adjusted weights
99
  return cp.logical_and(
100
+ cp.logical_and(
101
+ hue_diff <= tolerance['hue'],
102
+ sat_diff <= tolerance['sat']
103
+ ),
104
  val_diff <= tolerance['val']
105
  )
106
 
107
  def segment_image_gpu(self, img):
108
+ """GPU-accelerated image segmentation with improved road and shadow detection"""
109
  # Transfer image to GPU
110
  gpu_img = cp.asarray(img)
111
  gpu_hsv = cp.asarray(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))
 
113
  height, width = img.shape[:2]
114
  output = cp.zeros_like(gpu_img)
115
 
116
+ # Create a sliding window view for neighborhood analysis
117
+ pad = 2 # Equivalent to window_size=5 in segment.py
118
+ gpu_hsv_pad = cp.pad(gpu_hsv, ((pad, pad), (pad, pad), (0, 0)), mode='edge')
119
+
120
+ # Prepare flattened HSV data
121
  hsv_pixels = gpu_hsv.reshape(-1, 3)
122
 
123
+ # Initialize masks
124
  shadow_mask = cp.zeros((height * width,), dtype=bool)
125
  road_mask = cp.zeros((height * width,), dtype=bool)
126
  water_mask = cp.zeros((height * width,), dtype=bool)
127
 
128
+ # Improved color matching with adjusted tolerances
129
  for ref_hsv in self.shadow_colors_hsv:
130
+ # Lower the threshold for shadows to catch more subtle variations
131
+ temp_tolerance = {
132
+ 'hue': self.shadow_tolerance['hue'] * 1.2, # Slightly increased tolerance
133
+ 'sat': self.shadow_tolerance['sat'] * 1.1,
134
+ 'val': self.shadow_tolerance['val'] * 1.2
135
+ }
136
+ shadow_mask |= self.gpu_color_distance_hsv(hsv_pixels.T, ref_hsv, temp_tolerance)
137
+
138
  for ref_hsv in self.road_colors_hsv:
139
+ # Adjusted road detection with focus on value component
140
+ temp_tolerance = {
141
+ 'hue': self.road_tolerance['hue'] * 1.3, # Increased hue tolerance
142
+ 'sat': self.road_tolerance['sat'] * 1.2, # Increased saturation tolerance
143
+ 'val': self.road_tolerance['val'] # Keep original value tolerance
144
+ }
145
+ road_mask |= self.gpu_color_distance_hsv(hsv_pixels.T, ref_hsv, temp_tolerance)
146
+
147
  for ref_hsv in self.water_colors_hsv:
148
  water_mask |= self.gpu_color_distance_hsv(hsv_pixels.T, ref_hsv, self.water_tolerance)
149
 
150
+ # Normalize HSV values for vegetation and terrain detection
151
  h, s, v = hsv_pixels.T
152
  h = h * 2 # Convert to 0-360 range
153
  s = s / 255
154
  v = v / 255
155
 
156
+ # Enhanced vegetation detection
157
+ vegetation_mask = ((h >= 40) & (h <= 150) & (s >= 0.15))
158
+
159
+ # Enhanced terrain detection
160
+ terrain_mask = ((h >= 10) & (h <= 30) & (s >= 0.15)) | \
161
+ ((h >= 25) & (h <= 40) & (s >= 0.1) & (v <= 0.8)) # Added brown-gray detection
162
+
163
+ # Apply brightness-based corrections for roads
164
+ gray_mask = (s <= 0.2) & (v >= 0.4) & (v <= 0.85) # Detect grayish areas
165
+ road_mask |= gray_mask & ~(shadow_mask | water_mask | vegetation_mask | terrain_mask)
166
+
167
+ # Enhanced shadow detection using value component
168
+ dark_mask = (v <= 0.3) # Detect very dark areas
169
+ shadow_mask |= dark_mask & ~(water_mask | road_mask)
170
 
171
  # Building mask (everything that's not another category)
172
  building_mask = ~(shadow_mask | water_mask | road_mask | vegetation_mask | terrain_mask)
173
 
174
+ # Apply masks to create output
175
  output_flat = output.reshape(-1, 3)
176
  output_flat[shadow_mask] = self.colors['black']
177
  output_flat[water_mask] = self.colors['blue']
 
180
  output_flat[terrain_mask] = self.colors['brown']
181
  output_flat[building_mask] = self.colors['white']
182
 
 
183
  segmented = output.reshape(height, width, 3)
184
 
185
+ # Enhanced isolated pixel cleanup using morphological operations
186
  kernel = cp.ones((3, 3), dtype=bool)
187
  kernel[1, 1] = False
188
 
189
+ # Two-pass cleanup for better results
190
+ for _ in range(2):
191
+ for color_name, color_value in self.colors.items():
192
+ if cp.array_equal(color_value, self.colors['white']):
193
+ continue
194
 
195
+ # Create and dilate mask for current color
196
+ color_mask = cp.all(segmented == color_value, axis=2)
197
+ dilated = binary_dilation(color_mask, structure=kernel)
198
+
199
+ # Find isolated building pixels
200
+ building_pixels = cp.all(segmented == self.colors['white'], axis=2)
201
+ neighbor_count = binary_dilation(color_mask, structure=kernel).astype(int)
202
+
203
+ # More aggressive cleanup for truly isolated pixels
204
+ surrounded = (neighbor_count >= 5) & building_pixels # At least 5 neighbors of same color
205
+
206
+ # Update isolated pixels
207
+ segmented[surrounded] = color_value
208
 
209
  return segmented
210
 
 
358
 
359
  # Create Gradio interface
360
  with gr.Blocks() as demo:
361
+ gr.Markdown("# Text to Map")
362
+ gr.Markdown("Generate a 3D map from text!")
363
 
364
  with gr.Row():
365
  prompt_input = gr.Text(