| """ |
| Example script demonstrating tactile-visual feature extraction. |
| |
| This script: |
| 1. Generates fake wrist and tactile images |
| 2. Generates fake camera parameters |
| 3. Computes 3D pose of tactile sensor using forward kinematics |
| 4. Projects the pose to 2D bounding boxes |
| 5. Extracts features h_tau and h_w using CLIP-like backbone |
| """ |
|
|
| import numpy as np |
| import matplotlib.pyplot as plt |
| from dobot_control.tactile_feature_extraction import ( |
| TactileFeatureExtractor, |
| ForwardKinematics, |
| CameraProjection, |
| generate_fake_camera_params, |
| generate_fake_images |
| ) |
|
|
|
|
| def main(): |
| """Main example function.""" |
| print("=" * 60) |
| print("Tactile-Visual Feature Extraction Example") |
| print("=" * 60) |
| |
| |
| print("\n[Step 1] Generating fake images and camera parameters...") |
| |
| img_size = (640, 480) |
| wrist_image, tactile_image = generate_fake_images(img_size) |
| K_w, E_w = generate_fake_camera_params(img_size) |
| K_tp, E_tp = generate_fake_camera_params(img_size) |
| |
| print(f" - Wrist image shape: {wrist_image.shape}") |
| print(f" - Tactile image shape: {tactile_image.shape}") |
| print(f" - Camera intrinsic K:\n{K_w}") |
| |
| |
| print("\n[Step 2] Computing tactile sensor 3D pose using forward kinematics...") |
| |
| |
| joint_angles = np.array([ |
| 0.1, |
| 0.2, |
| -0.3, |
| 0.4, |
| -0.1, |
| 0.2 |
| ]) |
| |
| |
| sensor_offset = np.array([0.0, 0.0, 0.02]) |
| |
| |
| P_sensor = ForwardKinematics.compute_tactile_sensor_pose( |
| joint_angles=joint_angles, |
| robot_type="Nova 2", |
| sensor_offset=sensor_offset |
| ) |
| |
| print(f" - Joint angles (rad): {joint_angles}") |
| print(f" - Sensor pose (position): {P_sensor[:3, 3]}") |
| print(f" - Sensor pose matrix shape: {P_sensor.shape}") |
| |
| |
| print("\n[Step 3] Projecting 3D pose to 2D bounding boxes...") |
| |
| |
| sensor_size = (0.04, 0.04) |
| |
| |
| bbox_w = CameraProjection.compute_sensor_bounding_box( |
| sensor_pose=P_sensor, |
| sensor_size=sensor_size, |
| K=K_w, |
| E=E_w, |
| img_size=img_size |
| ) |
| |
| |
| bbox_tp = CameraProjection.compute_sensor_bounding_box( |
| sensor_pose=P_sensor, |
| sensor_size=sensor_size, |
| K=K_tp, |
| E=E_tp, |
| img_size=img_size |
| ) |
| |
| print(f" - Wrist bounding box: x=[{bbox_w['x_min']:.1f}, {bbox_w['x_max']:.1f}], " |
| f"y=[{bbox_w['y_min']:.1f}, {bbox_w['y_max']:.1f}]") |
| print(f" - Third-person bounding box: x=[{bbox_tp['x_min']:.1f}, {bbox_tp['x_max']:.1f}], " |
| f"y=[{bbox_tp['y_min']:.1f}, {bbox_tp['y_max']:.1f}]") |
| |
| |
| print("\n[Step 4] Extracting features using CLIP-like backbone...") |
| |
| |
| extractor = TactileFeatureExtractor( |
| img_size=640, |
| patch_size=16, |
| embed_dim=768, |
| device='cpu' |
| ) |
| |
| |
| features = extractor.extract_features( |
| wrist_image=wrist_image, |
| tactile_image=tactile_image, |
| bbox_wrist=bbox_w, |
| bbox_tp=bbox_tp |
| ) |
| |
| h_tau = features['h_tau'] |
| h_w = features['h_w'] |
| |
| print(f" - h_tau shape: {h_tau.shape}") |
| print(f" - h_w shape: {h_w.shape}") |
| print(f" - h_tau mean: {h_tau.mean().item():.4f}, std: {h_tau.std().item():.4f}") |
| print(f" - h_w mean: {h_w.mean().item():.4f}, std: {h_w.std().item():.4f}") |
| |
| |
| print("\n[Step 5] Visualizing results...") |
| |
| |
| fig, axes = plt.subplots(2, 2, figsize=(12, 10)) |
| |
| |
| axes[0, 0].imshow(wrist_image) |
| rect_w = plt.Rectangle( |
| (bbox_w['x_min'], bbox_w['y_min']), |
| bbox_w['x_max'] - bbox_w['x_min'], |
| bbox_w['y_max'] - bbox_w['y_min'], |
| linewidth=2, edgecolor='r', facecolor='none' |
| ) |
| axes[0, 0].add_patch(rect_w) |
| axes[0, 0].set_title('Wrist Camera Image\n(Red box: projected sensor)') |
| axes[0, 0].axis('off') |
| |
| |
| axes[0, 1].imshow(tactile_image) |
| axes[0, 1].set_title('Tactile Sensor Image') |
| axes[0, 1].axis('off') |
| |
| |
| axes[1, 0].plot(h_tau.detach().numpy()) |
| axes[1, 0].set_title('h_tau (Tactile Features)') |
| axes[1, 0].set_xlabel('Feature Dimension') |
| axes[1, 0].set_ylabel('Feature Value') |
| axes[1, 0].grid(True) |
| |
| axes[1, 1].plot(h_w.detach().numpy()) |
| axes[1, 1].set_title('h_w (Wrist Visual Features)') |
| axes[1, 1].set_xlabel('Feature Dimension') |
| axes[1, 1].set_ylabel('Feature Value') |
| axes[1, 1].grid(True) |
| |
| plt.tight_layout() |
| plt.savefig('tactile_feature_extraction_example.png', dpi=150) |
| print(" - Visualization saved to 'tactile_feature_extraction_example.png'") |
| |
| |
| print("\n[Step 6] Demonstrating feature grid mapping...") |
| |
| |
| feat_x_min, feat_y_min, feat_x_max, feat_y_max = extractor.map_bbox_to_feature_grid( |
| bbox_w, (wrist_image.shape[1], wrist_image.shape[0]) |
| ) |
| |
| feat_h, feat_w = extractor.feature_grid_shape |
| print(f" - Original image size: {wrist_image.shape[1]} x {wrist_image.shape[0]}") |
| print(f" - Feature grid size: {feat_w} x {feat_h}") |
| print(f" - Original bbox: x=[{bbox_w['x_min']:.1f}, {bbox_w['x_max']:.1f}], " |
| f"y=[{bbox_w['y_min']:.1f}, {bbox_w['y_max']:.1f}]") |
| print(f" - Feature grid bbox: x=[{feat_x_min}, {feat_x_max}], " |
| f"y=[{feat_y_min}, {feat_y_max}]") |
| print(f" - Number of tokens selected: {(feat_x_max - feat_x_min + 1) * (feat_y_max - feat_y_min + 1)}") |
| |
| print("\n" + "=" * 60) |
| print("Example completed successfully!") |
| print("=" * 60) |
| |
| |
| try: |
| plt.show() |
| except: |
| pass |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|
|
|