Usage¶
This guide explains how ovkit works and how to use each part. ovkit wraps
OpenVINO behind a single Model object: you give it a model name
or file and call it on an image, and it returns a clean Results
container. Everything in between — downloading, converting to OpenVINO IR,
caching, compiling for a device, detecting the task, pre/post-processing — is
handled for you.
Install¶
Install from PyPI:
pip install ovkit # core (lightweight)
pip install "ovkit[quant]" # + NNCF INT8 quantization
pip install "ovkit[genai]" # + openvino-genai (LLM / STT)
pip install "ovkit[all]" # everything
For development, install from source instead:
git clone https://github.com/leeyunjai82/ovkit.git && cd ovkit
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]" # editable: `git pull` updates in place
Python 3.10+ is required. The core
dependencies are kept light — openvino, numpy, opencv-python-headless,
pillow, pyyaml, huggingface_hub — and heavier pieces (NNCF, openvino-genai,
anomalib) are optional extras you opt into with [...].
Loading a model¶
from ovkit import Model
model = Model("rtdetr_r50") # registered name -> auto download + convert + cache
model = Model("path/to/model.xml") # an OpenVINO IR file
model = Model("path/to/model.onnx") # an ONNX file -> converted to IR on first use
There are three ways to name a model:
A registered name (e.g.
"rtdetr_r50") — looked up in the model registry (a YAML manifest). On first use the model is downloaded from its source, converted to OpenVINO IR if needed, and cached under~/.cache/ovkit. Later runs load straight from the cache.An IR path (
.xml) — used directly.An ONNX path (
.onnx) — OpenVINO reads/converts it on load.
Task auto-detection¶
ovkit figures out the model’s task so it can attach the right decoder. It
tries, in order: the task field in the manifest → the IR rt_info metadata →
a heuristic on the output tensor shapes. If it can’t decide, pass it explicitly:
model = Model("some_model.xml", task="detect") # detect | classify | segment | pose | ocr
Vision tasks (detect, classify, segment, pose,
optical_character_recognition) get a typed decoder; any other task falls back
to a generic adapter that returns the raw output tensors.
Predicting¶
Calling the model (model(x)) is the same as model.predict(x). The input
type is auto-detected:
results = model("img.jpg", device="NPU", conf=0.25) # an image file
results = model.predict("frames/", imgsz=640) # a folder of images
results = model.predict("clip.mp4") # a video file
for r in model.predict(0, stream=True): # webcam (camera index)
annotated = r.plot()
sourcecan be an image path, anumpyarray (HWC BGR), a folder, a video file, or a camera index (int).confis the confidence threshold for detection/instance tasks.stream=Truereturns a lazy generator (use it for video or large folders so frames are processed one at a time); otherwise you get alistofResults.
Non-image inputs are routed to raw inference automatically: a .npy tensor, a
.wav file, or a non-image ndarray is fed straight to the model and the raw
{name: ndarray} outputs are returned (see low-level).
Working with Results¶
A Results bundles the original image, the task, and whichever output the task
produced. Use r.plot() for an annotated image and r.save(path) to write it.
r = results[0]
r.boxes.xyxy # (N, 4) pixel boxes [x1, y1, x2, y2]
r.boxes.conf # (N,) confidence scores
r.boxes.cls # (N,) class ids
r.name_for(2) # "car" (class id -> name)
annotated = r.plot() # -> annotated ndarray (boxes/masks/keypoints/text drawn)
r.save("out.jpg")
Attribute |
Task |
Contents |
|---|---|---|
|
detect |
|
|
segment |
|
|
pose |
|
|
classify |
|
|
ocr |
decoded string |
|
generic |
raw |
Low-level — any model¶
For models that don’t take an image (NLP / audio / time-series, multiple
inputs), build the input tensors yourself and call infer():
m = Model("bert_small_uncased_whole_word_masking_squad_0002")
print(m.inputs) # [(name, shape, dtype), ...]
out = m.infer({"input_ids": ids, "attention_mask": mask}) # {name: ndarray}
m.inputs tells you exactly what tensors the model expects.
Devices¶
device="AUTO" (default) lets OpenVINO pick the best available device; "CPU",
"GPU", and "NPU" (Intel® Core™ Ultra and similar) are explicit. Set it on the
Model or override it per call. Single images run synchronously; stream=True
uses an AsyncInferQueue for throughput on video and multi-stream workloads.
from ovkit.core.backend import available_devices
print(available_devices()) # e.g. ['CPU', 'GPU', 'NPU']
Quantization (INT8)¶
Post-training quantization shrinks a model and speeds it up by converting weights/activations to INT8, using a handful of representative images to calibrate:
model.quantize(calib_images, preset="int8") # NNCF PTQ; the INT8 IR is cached
r = model("img.jpg") # now served from the INT8 model
Requires pip install "ovkit[quant]".
CLI¶
ovkit run detect img.jpg # one-shot inference (prints + saves img_out.jpg)
ovkit list # registered models (name / task / license)
ovkit info rtdetr_r50 # source, task, license, precision
ovkit download rtdetr_r50 # fetch + convert to IR (warm the cache)
ovkit devices # available OpenVINO devices
The model registry¶
Models live in YAML manifests (src/ovkit/manifests/*.yaml), separate from the
code, so adding a model is a one-line edit — no Python changes:
rtdetr_r50:
src: hf # hf | url | genai
repo: leeyunjai/ovkit-models
filename: detect/rtdetr_r50/model.xml
task: detect
precision: fp16
license: apache-2.0 # required; must be permissive
fallback: # optional: tried if the primary source fails
src: hf
repo: onnx-community/rtdetr_r50vd
filename: onnx/model.onnx
Model("name") resolves in this order: a local path → a cached IR under
$OVKIT_HOME → download from the manifest source → convert to IR → cache. It is
built to be robust: atomic writes (download to a temp file, rename on
success), optional sha256 integrity checks, convert-once caching keyed
by (name, precision), an upstream fallback when the primary source is down,
and an offline mode.
Environment variables¶
Variable |
Meaning |
|---|---|
|
Cache root (default |
|
|
|
Extra manifest files/dirs ( |
GenAI (LLM / STT / TTS)¶
Modern OpenVINO generative models are handled by openvino-genai, re-exposed
through ovkit.genai (separate from the vision pipeline). Install the extra and
call pipeline(name):
from ovkit.genai import pipeline
llm = pipeline("tinyllama_chat") # downloads + builds the pipeline
print(llm.generate("Explain OpenVINO in one sentence.", max_new_tokens=64))
stt = pipeline("whisper_base") # speech-to-text
print(stt.generate(audio_16k_mono_float32))
Registered genai models live in src/ovkit/manifests/genai.yaml. Needs
pip install "ovkit[genai]".
License policy¶
ovkit is Apache-2.0 and stays license-clean:
No AGPL-3.0 model stacks in dependencies or default models.
Detection defaults are the DETR family (RT-DETR, RT-DETRv2, D-FINE, RF-DETR) — all Apache-2.0.
Face models come from Apache-2.0 OMZ weights on the ovkit HF mirror
leeyunjai/ovkit-models(not the deprecatedomz_downloader).No InsightFace pretrained weights — non-commercial; architecture reference only. This is why
face_recognition_resnet100_arcface_onnxis skipped when mirroring OMZ public even though OMZ labels it Apache-2.0: that licence covers the packaging, not the InsightFace-derived weights.Every manifest entry must declare a permissive
license; non-permissive entries are refused at load time.