raft testing

This commit is contained in:
bluepulsar
2026-01-31 21:26:53 +08:00
parent d750a039fe
commit 93e0847db6
5 changed files with 34 additions and 13 deletions
+1
View File
@@ -11,3 +11,4 @@ orisys.egg-info/
/dist_nuitka/ /dist_nuitka/
/build_nuitka /build_nuitka
/data/ /data/
/models/
+15 -2
View File
@@ -50,14 +50,27 @@ def track_raft(prev_frame, frame, model, device):
curr_tensor = torch.from_numpy(gray.transpose(2, 0, 1).astype(np.float32) / 255.0) curr_tensor = torch.from_numpy(gray.transpose(2, 0, 1).astype(np.float32) / 255.0)
prev_tensor = preprocess(prev_tensor.unsqueeze(0), resize=None).to(device) prev_tensor = preprocess(prev_tensor.unsqueeze(0), resize=None).to(device)
curr_tensor = preprocess(curr_tensor.unsqueeze(0), resize=None).to(device) curr_tensor = preprocess(curr_tensor.unsqueeze(0), resize=None).to(device)
t0 = time.perf_counter()
with torch.no_grad(): with torch.no_grad():
flow = model(prev_tensor, curr_tensor) flow = model(prev_tensor, curr_tensor)
predicted_flows = flow[-1] predicted_flows = flow[-1]
t1 = time.perf_counter()
print(f"RAFT time: {t1 - t0}")
flow_np = predicted_flows[0].cpu().numpy() # or .squeeze(0) flow_np = predicted_flows[0].cpu().numpy() # or .squeeze(0)
# Transpose to (H, W, 2) format expected by draw_arrows # Transpose to (H, W, 2) format expected by draw_arrows
flow_np = flow_np.transpose(1, 2, 0) # (2, H, W) -> (H, W, 2) flow_np = flow_np.transpose(1, 2, 0) # (2, H, W) -> (H, W, 2)
# torch.onnx.export(
# model, # model to export
# (prev_tensor, curr_tensor), # inputs of the model,
# "my_model.onnx", # filename of the ONNX model
# input_names=["prev_tensor", "curr_tensor"], # Rename inputs for the ONNX model
# dynamo=True # True or False to select the exporter to use
# )
# print("ONNX model exported successfully")
return flow_np return flow_np
def main_simple(): def main_simple():
@@ -66,7 +79,7 @@ def main_simple():
model = setup_simple_raft() model = setup_simple_raft()
device = "cuda" if torch.cuda.is_available() else "cpu" device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}") print(f"Using device: {device}")
cap = cv2.VideoCapture(0) cap = cv2.VideoCapture("s1.mp4")
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

+2 -2
View File
@@ -2,11 +2,11 @@
"name": "prototype", "name": "prototype",
"version": "1.0", "version": "1.0",
"camera": { "camera": {
"resolution_raw": [1920, 1080], "resolution_raw": [960, 540],
"fps": 30, "fps": 30,
"units": 15, "units": 15,
"units_used": 9, "units_used": 9,
"resolution_stitch": [400, 400] "resolution_stitch": [200, 200]
}, },
"stitcher": { "stitcher": {
"min_area_frac": 0.01, "min_area_frac": 0.01,
+13 -6
View File
@@ -2,7 +2,8 @@ import cv2
import numpy as np import numpy as np
import torch import torch
import torchvision.transforms as T import torchvision.transforms as T
from torchvision.models.optical_flow import raft_large from torchvision.models.optical_flow import raft_large, raft_small
import time
class Tracker: class Tracker:
def __init__(self, def __init__(self,
@@ -54,6 +55,7 @@ class Tracker:
self.__upper_threshold = config_tracker["upper_threshold"] # error greater than threshold will add new reference frame self.__upper_threshold = config_tracker["upper_threshold"] # error greater than threshold will add new reference frame
### RAFT ### RAFT
self.__raft_device = "cuda" if torch.cuda.is_available() else "cpu" self.__raft_device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"RAFT device: {self.__raft_device}")
self.__raft_model = self.setup_simple_raft() self.__raft_model = self.setup_simple_raft()
self.__raft_ref_frame = None self.__raft_ref_frame = None
self.__raft_ref_tensor = None self.__raft_ref_tensor = None
@@ -250,7 +252,7 @@ class Tracker:
model = model.eval() model = model.eval()
# Optimize matmul precision for faster inference (TF32 on Ampere+ GPUs) # Optimize matmul precision for faster inference (TF32 on Ampere+ GPUs)
torch.set_float32_matmul_precision('medium') # torch.set_float32_matmul_precision('medium')
# Enable CUDA-specific optimizations # Enable CUDA-specific optimizations
if self.__raft_device == 'cuda': if self.__raft_device == 'cuda':
@@ -296,7 +298,6 @@ class Tracker:
# Add batch dimension # Add batch dimension
tensor = tensor.unsqueeze(0) tensor = tensor.unsqueeze(0)
# Keep in float32 - autocast will handle mixed precision during inference
return tensor return tensor
def track_raft(self, frame): def track_raft(self, frame):
@@ -319,9 +320,11 @@ class Tracker:
prev_tensor = self.__raft_ref_tensor prev_tensor = self.__raft_ref_tensor
curr_tensor = self._preprocess_frame_to_tensor(frame) curr_tensor = self._preprocess_frame_to_tensor(frame)
# OPTIMIZATION: Remove CUDA stream since immediate sync eliminates async benefit # Synchronize before timing to ensure preprocessing is complete
# The bottleneck is inference, not data transfer (already optimized with pin_memory) if self.__raft_device == 'cuda':
with torch.no_grad(): torch.cuda.synchronize()
with torch.inference_mode():
if self.__raft_device == 'cuda': if self.__raft_device == 'cuda':
with torch.amp.autocast('cuda'): with torch.amp.autocast('cuda'):
flow = self.__raft_model(prev_tensor, curr_tensor) flow = self.__raft_model(prev_tensor, curr_tensor)
@@ -329,6 +332,10 @@ class Tracker:
flow = self.__raft_model(prev_tensor, curr_tensor) flow = self.__raft_model(prev_tensor, curr_tensor)
predicted_flows = flow[-1] predicted_flows = flow[-1]
# Synchronize after inference to get accurate timing
if self.__raft_device == 'cuda':
torch.cuda.synchronize()
# Optimize tensor->numpy conversion: contiguous() ensures optimal memory layout # Optimize tensor->numpy conversion: contiguous() ensures optimal memory layout
flow_np = predicted_flows[0].contiguous().cpu().numpy() flow_np = predicted_flows[0].contiguous().cpu().numpy()