MohmedAnik commited on
Commit
21d3dc9
·
verified ·
1 Parent(s): b2b6cf0

Update utils.py

Browse files
Files changed (1) hide show
  1. utils.py +31 -51
utils.py CHANGED
@@ -21,9 +21,8 @@ def resize_foreground(
21
  alpha[1].min(),
22
  alpha[1].max(),
23
  )
24
- # crop the foreground
25
  fg = image[y1:y2, x1:x2]
26
- # pad to square
27
  size = max(fg.shape[0], fg.shape[1])
28
  ph0, pw0 = (size - fg.shape[0]) // 2, (size - fg.shape[1]) // 2
29
  ph1, pw1 = size - fg.shape[0] - ph0, size - fg.shape[1] - pw0
@@ -34,9 +33,9 @@ def resize_foreground(
34
  constant_values=((0, 0), (0, 0), (0, 0)),
35
  )
36
 
37
- # compute padding according to the ratio
38
  new_size = int(new_image.shape[0] / ratio)
39
- # pad to size, double side
40
  ph0, pw0 = (new_size - size) // 2, (new_size - size) // 2
41
  ph1, pw1 = new_size - size - ph0, new_size - size - pw0
42
  new_image = np.pad(
@@ -62,25 +61,21 @@ def remove_background(image: Image,
62
  return image
63
 
64
  def random_crop(image, crop_scale=(0.8, 0.95)):
65
- """
66
- 随机裁切图片
67
- image (numpy.ndarray): (H, W, C)。
68
- crop_scale (tuple): (min_scale, max_scale)。
69
- """
70
- assert isinstance(image, Image.Image), "iput must be PIL.Image.Image"
71
  assert len(crop_scale) == 2 and 0 < crop_scale[0] <= crop_scale[1] <= 1
72
 
73
  width, height = image.size
74
 
75
- # 计算裁切的高度和宽度
76
  crop_width = random.randint(int(width * crop_scale[0]), int(width * crop_scale[1]))
77
  crop_height = random.randint(int(height * crop_scale[0]), int(height * crop_scale[1]))
78
 
79
- # 随机选择裁切的起始点
80
  left = random.randint(0, width - crop_width)
81
  top = random.randint(0, height - crop_height)
82
 
83
- # 裁切图片
84
  cropped_image = image.crop((left, top, left + crop_width, top + crop_height))
85
 
86
  return cropped_image
@@ -102,7 +97,7 @@ def background_preprocess(input_image, do_remove_background):
102
  return input_image
103
 
104
  def remove_outliers_and_average(tensor, threshold=1.5):
105
- assert tensor.dim() == 1, "dimension of input Tensor must equal to 1"
106
 
107
  q1 = torch.quantile(tensor, 0.25)
108
  q3 = torch.quantile(tensor, 0.75)
@@ -120,37 +115,32 @@ def remove_outliers_and_average(tensor, threshold=1.5):
120
 
121
 
122
  def remove_outliers_and_average_circular(tensor, threshold=1.5):
123
- assert tensor.dim() == 1, "dimension of input Tensor must equal to 1"
124
-
125
- # 将角度转换为二维平面上的点
126
  radians = tensor * torch.pi / 180.0
127
  x_coords = torch.cos(radians)
128
  y_coords = torch.sin(radians)
129
 
130
- # 计算平均向量
131
  mean_x = torch.mean(x_coords)
132
  mean_y = torch.mean(y_coords)
133
 
134
  differences = torch.sqrt((x_coords - mean_x) * (x_coords - mean_x) + (y_coords - mean_y) * (y_coords - mean_y))
135
 
136
- # 计算四分位数和 IQR
137
  q1 = torch.quantile(differences, 0.25)
138
  q3 = torch.quantile(differences, 0.75)
139
  iqr = q3 - q1
140
 
141
- # 计算上下限
142
  lower_bound = q1 - threshold * iqr
143
  upper_bound = q3 + threshold * iqr
144
 
145
- # 筛选非离群点
146
  non_outliers = tensor[(differences >= lower_bound) & (differences <= upper_bound)]
147
 
148
  if len(non_outliers) == 0:
149
  mean_angle = torch.atan2(mean_y, mean_x) * 180.0 / torch.pi
150
  mean_angle = (mean_angle + 360) % 360
151
- return mean_angle # 如果没有非离群点,返回 None
152
-
153
- # 对非离群点再次计算平均向量
154
  radians = non_outliers * torch.pi / 180.0
155
  x_coords = torch.cos(radians)
156
  y_coords = torch.sin(radians)
@@ -181,7 +171,7 @@ def get_proj2D_XYZ(phi, theta, gamma):
181
  z = scale(z)
182
  return x, y, z
183
 
184
- # 绘制3D坐标轴
185
  def draw_axis(ax, origin, vector, color, label=None):
186
  ax.quiver(origin[0], origin[1], vector[0], vector[1], angles='xy', scale_units='xy', scale=1, color=color)
187
  if label!=None:
@@ -190,7 +180,7 @@ def draw_axis(ax, origin, vector, color, label=None):
190
  def matplotlib_2D_arrow(angles, rm_bkg_img):
191
  fig, ax = plt.subplots(figsize=(8, 8))
192
 
193
- # 设置旋转角度
194
  phi = np.radians(angles[0])
195
  theta = np.radians(angles[1])
196
  gamma = np.radians(-1*angles[2])
@@ -204,10 +194,10 @@ def matplotlib_2D_arrow(angles, rm_bkg_img):
204
 
205
  origin = np.array([0, 0])
206
 
207
- # 旋转后的向量
208
  rot_x, rot_y, rot_z = get_proj2D_XYZ(phi, theta, gamma)
209
 
210
- # draw arrow
211
  arrow_attr = [{'point':rot_x, 'color':'r', 'label':'front'},
212
  {'point':rot_y, 'color':'g', 'label':'right'},
213
  {'point':rot_z, 'color':'b', 'label':'top'}]
@@ -221,15 +211,13 @@ def matplotlib_2D_arrow(angles, rm_bkg_img):
221
 
222
  for i in range(3):
223
  draw_axis(ax, origin, arrow_attr[order[i]]['point'], arrow_attr[order[i]]['color'], arrow_attr[order[i]]['label'])
224
- # draw_axis(ax, origin, rot_y, 'g', label='right')
225
- # draw_axis(ax, origin, rot_z, 'b', label='top')
226
- # draw_axis(ax, origin, rot_x, 'r', label='front')
227
 
228
- # 关闭坐标轴和网格
229
  ax.set_axis_off()
230
  ax.grid(False)
231
 
232
- # 设置坐标范围
233
  ax.set_xlim(-5, 5)
234
  ax.set_ylim(-5, 5)
235
 
@@ -245,11 +233,10 @@ import math
245
  axis_model = Model("./axis.obj", texture_filename="./axis.png")
246
  def render_3D_axis(phi, theta, gamma):
247
  radius = 240
248
- # camera_location = [radius * math.cos(phi), radius * math.sin(phi), radius * math.tan(theta)]
249
- # print(camera_location)
250
  camera_location = [-1*radius * math.cos(phi), -1*radius * math.tan(theta), radius * math.sin(phi)]
251
  img = render(
252
- # Model("res/jinx.obj", texture_filename="res/jinx.tga"),
253
  axis_model,
254
  height=512,
255
  width=512,
@@ -260,44 +247,37 @@ def render_3D_axis(phi, theta, gamma):
260
  return img
261
 
262
  def overlay_images_with_scaling(center_image: Image.Image, background_image, target_size=(512, 512)):
263
- """
264
- 调整前景图像大小为 512x512,将背景图像缩放以适配,并中心对齐叠加
265
- :param center_image: 前景图像
266
- :param background_image: 背景图像
267
- :param target_size: 前景图像的目标大小,默认 (512, 512)
268
- :return: 叠加后的图像
269
- """
270
- # 确保输入图像为 RGBA 模式
271
  if center_image.mode != "RGBA":
272
  center_image = center_image.convert("RGBA")
273
  if background_image.mode != "RGBA":
274
  background_image = background_image.convert("RGBA")
275
 
276
- # 调整前景图像大小
277
  center_image = center_image.resize(target_size)
278
 
279
- # 缩放背景图像,确保其适合前景图像的尺寸
280
  bg_width, bg_height = background_image.size
281
 
282
- # 按宽度或高度等比例缩放背景
283
  scale = target_size[0] / max(bg_width, bg_height)
284
  new_width = int(bg_width * scale)
285
  new_height = int(bg_height * scale)
286
  resized_background = background_image.resize((new_width, new_height))
287
- # 计算需要的填充量
288
  pad_width = target_size[0] - new_width
289
  pad_height = target_size[0] - new_height
290
 
291
- # 计算上下左右的 padding
292
  left = pad_width // 2
293
  right = pad_width - left
294
  top = pad_height // 2
295
  bottom = pad_height - top
296
 
297
- # 添加 padding
298
  resized_background = ImageOps.expand(resized_background, border=(left, top, right, bottom), fill=(255,255,255,255))
299
 
300
- # 将前景图像叠加到背景图像上
301
  result = resized_background.copy()
302
  result.paste(center_image, (0, 0), mask=center_image)
303
 
 
21
  alpha[1].min(),
22
  alpha[1].max(),
23
  )
 
24
  fg = image[y1:y2, x1:x2]
25
+
26
  size = max(fg.shape[0], fg.shape[1])
27
  ph0, pw0 = (size - fg.shape[0]) // 2, (size - fg.shape[1]) // 2
28
  ph1, pw1 = size - fg.shape[0] - ph0, size - fg.shape[1] - pw0
 
33
  constant_values=((0, 0), (0, 0), (0, 0)),
34
  )
35
 
36
+
37
  new_size = int(new_image.shape[0] / ratio)
38
+
39
  ph0, pw0 = (new_size - size) // 2, (new_size - size) // 2
40
  ph1, pw1 = new_size - size - ph0, new_size - size - pw0
41
  new_image = np.pad(
 
61
  return image
62
 
63
  def random_crop(image, crop_scale=(0.8, 0.95)):
64
+
65
+ assert isinstance(image, Image.Image),
 
 
 
 
66
  assert len(crop_scale) == 2 and 0 < crop_scale[0] <= crop_scale[1] <= 1
67
 
68
  width, height = image.size
69
 
70
+
71
  crop_width = random.randint(int(width * crop_scale[0]), int(width * crop_scale[1]))
72
  crop_height = random.randint(int(height * crop_scale[0]), int(height * crop_scale[1]))
73
 
74
+
75
  left = random.randint(0, width - crop_width)
76
  top = random.randint(0, height - crop_height)
77
 
78
+
79
  cropped_image = image.crop((left, top, left + crop_width, top + crop_height))
80
 
81
  return cropped_image
 
97
  return input_image
98
 
99
  def remove_outliers_and_average(tensor, threshold=1.5):
100
+ assert tensor.dim() == 1,
101
 
102
  q1 = torch.quantile(tensor, 0.25)
103
  q3 = torch.quantile(tensor, 0.75)
 
115
 
116
 
117
  def remove_outliers_and_average_circular(tensor, threshold=1.5):
118
+ assert tensor.dim() == 1,
 
 
119
  radians = tensor * torch.pi / 180.0
120
  x_coords = torch.cos(radians)
121
  y_coords = torch.sin(radians)
122
 
123
+
124
  mean_x = torch.mean(x_coords)
125
  mean_y = torch.mean(y_coords)
126
 
127
  differences = torch.sqrt((x_coords - mean_x) * (x_coords - mean_x) + (y_coords - mean_y) * (y_coords - mean_y))
128
 
129
+
130
  q1 = torch.quantile(differences, 0.25)
131
  q3 = torch.quantile(differences, 0.75)
132
  iqr = q3 - q1
133
 
 
134
  lower_bound = q1 - threshold * iqr
135
  upper_bound = q3 + threshold * iqr
136
 
137
+
138
  non_outliers = tensor[(differences >= lower_bound) & (differences <= upper_bound)]
139
 
140
  if len(non_outliers) == 0:
141
  mean_angle = torch.atan2(mean_y, mean_x) * 180.0 / torch.pi
142
  mean_angle = (mean_angle + 360) % 360
143
+ return mean_angle
 
 
144
  radians = non_outliers * torch.pi / 180.0
145
  x_coords = torch.cos(radians)
146
  y_coords = torch.sin(radians)
 
171
  z = scale(z)
172
  return x, y, z
173
 
174
+
175
  def draw_axis(ax, origin, vector, color, label=None):
176
  ax.quiver(origin[0], origin[1], vector[0], vector[1], angles='xy', scale_units='xy', scale=1, color=color)
177
  if label!=None:
 
180
  def matplotlib_2D_arrow(angles, rm_bkg_img):
181
  fig, ax = plt.subplots(figsize=(8, 8))
182
 
183
+
184
  phi = np.radians(angles[0])
185
  theta = np.radians(angles[1])
186
  gamma = np.radians(-1*angles[2])
 
194
 
195
  origin = np.array([0, 0])
196
 
197
+
198
  rot_x, rot_y, rot_z = get_proj2D_XYZ(phi, theta, gamma)
199
 
200
+
201
  arrow_attr = [{'point':rot_x, 'color':'r', 'label':'front'},
202
  {'point':rot_y, 'color':'g', 'label':'right'},
203
  {'point':rot_z, 'color':'b', 'label':'top'}]
 
211
 
212
  for i in range(3):
213
  draw_axis(ax, origin, arrow_attr[order[i]]['point'], arrow_attr[order[i]]['color'], arrow_attr[order[i]]['label'])
214
+
 
 
215
 
216
+
217
  ax.set_axis_off()
218
  ax.grid(False)
219
 
220
+
221
  ax.set_xlim(-5, 5)
222
  ax.set_ylim(-5, 5)
223
 
 
233
  axis_model = Model("./axis.obj", texture_filename="./axis.png")
234
  def render_3D_axis(phi, theta, gamma):
235
  radius = 240
236
+
 
237
  camera_location = [-1*radius * math.cos(phi), -1*radius * math.tan(theta), radius * math.sin(phi)]
238
  img = render(
239
+
240
  axis_model,
241
  height=512,
242
  width=512,
 
247
  return img
248
 
249
  def overlay_images_with_scaling(center_image: Image.Image, background_image, target_size=(512, 512)):
250
+
 
 
 
 
 
 
 
251
  if center_image.mode != "RGBA":
252
  center_image = center_image.convert("RGBA")
253
  if background_image.mode != "RGBA":
254
  background_image = background_image.convert("RGBA")
255
 
256
+
257
  center_image = center_image.resize(target_size)
258
 
259
+
260
  bg_width, bg_height = background_image.size
261
 
262
+
263
  scale = target_size[0] / max(bg_width, bg_height)
264
  new_width = int(bg_width * scale)
265
  new_height = int(bg_height * scale)
266
  resized_background = background_image.resize((new_width, new_height))
267
+
268
  pad_width = target_size[0] - new_width
269
  pad_height = target_size[0] - new_height
270
 
271
+
272
  left = pad_width // 2
273
  right = pad_width - left
274
  top = pad_height // 2
275
  bottom = pad_height - top
276
 
277
+
278
  resized_background = ImageOps.expand(resized_background, border=(left, top, right, bottom), fill=(255,255,255,255))
279
 
280
+
281
  result = resized_background.copy()
282
  result.paste(center_image, (0, 0), mask=center_image)
283