kvinod15 commited on
Commit
b64c448
·
verified ·
1 Parent(s): 1e42f2e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +18 -29
app.py CHANGED
@@ -14,13 +14,14 @@ from transformers import AutoModelForImageSegmentation, pipeline
14
  # Set device (GPU if available, else CPU)
15
  device = "cuda" if torch.cuda.is_available() else "cpu"
16
 
17
- # Retrieve Hugging Face token from environment variable
 
18
  hf_token = os.environ.get("HF_ACCESS_TOKEN")
19
  if hf_token is None:
20
- print("Warning: HF_ACCESS_TOKEN is not set. Access to gated models may fail.")
21
 
22
  # Load the segmentation model (RMBG-2.0)
23
- # Ensure you have access to this gated repo and that your token is valid.
24
  segmentation_model = AutoModelForImageSegmentation.from_pretrained(
25
  'briaai/RMBG-2.0',
26
  trust_remote_code=True,
@@ -29,7 +30,7 @@ segmentation_model = AutoModelForImageSegmentation.from_pretrained(
29
  segmentation_model.to(device)
30
  segmentation_model.eval()
31
 
32
- # Define the image transformation for segmentation (resize to 512x512, then normalize)
33
  image_size = (512, 512)
34
  segmentation_transform = transforms.Compose([
35
  transforms.Resize(image_size),
@@ -50,11 +51,11 @@ def segment_and_blur_background(input_image: Image.Image, blur_radius: int = 15,
50
  then composites a Gaussian-blurred background with the sharp foreground.
51
  The segmentation threshold is adjustable.
52
  """
53
- # Ensure the image is in RGB and get its original dimensions
54
  image = input_image.convert("RGB")
55
  orig_width, orig_height = image.size
56
 
57
- # Preprocess image for segmentation
58
  input_tensor = segmentation_transform(image).unsqueeze(0).to(device)
59
 
60
  # Run inference on the segmentation model
@@ -65,75 +66,63 @@ def segment_and_blur_background(input_image: Image.Image, blur_radius: int = 15,
65
  # Create a binary mask using the adjustable threshold
66
  binary_mask = (pred > threshold).float()
67
  mask_pil = transforms.ToPILImage()(binary_mask).convert("L")
68
- # Convert grayscale mask to pure binary (0 or 255)
69
  mask_pil = mask_pil.point(lambda p: 255 if p > 128 else 0)
70
- # Resize mask back to the original image dimensions
71
  mask_pil = mask_pil.resize((orig_width, orig_height), resample=Image.BILINEAR)
72
 
73
- # Apply Gaussian blur to the entire image for background
74
  blurred_image = image.filter(ImageFilter.GaussianBlur(blur_radius))
75
- # Composite the original image (foreground) with the blurred background using the mask
76
  final_image = Image.composite(image, blurred_image, mask_pil)
77
  return final_image
78
 
79
  def depth_based_lens_blur(input_image: Image.Image, max_blur: float = 2, num_bands: int = 40, invert_depth: bool = False) -> Image.Image:
80
  """
81
  Applies a depth-based blur effect using a depth map from Depth-Anything.
82
- The max_blur parameter (controlled by a slider) sets the highest blur intensity.
83
  """
84
- # Resize the input image to 512x512 for the depth estimation model
85
  image_resized = input_image.resize((512, 512))
86
 
87
- # Run depth estimation to obtain the depth map (as a PIL image)
88
  results = depth_pipeline(image_resized)
89
  depth_map_image = results['depth']
90
 
91
- # Convert the depth map to a NumPy array and normalize to [0, 1]
92
  depth_array = np.array(depth_map_image, dtype=np.float32)
93
  d_min, d_max = depth_array.min(), depth_array.max()
94
  depth_norm = (depth_array - d_min) / (d_max - d_min + 1e-8)
95
  if invert_depth:
96
  depth_norm = 1.0 - depth_norm
97
 
98
- # Convert the resized image to RGBA for compositing
99
  orig_rgba = image_resized.convert("RGBA")
100
  final_image = orig_rgba.copy()
101
 
102
- # Divide the normalized depth range into bands and apply variable blur
103
  band_edges = np.linspace(0, 1, num_bands + 1)
104
  for i in range(num_bands):
105
  band_min = band_edges[i]
106
  band_max = band_edges[i + 1]
107
- # Use the midpoint of the band to determine the blur strength.
108
  mid = (band_min + band_max) / 2.0
109
  blur_radius_band = (1 - mid) * max_blur
110
 
111
- # Create a blurred version of the image for this band.
112
  blurred_version = orig_rgba.filter(ImageFilter.GaussianBlur(blur_radius_band))
113
-
114
- # Create a mask for pixels whose normalized depth falls within this band.
115
  band_mask = ((depth_norm >= band_min) & (depth_norm < band_max)).astype(np.uint8) * 255
116
  band_mask_pil = Image.fromarray(band_mask, mode="L")
117
 
118
- # Composite the blurred version with the current final image using the band mask.
119
  final_image = Image.composite(blurred_version, final_image, band_mask_pil)
120
 
121
- # Return the final composited image as RGB.
122
  return final_image.convert("RGB")
123
 
124
  def process_image(input_image: Image.Image, effect: str, threshold: float, blur_intensity: float) -> Image.Image:
125
  """
126
- Dispatch function to apply the selected effect:
127
- - "Gaussian Blur Background": uses segmentation with an adjustable threshold and blur radius.
128
- - "Depth-based Lens Blur": applies depth-based blur with an adjustable maximum blur.
129
- The threshold slider is used only for the segmentation effect.
130
- The blur_intensity slider controls the blur strength in both effects.
131
  """
132
  if effect == "Gaussian Blur Background":
133
- # For segmentation, use the threshold and blur_intensity (as blur_radius)
134
  return segment_and_blur_background(input_image, blur_radius=int(blur_intensity), threshold=threshold)
135
  elif effect == "Depth-based Lens Blur":
136
- # For depth-based blur, use the blur_intensity as the max blur value.
137
  return depth_based_lens_blur(input_image, max_blur=blur_intensity)
138
  else:
139
  return input_image
 
14
  # Set device (GPU if available, else CPU)
15
  device = "cuda" if torch.cuda.is_available() else "cpu"
16
 
17
+ # Retrieve the Hugging Face access token from environment variables.
18
+ # In your Space, you will set this in the Secrets panel.
19
  hf_token = os.environ.get("HF_ACCESS_TOKEN")
20
  if hf_token is None:
21
+ print("Warning: HF_ACCESS_TOKEN environment variable is not set. Model access might fail.")
22
 
23
  # Load the segmentation model (RMBG-2.0)
24
+ # Make sure that you have been granted access to this gated model.
25
  segmentation_model = AutoModelForImageSegmentation.from_pretrained(
26
  'briaai/RMBG-2.0',
27
  trust_remote_code=True,
 
30
  segmentation_model.to(device)
31
  segmentation_model.eval()
32
 
33
+ # Define the transformation for segmentation (resize to 512x512, convert to tensor, and normalize)
34
  image_size = (512, 512)
35
  segmentation_transform = transforms.Compose([
36
  transforms.Resize(image_size),
 
51
  then composites a Gaussian-blurred background with the sharp foreground.
52
  The segmentation threshold is adjustable.
53
  """
54
+ # Ensure the image is in RGB and record original dimensions
55
  image = input_image.convert("RGB")
56
  orig_width, orig_height = image.size
57
 
58
+ # Preprocess the image for segmentation
59
  input_tensor = segmentation_transform(image).unsqueeze(0).to(device)
60
 
61
  # Run inference on the segmentation model
 
66
  # Create a binary mask using the adjustable threshold
67
  binary_mask = (pred > threshold).float()
68
  mask_pil = transforms.ToPILImage()(binary_mask).convert("L")
 
69
  mask_pil = mask_pil.point(lambda p: 255 if p > 128 else 0)
 
70
  mask_pil = mask_pil.resize((orig_width, orig_height), resample=Image.BILINEAR)
71
 
72
+ # Apply Gaussian blur to create the background
73
  blurred_image = image.filter(ImageFilter.GaussianBlur(blur_radius))
74
+ # Composite the foreground with the blurred background using the mask
75
  final_image = Image.composite(image, blurred_image, mask_pil)
76
  return final_image
77
 
78
  def depth_based_lens_blur(input_image: Image.Image, max_blur: float = 2, num_bands: int = 40, invert_depth: bool = False) -> Image.Image:
79
  """
80
  Applies a depth-based blur effect using a depth map from Depth-Anything.
81
+ The blur intensity is controlled by the max_blur parameter.
82
  """
83
+ # Resize input image to 512x512 for the depth estimation model
84
  image_resized = input_image.resize((512, 512))
85
 
86
+ # Obtain the depth map using the depth estimation pipeline
87
  results = depth_pipeline(image_resized)
88
  depth_map_image = results['depth']
89
 
90
+ # Normalize the depth map to [0, 1]
91
  depth_array = np.array(depth_map_image, dtype=np.float32)
92
  d_min, d_max = depth_array.min(), depth_array.max()
93
  depth_norm = (depth_array - d_min) / (d_max - d_min + 1e-8)
94
  if invert_depth:
95
  depth_norm = 1.0 - depth_norm
96
 
97
+ # Convert the resized image to RGBA for proper compositing
98
  orig_rgba = image_resized.convert("RGBA")
99
  final_image = orig_rgba.copy()
100
 
101
+ # Divide the depth range into bands and apply variable blur
102
  band_edges = np.linspace(0, 1, num_bands + 1)
103
  for i in range(num_bands):
104
  band_min = band_edges[i]
105
  band_max = band_edges[i + 1]
 
106
  mid = (band_min + band_max) / 2.0
107
  blur_radius_band = (1 - mid) * max_blur
108
 
 
109
  blurred_version = orig_rgba.filter(ImageFilter.GaussianBlur(blur_radius_band))
 
 
110
  band_mask = ((depth_norm >= band_min) & (depth_norm < band_max)).astype(np.uint8) * 255
111
  band_mask_pil = Image.fromarray(band_mask, mode="L")
112
 
 
113
  final_image = Image.composite(blurred_version, final_image, band_mask_pil)
114
 
 
115
  return final_image.convert("RGB")
116
 
117
  def process_image(input_image: Image.Image, effect: str, threshold: float, blur_intensity: float) -> Image.Image:
118
  """
119
+ Dispatches the image processing based on the chosen effect:
120
+ - 'Gaussian Blur Background' uses segmentation with adjustable threshold and blur radius.
121
+ - 'Depth-based Lens Blur' uses a depth-based approach with adjustable blur intensity.
 
 
122
  """
123
  if effect == "Gaussian Blur Background":
 
124
  return segment_and_blur_background(input_image, blur_radius=int(blur_intensity), threshold=threshold)
125
  elif effect == "Depth-based Lens Blur":
 
126
  return depth_based_lens_blur(input_image, max_blur=blur_intensity)
127
  else:
128
  return input_image