mariboo commited on
Commit
a85e26f
·
verified ·
1 Parent(s): 8fc11fa

Create shoe_outlines_lib.py

Browse files
Files changed (1) hide show
  1. shoe_outlines_lib.py +99 -0
shoe_outlines_lib.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ from typing import Iterable, List
3
+ import cv2
4
+ import json
5
+ import numpy as np
6
+ import pandas as pd
7
+
8
+
9
+ def norm_by_x(df):
10
+ df['x'] = df['x'] - df['x'].min()
11
+ df['y'] = df['y'] - df['y'].min()
12
+ maxx = df['x'].max()
13
+ df['x'] /= maxx
14
+ df['y'] /= maxx
15
+ return df
16
+
17
+
18
+ def csv2dfs(filenames:Iterable[str], rotate_func:callable=None) -> List[pd.DataFrame]:
19
+ ''' Extract x,y coordinates from a .csv/.xlsx file. Each file may include multiple outlines.'''
20
+
21
+ # if multiple x,y columns in the csv/xlsx file
22
+ def _sheet2dfs(df, df_name):
23
+ dfs_local = []
24
+ if 'Unnamed: 0' in df.columns:
25
+ df = df.drop(columns=['Unnamed: 0'])
26
+ column_pairs = [(df.columns[i], df.columns[i+1]) for i in range(0, len(df.columns)-1, 2)]
27
+ for x_col, y_col in column_pairs:
28
+ shoe_id = x_col
29
+ x, y = df[x_col].iloc[1:].astype(float), df[y_col].iloc[1:].astype(float)
30
+ if rotate_func: x, y = rotate_func(x, y)
31
+ shoe_df = pd.DataFrame({'x': x, 'y': y}).dropna()
32
+ shoe_df.name = shoe_id
33
+ dfs_local.append(shoe_df)
34
+ else:
35
+ df.name = df_name
36
+ dfs_local += [df]
37
+ return dfs_local
38
+
39
+ dfs = []
40
+ for filename in filenames:
41
+ filename = Path(filename)
42
+
43
+ if filename.suffix.lower() == '.csv':
44
+ df = pd.read_csv(filename)
45
+ dfs += _sheet2dfs(df, filename.name)
46
+
47
+ elif filename.suffix.lower() == '.xlsx':
48
+ xls = pd.ExcelFile(filename)
49
+ for sheet in xls.sheet_names:
50
+ df = pd.read_excel(xls, sheet)
51
+ dfs += _sheet2dfs(df, sheet)
52
+
53
+ elif filename.suffix.lower() == '.json':
54
+ vgg_json = json.load(filename.open())
55
+ for _,v in vgg_json.items():
56
+ fn = v['filename']
57
+ for region in v['regions']:
58
+ if region['shape_attributes']['name'] != 'polygon': continue
59
+ xs,ys = region['shape_attributes']['all_points_x'], region['shape_attributes']['all_points_y']
60
+ df = pd.DataFrame({'x':xs, 'y':ys})
61
+ df.name = fn
62
+ dfs.append(df)
63
+ break
64
+
65
+ return dfs
66
+
67
+
68
+ def coordsdf2image(df:pd.DataFrame, target_height:int=256, margin:float=0.1) -> np.ndarray:
69
+ ''' Render a footprint outline from x,y coordinates in a DataFrame into a binary image (filled shape). '''
70
+
71
+ x_coords, y_coords = df['x'].values, df['y'].values
72
+
73
+ # Compute the bounding box of the footprint
74
+ x_min, x_max = x_coords.min(), x_coords.max()
75
+ y_min, y_max = y_coords.min(), y_coords.max()
76
+ width = x_max - x_min
77
+ height = y_max - y_min
78
+
79
+ # Compute canvas width proportional to the footprint's aspect ratio
80
+ scale = target_height / (1 + 2 * margin) / height
81
+ target_width = int(scale * width + 2 * margin * target_height)
82
+
83
+ image = np.zeros((target_height, target_width), dtype=np.uint8)
84
+
85
+ # Scale coordinates to fit within the canvas
86
+ x_scaled = ((x_coords - x_min) * scale).astype(np.int32)
87
+ y_scaled = ((y_coords - y_min) * scale).astype(np.int32)
88
+
89
+ # Compute the size of the scaled footprint
90
+ scaled_width = x_scaled.max() - x_scaled.min()
91
+ scaled_height = y_scaled.max() - y_scaled.min()
92
+
93
+ # Compute and apply offsets for centering
94
+ x_scaled += (target_width - scaled_width) // 2 - x_scaled.min()
95
+ y_scaled += (target_height - scaled_height) // 2 - y_scaled.min()
96
+
97
+ contour = np.array([np.stack((x_scaled, y_scaled), axis=-1)], dtype=np.int32)
98
+ cv2.fillPoly(image, contour, color=255) # Fill the shape with white (255)
99
+ return image