### Install 6DRepNet from Source Source: https://context7.com/thohemp/6drepnet/llms.txt Clone the repository and install dependencies from source for development or customization. ```bash git clone https://github.com/thohemp/6DRepNet cd 6DRepNet python3 -m venv venv source venv/bin/activate pip install -r requirements.txt # For demo scripts with face detection pip install git+https://github.com/elliottzheng/face-detection.git@master ``` -------------------------------- ### Install 6DRepNet via Pip Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Install the library using pip. ```sh pip3 install sixdrepnet ``` -------------------------------- ### Clone and Setup 6DRepNet Repository Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Clone the source code and prepare the environment for development or running demo scripts. ```sh git clone https://github.com/thohemp/6DRepNet cd 6DRepNet ``` ```sh python3 -m venv venv source venv/bin/activate pip install -r requirements.txt # Install required packages ``` ```sh pip install git+https://github.com/elliottzheng/face-detection.git@master ``` -------------------------------- ### Real-Time Webcam Demo Setup Source: https://context7.com/thohemp/6drepnet/llms.txt Initializes the necessary components for a real-time head pose estimation pipeline, including a GPU device, a face detector, and the 6DRepNet pose estimator model. ```python import cv2 import torch import numpy as np from PIL import Image from torchvision import transforms from face_detection import RetinaFace from sixdrepnet.model import SixDRepNet from sixdrepnet import utils # Setup gpu_id = 0 device = torch.device(f'cuda:{gpu_id}') # Initialize face detector detector = RetinaFace(gpu_id=gpu_id) # Initialize pose estimator model = SixDRepNet( backbone_name='RepVGG-B1g2', backbone_file='', deploy=True, pretrained=False ) ``` -------------------------------- ### Train 6DRepNet Model Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Execute this command to start the training process for the 6DRepNet model. Ensure the pre-trained RepVGG model is downloaded and placed in the root directory. ```sh python sixdrepnet/train.py ``` -------------------------------- ### Import SixDRepNet for Head Pose Estimation Source: https://context7.com/thohemp/6drepnet/llms.txt Use this import statement to access the SixDRepNet functionality for head pose estimation. Ensure the package is installed. ```python from sixdrepnet import SixDRepNet ``` -------------------------------- ### Predict Head Pose from Face Crop Source: https://context7.com/thohemp/6drepnet/llms.txt Use the predict method to get Euler angles (pitch, yaw, roll) in degrees from a face crop image. The input must be a BGR image. ```python from sixdrepnet import SixDRepNet import cv2 model = SixDRepNet(gpu_id=0) # Load face crop image (BGR format from OpenCV) face_crop = cv2.imread('face_crop.jpg') # predict() expects a cropped face image # Returns: pitch, yaw, roll as numpy arrays pitch, yaw, roll = model.predict(face_crop) # Values are in degrees # Pitch: Up/Down rotation (-90 to 90) # Yaw: Left/Right rotation (-90 to 90) # Roll: Tilt rotation (-90 to 90) print(f"Head orientation:") print(f" Pitch (up/down): {pitch[0]:.2f}°") print(f" Yaw (left/right): {yaw[0]:.2f}°") print(f" Roll (tilt): {roll[0]:.2f}°") ``` -------------------------------- ### Load Datasets for Training and Testing Source: https://context7.com/thohemp/6drepnet/llms.txt Demonstrates loading supported datasets like 300W-LP, AFLW2000, and BIWI using standard transforms. ```python from sixdrepnet import datasets from torchvision import transforms transform = transforms.Compose([ transforms.Resize(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 300W-LP dataset (training) - 122,450 samples pose_300w = datasets.Pose_300W_LP( data_dir='datasets/300W_LP', filename_path='datasets/300W_LP/files.txt', transform=transform ) # AFLW2000 dataset (testing) - 2,000 samples aflw2000 = datasets.AFLW2000( data_dir='datasets/AFLW2000', filename_path='datasets/AFLW2000/files.txt', transform=transform ) # BIWI dataset (training/testing) - 15,667 samples biwi = datasets.BIWI( data_dir='datasets/BIWI', filename_path='datasets/BIWI_70_30_train.npz', transform=transform, train_mode=True ) # Generic dataset loader dataset = datasets.getDataset( dataset='Pose_300W_LP', # Options: Pose_300W_LP, AFLW2000, BIWI, AFLW, AFW data_dir='datasets/300W_LP', filename_list='datasets/300W_LP/files.txt', transformations=transform, train_mode=True ) # Each sample returns: (image_tensor, rotation_matrix, euler_labels, filename) img, R, labels, name = dataset[0] print(f"Image shape: {img.shape}") # [3, 224, 224] print(f"Rotation matrix shape: {R.shape}") # [3, 3] print(f"Filename: {name}") ``` -------------------------------- ### Run Camera Demo Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Execute the demo script using a specific model snapshot and camera index. ```sh python ./sixdrepnet/demo.py --snapshot 6DRepNet_300W_LP_AFLW2000.pth \ --cam 0 ``` -------------------------------- ### Load 6DRepNet for Inference Source: https://context7.com/thohemp/6drepnet/llms.txt Initializes the model in deployment mode and loads pre-trained weights. ```python deploy_model = SixDRepNet( backbone_name='RepVGG-B1g2', backbone_file='', deploy=True, # Deployment mode pretrained=False ) deploy_model.load_state_dict(torch.load('deployed_model.pth')) deploy_model.eval() print("Model converted for optimized inference") ``` -------------------------------- ### Load 6DRepNet Model in Deploy Mode Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Instantiate the SixDRepNet model with `deploy=True` to load it in inference mode. Specify the backbone name and optionally the backbone file. ```python model = SixDRepNet(backbone_name='RepVGG-B1g2', backbone_file='', deploy=True, pretrained=False) ``` -------------------------------- ### Load and Run 6DRepNet Inference Source: https://context7.com/thohemp/6drepnet/llms.txt Initializes the model with local weights and processes a video stream to estimate head pose angles. ```python saved_state_dict = torch.load('6DRepNet_300W_LP_AFLW2000.pth', map_location='cpu') model.load_state_dict(saved_state_dict) model.to(device) model.eval() transform = transforms.Compose([ transforms.Resize(224), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) cap = cv2.VideoCapture(0) with torch.no_grad(): while True: ret, frame = cap.read() if not ret: break # Detect faces faces = detector(frame) for box, landmarks, score in faces: if score < 0.95: continue # Extract face region with margin x_min, y_min, x_max, y_max = map(int, box[:4]) bbox_width = abs(x_max - x_min) bbox_height = abs(y_max - y_min) # Add 20% margin x_min = max(0, x_min - int(0.2 * bbox_height)) y_min = max(0, y_min - int(0.2 * bbox_width)) x_max = x_max + int(0.2 * bbox_height) y_max = y_max + int(0.2 * bbox_width) # Crop and preprocess face face_crop = frame[y_min:y_max, x_min:x_max] face_img = Image.fromarray(face_crop).convert('RGB') input_tensor = transform(face_img).unsqueeze(0).to(device) # Predict pose R_pred = model(input_tensor) euler = utils.compute_euler_angles_from_rotation_matrices(R_pred) * 180 / np.pi pitch = euler[:, 0].cpu().numpy()[0] yaw = euler[:, 1].cpu().numpy()[0] roll = euler[:, 2].cpu().numpy()[0] # Draw visualization center_x = x_min + int(0.5 * (x_max - x_min)) center_y = y_min + int(0.5 * (y_max - y_min)) utils.plot_pose_cube(frame, yaw, pitch, roll, center_x, center_y, size=bbox_width) # Draw face box and angles cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2) cv2.putText(frame, f"Y:{yaw:.1f} P:{pitch:.1f} R:{roll:.1f}", (x_min, y_min - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) cv2.imshow("Head Pose Estimation", frame) if cv2.waitKey(1) & 0xFF == 27: # ESC to quit break cap.release() cv2.destroyAllWindows() ``` -------------------------------- ### Initialize and Use SixDRepNet for Head Pose Estimation Source: https://context7.com/thohemp/6drepnet/llms.txt Initialize the SixDRepNet model and predict head pose from an image. Pre-trained weights are downloaded automatically. Supports CPU and GPU inference. ```python from sixdrepnet import SixDRepNet import cv2 import numpy as np # Initialize model (weights downloaded automatically) # gpu_id: GPU device id, set -1 for CPU # dict_path: Optional path to local weight file model = SixDRepNet(gpu_id=0, dict_path='') # Load an image containing a face img = cv2.imread('face_image.jpg') # Predict head pose (returns pitch, yaw, roll in degrees) pitch, yaw, roll = model.predict(img) print(f"Pitch: {pitch[0]:.2f}°, Yaw: {yaw[0]:.2f}°, Roll: {roll[0]:.2f}°") # Output: Pitch: -5.23°, Yaw: 12.45°, Roll: 2.18° # Draw pose axes on the image img_with_axes = model.draw_axis(img, yaw, pitch, roll) # Display result cv2.imshow("Head Pose", img_with_axes) cv2.waitKey(0) cv2.destroyAllWindows() ``` -------------------------------- ### Create Filename List for Datasets Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Use this script to generate a file list for the 300W-LP and AFLW2000 datasets. Ensure the root directory is correctly specified. ```python python create_filename_list.py --root_dir datasets/300W_LP ``` -------------------------------- ### Test 6DRepNet Model Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Run this command to test the trained 6DRepNet model. Configure batch size, dataset, data directory, filename list, snapshot path, and visualization settings. ```sh python test.py --batch_size 64 \ --dataset AFLW2000 \ --data_dir datasets/AFLW2000 \ --filename_list datasets/AFLW2000/files.txt \ --snapshot output/snapshots/1.pth \ --show_viz False ``` -------------------------------- ### Convert 6DRepNet Model for Deployment Source: https://context7.com/thohemp/6drepnet/llms.txt This command-line instruction and Python snippet demonstrate how to convert a trained 6DRepNet model to an optimized inference format using RepVGG reparameterization. This process fuses Batch Normalization layers and removes branches, significantly improving inference speed. Ensure the input model path and desired output path are correctly specified. ```bash # Command line conversion python sixdrepnet/convert.py input-model.tar output-model.pth ``` ```python import torch from sixdrepnet.model import SixDRepNet from sixdrepnet.backbone.repvgg import repvgg_model_convert # Load training checkpoint model = SixDRepNet( backbone_name='RepVGG-B1g2', backbone_file='', deploy=False, # Training mode architecture pretrained=False ) checkpoint = torch.load('training_checkpoint.tar') model.load_state_dict(checkpoint['model_state_dict']) # Convert to deployment model (fuses BN layers, removes branches) # This significantly improves inference speed repvgg_model_convert(model, save_path='deployed_model.pth') ``` -------------------------------- ### Predict Head Pose with 6DRepNet Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Initialize the model, perform inference on an image, and visualize the results using OpenCV. ```py # Import SixDRepNet from sixdrepnet import SixDRepNet import cv2 # Create model # Weights are automatically downloaded model = SixDRepNet() img = cv2.imread('/path/to/image.jpg') pitch, yaw, roll = model.predict(img) model.draw_axis(img, yaw, pitch, roll) cv2.imshow("test_window", img) cv2.waitKey(0) ``` -------------------------------- ### Initialize Low-Level Model for Inference Source: https://context7.com/thohemp/6drepnet/llms.txt Load the low-level SixDRepNet model for advanced use cases, such as batch processing. Ensure weights are loaded separately and the model is set to evaluation mode. ```python import torch from torchvision import transforms from PIL import Image import numpy as np # Import the low-level model from sixdrepnet.model import SixDRepNet as SixDRepNetModel from sixdrepnet import utils # Initialize model for deployment (inference mode) model = SixDRepNetModel( backbone_name='RepVGG-B1g2', backbone_file='', deploy=True, # True for inference, False for training pretrained=False # Weights loaded separately ) # Load pre-trained weights from torch.hub import load_state_dict_from_url weights_url = "https://cloud.ovgu.de/s/Q67RnLDy6JKLRWm/download/6DRepNet_300W_LP_AFLW2000.pth" state_dict = load_state_dict_from_url(weights_url) model.load_state_dict(state_dict) model.eval() # Move to GPU if available device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') model.to(device) # Preprocessing pipeline transform = transforms.Compose([ transforms.Resize(224), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # Process image img = Image.open('face.jpg').convert('RGB') input_tensor = transform(img).unsqueeze(0).to(device) ``` -------------------------------- ### Train 6DRepNet on Custom Dataset Source: https://context7.com/thohemp/6drepnet/llms.txt Configures the model for training using the 300W-LP dataset and Geodesic loss. ```python import torch from torch.utils.data import DataLoader from torchvision import transforms from sixdrepnet.model import SixDRepNet from sixdrepnet.loss import GeodesicLoss from sixdrepnet import datasets # Configuration gpu_id = 0 num_epochs = 80 batch_size = 80 learning_rate = 0.0001 # Initialize model with pretrained RepVGG backbone model = SixDRepNet( backbone_name='RepVGG-B1g2', backbone_file='RepVGG-B1g2-train.pth', # Download from RepVGG repo deploy=False, # Training mode pretrained=True # Load pretrained backbone ) model.cuda(gpu_id) # Setup transforms with data augmentation normalize = transforms.Normalize( mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225] ) train_transforms = transforms.Compose([ transforms.RandomResizedCrop(size=224, scale=(0.8, 1.0)), transforms.ToTensor(), normalize ]) # Load dataset (300W-LP) # First create filename list: python create_filename_list.py --root_dir datasets/300W_LP pose_dataset = datasets.getDataset( dataset='Pose_300W_LP', data_dir='datasets/300W_LP', filename_list='datasets/300W_LP/files.txt', transformations=train_transforms, train_mode=True ) train_loader = DataLoader( dataset=pose_dataset, batch_size=batch_size, shuffle=True, num_workers=4 ) # Geodesic loss respects SO(3) manifold geometry criterion = GeodesicLoss().cuda(gpu_id) optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) scheduler = torch.optim.lr_scheduler.MultiStepLR( optimizer, milestones=[10, 20], gamma=0.5 ) ``` -------------------------------- ### Training Loop for 6DRepNet Source: https://context7.com/thohemp/6drepnet/llms.txt This snippet outlines the core training loop for the 6DRepNet model. It includes forward and backward passes, loss calculation, optimization, and checkpoint saving. Ensure the dataset, model, criterion, optimizer, and scheduler are properly initialized. ```python print(f'Starting training on {len(pose_dataset)} samples') for epoch in range(num_epochs): model.train() epoch_loss = 0.0 for i, (images, gt_rotation_matrix, _, _) in enumerate(train_loader): images = images.cuda(gpu_id) gt_rotation_matrix = gt_rotation_matrix.cuda(gpu_id) # Forward pass - model outputs rotation matrix pred_rotation_matrix = model(images) # Geodesic loss between predicted and ground truth rotation matrices loss = criterion(gt_rotation_matrix, pred_rotation_matrix) optimizer.zero_grad() loss.backward() optimizer.step() epoch_loss += loss.item() if (i + 1) % 100 == 0: print(f'Epoch [{epoch+1}/{num_epochs}], Step [{i+1}/{len(train_loader)}], ' f'Loss: {loss.item():.6f}') scheduler.step() # Save checkpoint torch.save({ 'epoch': epoch, 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), }, f'checkpoint_epoch_{epoch+1}.tar') print(f'Epoch {epoch+1} complete. Avg loss: {epoch_loss/len(train_loader):.6f}') ``` -------------------------------- ### Batch Image Processing with 6DRepNet Source: https://context7.com/thohemp/6drepnet/llms.txt Sets up the 6DRepNet model and transforms images for batch processing. It then performs a forward pass on a batch of images to estimate head poses and prints the results. ```python import torch from torchvision import transforms from PIL import Image import numpy as np from sixdrepnet.model import SixDRepNet as SixDRepNetModel from sixdrepnet import utils # Setup model model = SixDRepNetModel( backbone_name='RepVGG-B1g2', backbone_file='', deploy=True, pretrained=False ) from torch.hub import load_state_dict_from_url state_dict = load_state_dict_from_url( "https://cloud.ovgu.de/s/Q67RnLDy6JKLRWm/download/6DRepNet_300W_LP_AFLW2000.pth" ) model.load_state_dict(state_dict) model.eval().cuda() transform = transforms.Compose([ transforms.Resize(224), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # Process batch of images image_paths = ['face1.jpg', 'face2.jpg', 'face3.jpg', 'face4.jpg'] batch = torch.stack([ transform(Image.open(p).convert('RGB')) for p in image_paths ]).cuda() with torch.no_grad(): rotation_matrices = model(batch) euler_angles = utils.compute_euler_angles_from_rotation_matrices(rotation_matrices) euler_deg = euler_angles * 180 / np.pi # Results for all images for i, path in enumerate(image_paths): print(f"{path}: pitch={euler_deg[i,0]:.2f}°, " f"yaw={euler_deg[i,1]:.2f}°, roll={euler_deg[i,2]:.2f}°") ``` -------------------------------- ### Convert Trained Model for Inference Source: https://github.com/thohemp/6drepnet/blob/master/README.MD Use this script to convert trained models into inference-ready models. Specify the input model archive and the desired output path for the inference model. ```sh python convert.py input-model.tar output-model.pth ``` -------------------------------- ### Draw Head Pose Axes on Image Source: https://context7.com/thohemp/6drepnet/llms.txt Visualize head orientation by drawing RGB axes on an image. Customize the origin and size of the axes. ```python from sixdrepnet import SixDRepNet import cv2 model = SixDRepNet(gpu_id=-1) # Use CPU img = cv2.imread('face_image.jpg') pitch, yaw, roll = model.predict(img) # Draw axes at image center (default) img_result = model.draw_axis(img, yaw, pitch, roll) # Draw axes at custom position with custom size height, width = img.shape[:2] img_custom = model.draw_axis( img.copy(), yaw, pitch, roll, tdx=width // 3, # X position for axis origin tdy=height // 3, # Y position for axis origin size=150 # Length of axis lines (default: 100) ) cv2.imwrite('pose_visualization.jpg', img_result) ``` -------------------------------- ### Visualize Pose with Axes and Cubes Source: https://context7.com/thohemp/6drepnet/llms.txt Draws 3D pose axes or cubes onto an image using pose values. ```python import cv2 import numpy as np from sixdrepnet import utils # Load image img = cv2.imread('face.jpg') # Pose values in degrees yaw, pitch, roll = 15.0, -5.0, 3.0 # Draw 3D axes (simple visualization) img_axes = utils.draw_axis( img.copy(), yaw, pitch, roll, tdx=img.shape[1]//2, # Center X tdy=img.shape[0]//2, # Center Y size=100 # Axis length ) # Draw 3D pose cube (more detailed visualization) img_cube = utils.plot_pose_cube( img.copy(), yaw, pitch, roll, tdx=img.shape[1]//2, tdy=img.shape[0]//2, size=150 ) cv2.imwrite('pose_axes.jpg', img_axes) cv2.imwrite('pose_cube.jpg', img_cube) ``` -------------------------------- ### SixDRepNet.predict() Source: https://context7.com/thohemp/6drepnet/llms.txt Predicts head pose from a cropped face image and returns Euler angles in degrees. ```APIDOC ## SixDRepNet.predict() ### Description Predicts head pose from a face crop image and returns Euler angles in degrees. ### Parameters #### Request Body - **face_crop** (numpy.ndarray) - Required - BGR format image crop containing a face. ### Response - **pitch** (numpy.ndarray) - Up/Down rotation in degrees (-90 to 90). - **yaw** (numpy.ndarray) - Left/Right rotation in degrees (-90 to 90). - **roll** (numpy.ndarray) - Tilt rotation in degrees (-90 to 90). ``` -------------------------------- ### Evaluate 6DRepNet Model Performance Source: https://context7.com/thohemp/6drepnet/llms.txt This code evaluates the trained 6DRepNet model on a specified test dataset (AFLW2000 or BIWI). It loads the model, applies test transformations, and calculates Mean Absolute Error (MAE) for yaw, pitch, and roll angles. Ensure the model weights and dataset paths are correct. ```python import torch import numpy as np from torch.utils.data import DataLoader from torchvision import transforms from sixdrepnet.model import SixDRepNet from sixdrepnet import datasets, utils # Configuration gpu_id = 0 batch_size = 64 dataset_name = 'AFLW2000' # or 'BIWI' # Initialize model in deploy mode model = SixDRepNet( backbone_name='RepVGG-B1g2', backbone_file='', deploy=True, pretrained=False ) # Load trained weights checkpoint = torch.load('6DRepNet_300W_LP_AFLW2000.pth', map_location='cpu') if 'model_state_dict' in checkpoint: model.load_state_dict(checkpoint['model_state_dict']) else: model.load_state_dict(checkpoint) model.cuda(gpu_id) model.eval() # Test transforms (no augmentation) test_transforms = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # Load test dataset test_dataset = datasets.getDataset( dataset=dataset_name, data_dir=f'datasets/{dataset_name}', filename_list=f'datasets/{dataset_name}/files.txt', transformations=test_transforms, train_mode=False ) test_loader = DataLoader( dataset=test_dataset, batch_size=batch_size, num_workers=2 ) # Evaluation total = 0 yaw_error = pitch_error = roll_error = 0.0 with torch.no_grad(): for images, gt_rotation, gt_euler, names in test_loader: images = images.cuda(gpu_id) total += gt_euler.size(0) # Ground truth in degrees y_gt = gt_euler[:, 0].float() * 180 / np.pi p_gt = gt_euler[:, 1].float() * 180 / np.pi r_gt = gt_euler[:, 2].float() * 180 / np.pi # Prediction R_pred = model(images) euler_pred = utils.compute_euler_angles_from_rotation_matrices(R_pred) * 180 / np.pi p_pred = euler_pred[:, 0].cpu() y_pred = euler_pred[:, 1].cpu() r_pred = euler_pred[:, 2].cpu() # Accumulate errors (handling angle wraparound) pitch_error += torch.sum(torch.abs(p_gt - p_pred)) yaw_error += torch.sum(torch.abs(y_gt - y_pred)) roll_error += torch.sum(torch.abs(r_gt - r_pred)) # Calculate Mean Absolute Error mae_yaw = yaw_error / total mae_pitch = pitch_error / total mae_roll = roll_error / total mae_total = (yaw_error + pitch_error + roll_error) / (total * 3) print(f'Results on {dataset_name} ({total} samples):') print(f' Yaw MAE: {mae_yaw:.4f}°') print(f' Pitch MAE: {mae_pitch:.4f}°') print(f' Roll MAE: {mae_roll:.4f}°') print(f' Total MAE: {mae_total:.4f}°') # Expected output for AFLW2000: Yaw: 3.63, Pitch: 4.91, Roll: 3.37, MAE: 3.97 ``` -------------------------------- ### SixDRepNet.draw_axis() Source: https://context7.com/thohemp/6drepnet/llms.txt Draws RGB axes representing head orientation on the image. ```APIDOC ## SixDRepNet.draw_axis() ### Description Draws RGB axes representing head orientation on the image. Red=X axis, Green=Y axis, Blue=Z axis. ### Parameters #### Request Body - **img** (numpy.ndarray) - Required - The image to draw on. - **yaw** (float) - Required - Yaw angle in degrees. - **pitch** (float) - Required - Pitch angle in degrees. - **roll** (float) - Required - Roll angle in degrees. - **tdx** (int) - Optional - X position for axis origin. - **tdy** (int) - Optional - Y position for axis origin. - **size** (int) - Optional - Length of axis lines (default: 100). ### Response - **img_result** (numpy.ndarray) - The image with pose axes drawn. ``` -------------------------------- ### Convert Rotation Matrix to Euler Angles Source: https://context7.com/thohemp/6drepnet/llms.txt Converts a batch of 3x3 rotation matrices into pitch, yaw, and roll Euler angles. ```python import torch import numpy as np from sixdrepnet import utils # Assuming you have a batch of 3x3 rotation matrices # Shape: [batch_size, 3, 3] rotation_matrices = torch.randn(4, 3, 3) # Example batch # Convert to Euler angles (radians) euler_radians = utils.compute_euler_angles_from_rotation_matrices(rotation_matrices) # Shape: [batch_size, 3] -> [pitch, yaw, roll] # Convert to degrees euler_degrees = euler_radians * 180 / np.pi print(f"Euler angles (degrees):\n{euler_degrees}") ``` -------------------------------- ### Single Image Forward Pass and Euler Angle Conversion Source: https://context7.com/thohemp/6drepnet/llms.txt Performs a forward pass on a single input tensor to obtain a rotation matrix and converts it to Euler angles in degrees. Ensure the model is loaded and the input tensor is prepared. ```python with torch.no_grad(): rotation_matrix = model(input_tensor) # Shape: [batch, 3, 3] # Convert rotation matrix to Euler angles (radians) euler_rad = utils.compute_euler_angles_from_rotation_matrices(rotation_matrix) # Convert to degrees euler_deg = euler_rad * 180 / np.pi pitch = euler_deg[:, 0].cpu().numpy() yaw = euler_deg[:, 1].cpu().numpy() roll = euler_deg[:, 2].cpu().numpy() print(f"Rotation matrix:\n{rotation_matrix[0].cpu().numpy()}") print(f"Euler angles: pitch={pitch[0]:.2f}°, yaw={yaw[0]:.2f}°, roll={roll[0]:.2f}°") ``` -------------------------------- ### Convert 6D Representation to Rotation Matrix Source: https://context7.com/thohemp/6drepnet/llms.txt Converts a 6D continuous rotation representation into a 3x3 rotation matrix. ```python import torch from sixdrepnet import utils # 6D ortho representation (continuous rotation representation) # Shape: [batch_size, 6] ortho_6d = torch.randn(4, 6) # Convert to 3x3 rotation matrix rotation_matrix = utils.compute_rotation_matrix_from_ortho6d(ortho_6d) # Shape: [batch_size, 3, 3] print(f"Rotation matrix shape: {rotation_matrix.shape}") ``` -------------------------------- ### Compute Geodesic Loss Source: https://context7.com/thohemp/6drepnet/llms.txt Calculates the geodesic distance between ground truth and predicted rotation matrices on the SO(3) manifold. ```python import torch from sixdrepnet.loss import GeodesicLoss # Initialize loss function criterion = GeodesicLoss(eps=1e-7) # Example: batch of ground truth and predicted rotation matrices # Both should be orthogonal rotation matrices of shape [batch, 3, 3] batch_size = 16 gt_matrices = torch.randn(batch_size, 3, 3) # Ground truth pred_matrices = torch.randn(batch_size, 3, 3) # Predictions # Compute geodesic loss (returns angle in radians, averaged over batch) loss = criterion(gt_matrices.cuda(), pred_matrices.cuda()) print(f"Geodesic loss: {loss.item():.6f} radians") print(f"Geodesic loss: {loss.item() * 180 / 3.14159:.2f} degrees") # Use in training loss.backward() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.