packages/objdet/src/detect.nu — tiny-YOLOv2 detection head.
Decodes the [1,125,13,13] grid the network produces into boxes: each of the 13×13 cells predicts 5 anchor boxes, each carrying (tx,ty,tw,th,to)
sigmoid/exp; the score is objectness × softmax(class). Overlapping boxes of the same class are then removed by non-max suppression.
& c @ nurl_peek_f32 *u base i idx → f: Detection { i cls f score f cx f cy f w f h }A detection in normalised (0..1) centre/size coordinates.
@ sigmoid f x → f@ voc_class i i → sVOC 2007 20 classes (tiny-yolov2 order). Static literals — the old version built a fresh Vec String per call and returned a borrow into it (leaked the vector every lookup).
@ yolo_decode * u grid f thresh → ( Vec Detection )Decode the grid into detections above thresh.
@ yolo_nms ( Vec Detection ) dets f iou_thresh → ( Vec Detection )Non-max suppression: sort by score, greedily keep, drop same-class boxes overlapping a kept box by more than iou_thresh.
packages/objdet/src/image.nu — detector-facing adapter over packages/image.
The codecs and raster ops live in the image package (PNG/JPEG/PPM decode, bilinear resize, rectangle drawing — see deps/image); this file keeps only what is detector-specific: loading ANY supported format as guaranteed-RGB, saving by extension, saturating pixel stores, and packing to the NCHW float tensor the model consumes. The Image type is the image package's (width/height/channels/data).
& c @ nurl_poke_f32 *u base i idx f val → v@ img_w Image im → i@ img_h Image im → i@ img_blank i w i h → ImageA blank (black) RGB image.
@ img_get Image im i x i y i ch → i@ img_set Image im i x i y i ch i val → vSaturating store (image_set masks to the low byte; the detector's callers pass computed values that must clamp, not wrap).
@ img_resize Image im i nw i nh → Image@ img_load s path → ?ImageLoad any supported format (PNG / baseline+progressive JPEG / PPM) as 3-channel RGB. On None, ( image_error ) says why.
@ img_save s path Image im → bSave by extension: .png / .jpg / .jpeg (quality 90) / anything else = PPM.
@ img_draw_rect Image im i x0 i y0 i x1 i y1 i r i gg i bb → vDraw a thickness-2 rectangle outline in the given colour.
@ img_to_nchw Image im → *u── pack to NCHW float tensor (values 0..255) ───────────────────── Writes a fresh host buffer of 3HW floats in CHW order; the model's in-graph preprocessor scales by 1/255.
packages/objdet/src/main.nu — object detection from pure NURL on the GPU.
objdet <model.onnx> <image.{png,jpg,ppm}> [out.{png,jpg,ppm}] objdet <model.onnx> --video <in_dir> <out_dir> <count>
Loads any tiny-YOLOv2-style ONNX detector (e.g. the ONNX model-zoo tinyyolov2-8.onnx), runs it on the GPU through packages/onnx, decodes the grid into labelled boxes (packages objdet/detect), prints them, and (for an image) writes an annotated image. Stills are read/written natively via packages/image (PNG, baseline+progressive JPEG, PPM) — no ImageMagick. The video mode runs a frame sequence frame00000.ppm … reusing one GPU engine (kernels compiled once); use ffmpeg for the container: ffmpeg -i clip.mp4 -vf fps=10 in/frame%05d.ppm ffmpeg -framerate 10 -i out/frame%05d.ppm out.mp4
@ p s m → v@ pf f x → v@ pn i n → v@ streqm s a s b → b@ shape4 i a i b i c i d → ( Vec i )@ detect_image * Engine e OGraph g Image im f conf f iou → iRun the detector on one image, draw boxes in place, print detections. Returns the number of detections.
@ load_model s path * u pok → OGraph@ frame_path s dir i n → Stringframe path: <dir>/frameNNNNN.ppm
@ main → i