Files
vision-anti-pinch/orin/pipeline/native_backend.py
T

67 lines
3.1 KiB
Python

"""Native Jetson TensorRT adapter; temporal/risk policy stays in upstream Python."""
from __future__ import annotations
import ctypes as C
from pathlib import Path
import numpy as np
ROOT = Path(__file__).resolve().parents[1]
class NativeBackend:
def __init__(self, args):
self.lib = C.CDLL(str(ROOT / 'build/libvision_native.so'))
pointer = C.c_void_p
signatures = {
'vap_error': ([], C.c_char_p),
'vap_engine': ([C.c_char_p,C.c_int,C.c_int,C.c_int,C.c_float],pointer),
'vap_engine_close': ([pointer],None),
'vap_detect': ([pointer,pointer,C.c_int,C.c_int,pointer],C.c_int),
'vap_pose': ([pointer,pointer,C.c_int,C.c_int,pointer,C.c_int,pointer],C.c_int),
'vap_camera': ([C.c_char_p,C.c_int,C.c_int,C.c_int,C.c_int],pointer),
'vap_camera_close': ([pointer],None),
'vap_read': ([pointer,pointer,pointer],C.c_int),
'vap_can': ([pointer],None),
}
for name,(inputs,output) in signatures.items():
fn=getattr(self.lib,name);fn.argtypes=inputs;fn.restype=output
self.engine = self.lib.vap_engine(str(args.engines.resolve()).encode(),args.width,args.height,args.max_people,args.det_conf)
if not self.engine: self.fail()
self.camera=None
self.args=args
def fail(self):
raise RuntimeError(self.lib.vap_error().decode())
def open_camera(self):
a=self.args
self.camera=self.lib.vap_camera(a.camera.encode(),a.width,a.height,a.fps,not a.no_can)
if not self.camera:self.fail()
def read(self):
image=np.empty((self.args.height,self.args.width,3),np.uint8)
meta=np.zeros(4,np.float64)
result=self.lib.vap_read(self.camera,image.ctypes.data,meta.ctypes.data)
if result<0:self.fail()
if result==0:return None,None
return image,{'sequence':int(meta[0]),'capture_monotonic_ms':float(meta[1]),'dropped_before_inference':int(meta[2]),'driver_timestamp_ms':float(meta[3]),'latency_clock':'host_monotonic_at_dequeue'}
def can_snapshot(self):
data=np.zeros(5,np.float64);self.lib.vap_can(data.ctypes.data)
return {'positions':[int(x) for x in data[:4]],'age_ms':float(data[4])}
def detect(self, frame):
frame=np.ascontiguousarray(frame);out=np.empty((self.args.max_people,5),np.float32)
n=self.lib.vap_detect(self.engine,frame.ctypes.data,frame.shape[1],frame.shape[0],out.ctypes.data)
if n<0:self.fail()
return out[:n,:4].tolist(),out[:n,4].tolist()
def pose(self,frame,bboxes):
frame=np.ascontiguousarray(frame);boxes=np.ascontiguousarray(bboxes,dtype=np.float32)
out=np.empty((len(boxes),133,3),np.float32)
n=self.lib.vap_pose(self.engine,frame.ctypes.data,frame.shape[1],frame.shape[0],boxes.ctypes.data,len(boxes),out.ctypes.data)
if n<0:self.fail()
return out[:n,:,:2].astype(np.float64),out[:n,:,2].astype(np.float64)
def close(self):
if self.camera:self.lib.vap_camera_close(self.camera);self.camera=None
if self.engine:self.lib.vap_engine_close(self.engine);self.engine=None