7e4ef6f98b
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
174 lines
5.7 KiB
Python
174 lines
5.7 KiB
Python
import argparse
|
|
import os
|
|
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
from rdp import rdp
|
|
|
|
from utils import hull
|
|
|
|
FINGER_NAMES = ["Thumb", "Index", "Middle", "Ring", "Pinky(Little)"]
|
|
BONE_NAMES = ["PIP", "DIP", "TIP"]
|
|
|
|
|
|
def count_num_in_convex_hull(points_, convex_hull_):
|
|
'''
|
|
|
|
:param points_: points in plane, N*2
|
|
:param convex_hull_: list of points to construct a convex hull , M*2
|
|
:return: numbers of points in convex hull
|
|
'''
|
|
points = points_.copy()
|
|
convex_hull = convex_hull_.copy()
|
|
convex_hull = np.append(convex_hull, [convex_hull[0]], axis=0)
|
|
|
|
v = convex_hull[1:] - convex_hull[:-1] # NUM*2
|
|
v = np.tile(v, (points_.shape[0], 1, 1))
|
|
|
|
w = -np.tile(convex_hull[:-1], (points_.shape[0], 1, 1)) + points[:, np.newaxis, :] # N*NUM*2
|
|
# 2d cross product (w1, w2) x (v1, v2) := w1*v2 - w2*v1
|
|
cross_product_2d = w[:, :, 0] * v[:, :, 1] - w[:, :, 1] * v[:, :, 0]
|
|
tmp = (cross_product_2d < 1e-6).all(axis=-1).sum()
|
|
|
|
return tmp
|
|
|
|
|
|
def calculate_convex_hull(joint_angles, args):
|
|
all_del_hulls = []
|
|
for ID in range(15):
|
|
print('*' * 40)
|
|
ja = joint_angles[:, ID]
|
|
ja_list = [tuple(x) for x in ja.tolist()]
|
|
|
|
# original convex hull
|
|
convex = hull.convex(ja_list)
|
|
convex = np.array(convex)
|
|
print("ori_hull.shape=", convex.shape)
|
|
|
|
convex_list = convex.tolist()
|
|
# convex hull simplified by the Ramer-Douglas-Peucker algorithm, a polygon simplification algorithm
|
|
rdp_convex = rdp(convex_list, epsilon=args.epsilon)
|
|
rdp_convex = np.array(rdp_convex)
|
|
print("rdp_hull.shape=", rdp_convex.shape)
|
|
|
|
# convex hull further simplified by a greedy algorithm
|
|
dep_hull = rdp_convex.copy()
|
|
for i in range(rdp_convex.shape[0]):
|
|
tmp_index = np.argwhere(dep_hull == rdp_convex[i])[0][0]
|
|
tmp_num = count_num_in_convex_hull(ja, np.delete(dep_hull, tmp_index, axis=0))
|
|
tmp_ratio = tmp_num / ja.shape[0]
|
|
print("tmp_ratio=", tmp_ratio)
|
|
|
|
if tmp_ratio > args.ratio:
|
|
dep_hull = np.delete(dep_hull, tmp_index, axis=0)
|
|
elif args.ratio - args.delta <= tmp_ratio <= args.ratio:
|
|
dep_hull = np.delete(dep_hull, tmp_index, axis=0)
|
|
break
|
|
else:
|
|
break
|
|
print("dep_hull.shape=", dep_hull.shape)
|
|
all_del_hulls.append(dep_hull)
|
|
|
|
if args.visualize:
|
|
fig = plt.figure()
|
|
figManager = plt.get_current_fig_manager()
|
|
figManager.window.showMaximized()
|
|
ax = fig.add_subplot(111)
|
|
ax.scatter(ja[:, 0], ja[:, 1], s=0.05, c='r')
|
|
ax.set_xlabel("flexion")
|
|
ax.set_ylabel("abduction")
|
|
ax.set_title('ID:{} Finger:{} Bone:{}'.format(ID, FINGER_NAMES[ID % 5], BONE_NAMES[int(ID / 5)]))
|
|
|
|
plt.plot(np.append(convex[:, 0], convex[0, 0]), np.append(convex[:, 1], convex[0, 1]), 'ro--', linewidth=3,
|
|
label='ori_convex_hull')
|
|
plt.plot(np.append(rdp_convex[:, 0], rdp_convex[0, 0]), np.append(rdp_convex[:, 1], rdp_convex[0, 1]),
|
|
'gv--',
|
|
linewidth=2, label='rdp_convex_hull')
|
|
plt.plot(np.append(dep_hull[:, 0], dep_hull[0, 0]),
|
|
np.append(dep_hull[:, 1], dep_hull[0, 1]),
|
|
'-b*', linewidth=1, label='del_convex_hull')
|
|
|
|
ja_min = np.min(ja, axis=0)
|
|
ja_max = np.max(ja, axis=0)
|
|
|
|
plt.gca().add_patch(
|
|
plt.Rectangle((ja_min[0], ja_min[1]), ja_max[0] - ja_min[0], ja_max[1] - ja_min[1], edgecolor="yellow",
|
|
fill=False, linewidth=2, label='rectangle'))
|
|
|
|
plt.xticks(np.arange(-3, 4, 1))
|
|
plt.yticks(np.arange(-2, 2, 0.5))
|
|
plt.legend(title='Convex hull category:')
|
|
|
|
plt.show()
|
|
|
|
# check if hull_test is in counter-clockwise order
|
|
# hull_test = convex
|
|
# for END in range(
|
|
# hull_test.shape[0]):
|
|
# fig = plt.figure()
|
|
# figManager = plt.get_current_fig_manager()
|
|
# figManager.window.showMaximized()
|
|
# ax = fig.add_subplot(111)
|
|
# ax.scatter(ja[:, 0], ja[:, 1], s=0.1, c='r')
|
|
# ax.set_xlabel("flexion")
|
|
# ax.set_ylabel("abduction")
|
|
#
|
|
# plt.plot(hull_test[:END, 0], hull_test[:END, 1], 'y--', linewidth=1)
|
|
# plt.xticks(np.arange(-3, 4, 1))
|
|
# plt.yticks(np.arange(-2, 2, 0.5))
|
|
# plt.show()
|
|
|
|
all_del_hulls = np.array(all_del_hulls, dtype=object)
|
|
np.save("BMC/CONVEX_HULLS.npy", all_del_hulls)
|
|
print("all_del_hulls.shape=", all_del_hulls.shape)
|
|
|
|
|
|
def main(args):
|
|
joint_angles = np.load(os.path.join(args.path, "joint_angles.npy"))
|
|
print("joint_angles.shape=", joint_angles.shape)
|
|
calculate_convex_hull(joint_angles, args)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser(
|
|
description='calculate convex hull for joint angles ')
|
|
|
|
parser.add_argument(
|
|
'-p',
|
|
'--path',
|
|
default='BMC',
|
|
type=str,
|
|
metavar='data_root',
|
|
help='directory')
|
|
|
|
parser.add_argument(
|
|
'-vis',
|
|
'--visualize',
|
|
action='store_true',
|
|
help='visualize reconstruction result',
|
|
default=True
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--epsilon',
|
|
type=float,
|
|
default=5e-4,
|
|
help='epsilon0.'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--ratio',
|
|
type=float,
|
|
default=0.9995,
|
|
help='ration0.'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--delta',
|
|
type=float,
|
|
default=0.0005,
|
|
help='ration_delta.'
|
|
)
|
|
|
|
main(parser.parse_args())
|