Can an object detector look for categories you describe in words? In this Python tutorial we use a pretrained YOLO-World model and an image, choose text labels, and inspect the bounding boxes it returns. We then change the label list and run the model again.
Our example uses a synthetic office image from my course and a local Windows CPU run. With one list the model returned four predictions; with an expanded list it returned nine predictions. Those counts are model outputs, not verified counts of real objects or proof of accuracy.
Watch the YOLO-World tutorial
Watch the full Python tutorial or see the short demonstration.

What does “no training needed” mean?
YOLO-World is an open-vocabulary object detector: it can accept text class names before prediction. Here we load pretrained YOLO-World and CLIP components and do not train them again. They were trained earlier; “no additional training” does not mean that the model learned from nothing. It also does not guarantee detection of every item or phrase. See the Ultralytics YOLO-World documentation and the original research paper.
What you need
The demonstrated run used Windows 11, Python 3.13.9, Ultralytics 8.4.116, PyTorch 2.13.0+cpu, OpenCV 4.14.0 and NumPy 2.5.1. It used the local YOLOv8s-World checkpoint and the OpenAI CLIP ViT-B/32 text encoder. The installation commands pin Ultralytics and the CLIP fork, not every transitive dependency. Other software versions or devices can change the results. Git is needed for the command that installs the fork from its repository.
From a Windows Command Prompt, create a project folder, then create and install into its virtual environment:
py -3.13 -m venv .venv
.venv\Scripts\python.exe -m pip install ultralytics==8.4.116
.venv\Scripts\python.exe -m pip install "git+https://github.com/ultralytics/CLIP.git@488e81a6711eea7346872b46ea928b367da8889d"
The tested course package includes an already built source-bound wheel for the CLIP fork. The Git-based installation above is an alternative way to get the identified source; this exact fresh online installation was not part of the offline replay. Installing packages and obtaining the files requires a network connection unless you have them available locally.
Prepare the local image and weights
Save the two scripts below next to a permitted image called image.png. The shown image is supplied with lesson 47 of my Computer Vision course. For your own image, the detections and numbers will differ. Download the official Ultralytics YOLOv8s-World checkpoint and the OpenAI CLIP ViT-B/32 checkpoint separately. The latter URL appears in the OpenAI CLIP model registry. Place them as follows:
yolo-world-demo/
├── setup_local.py
├── world_demo.py
├── image.png
├── yolov8s-world.pt
└── weights/
└── clip/
└── ViT-B-32.pt
The tested detector checkpoint SHA-256 is 095f5266bb9b654bd5ad9e21e9cdeda78e0f2c8460f5d652eaf04bab7ee251cf; the CLIP file SHA-256 is 40d365715913c9da98579312b702a82c18be219cc2a73407c4526f58eba950af. A hash identifies bytes; it does not itself establish usage rights. Model files are not hosted by this article.
Configure a project-local weights folder
The text encoder must find its local CLIP checkpoint when the class names are set. Run the following small setup script once, as a separate process. It places Ultralytics settings in this project’s config folder and sets its weights directory to this project’s weights folder. This avoids editing your user-wide Ultralytics settings for the demonstration.
Save as setup_local.py:
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright (c) 2026 ARTSCI - Author of the AI/ML/CV course materials.
"""Store an isolated Ultralytics weights-directory setting for this example."""
from pathlib import Path
import os
ROOT = Path(__file__).resolve().parent
config_dir = ROOT / 'config'
config_dir.mkdir(exist_ok=True)
os.environ['YOLO_CONFIG_DIR'] = str(config_dir)
import cv2 # Import first in the demonstrated Windows environment.
from ultralytics import settings
settings.update({'weights_dir': str(ROOT / 'weights'), 'sync': False})
print('Project weights directory:', ROOT / 'weights')
print('Run world_demo.py as a separate process after this one exits.')
Run it from the project directory:
.venv\Scripts\python.exe setup_local.py
Then start the following script as a new process so the weights-directory setting is read during initialization. If you move the project folder later, run the setup script again before prediction.
Complete runnable example
Save the following as world_demo.py:
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright (c) 2026 ARTSCI - Author of the AI/ML/CV course materials.
"""Compare two text vocabularies with a local pretrained YOLO-World model."""
from pathlib import Path
import os
ROOT = Path(__file__).resolve().parent
# Keep Ultralytics settings in this project, not in your user-wide profile.
config_dir = ROOT / 'config'
config_dir.mkdir(exist_ok=True)
os.environ['YOLO_CONFIG_DIR'] = str(config_dir)
os.environ['YOLO_OFFLINE'] = 'true'
import cv2 # Import first in the demonstrated Windows environment.
import torch
from ultralytics import YOLOWorld
from ultralytics.utils import WEIGHTS_DIR
def main():
image = ROOT / 'image.png'
model_file = ROOT / 'yolov8s-world.pt'
clip_file = ROOT / 'weights' / 'clip' / 'ViT-B-32.pt'
if Path(WEIGHTS_DIR).resolve() != (ROOT / 'weights').resolve():
raise RuntimeError('Configure this project weights directory first; see the setup command.')
for path in (image, model_file, clip_file):
if not path.is_file():
raise FileNotFoundError(f'Required local file: {path}')
torch.set_num_threads(4)
model = YOLOWorld(str(model_file))
groups = {
'focused': ['person', 'backpack', 'laptop', 'cup'],
'broad': ['person', 'backpack', 'laptop', 'cup', 'chair', 'desk'],
'single_cup': ['cup'],
'single_coffee_cup': ['coffee cup'],
}
output = ROOT / 'output'
output.mkdir(exist_ok=True)
for name, classes in groups.items():
model.set_classes(classes)
result = model.predict(
source=str(image), conf=0.25, iou=0.70, imgsz=640, device='cpu',
half=False, rect=True, augment=False, agnostic_nms=False,
max_det=300, verbose=False,
)[0]
print(f'\n{name}: {classes} -> {len(result.boxes)} predictions')
for box in result.boxes:
label = result.names[int(box.cls.item())]
score = float(box.conf.item())
coords = [round(float(v), 1) for v in box.xyxy[0].tolist()]
print(f' {label}: score={score:.3f} xyxy={coords}')
annotated = result.plot()
if not cv2.imwrite(str(output / f'{name}.png'), annotated):
raise OSError(f'Could not save output for {name}')
print(f'\nSaved annotated images in {output}')
if __name__ == '__main__':
main()
From the project directory, run:
.venv\Scripts\python.exe world_demo.py
For each vocabulary, model.set_classes(classes) configures the class names with the CLIP text encoder. model.predict(...)[0] then runs a new prediction on the image; the subsequent loop reads its boxes. The code saves an annotated image per vocabulary to output/. The illustrations on this page are the actual saved outputs from the demonstrated execution, using Ultralytics’ plotting style.
All four runs use the same input image and checkpoint, conf=0.25, iou=0.70, imgsz=640 and CPU. The two standalone prompts are separate one-class vocabularies; the focused and broad lists are separate runs too. Changing the list can change predictions and scores for shared classes, so the broad result should not be treated as simply appending new boxes to an unchanged prior result. Confidence is a model score, not a calibrated probability that a particular box is correct.
Read the result: focused versus broad
The focused list asks for person, backpack, laptop and cup. In the recorded execution it returned four predictions. The broad list retains those words and adds chair and desk; it returned nine predictions. The change in count does not establish that every additional prediction is correct.

For example, the expanded run includes a desk box scoring approximately 0.286 over a region that appears to contain a chair. Another nearby chair prediction overlaps the region. This is a reason to inspect the image and outputs, not evidence that every overlap is a duplicate. Changing the vocabulary also changed the laptop score from about 0.924 to 0.909 in this particular run.
Does wording matter?
We also tried two separate one-class runs on the same image. With ["cup"] the model returned one prediction with score approximately 0.917. With ["coffee cup"] it returned one prediction around the same visible item with score approximately 0.830. These two scores and boxes are observations for this image and these prompts; they do not prove that either phrase is generally better or measure accuracy. Inspect the predictions before relying on them.
Try it yourself
- Choose an image you have permission to use and predict which objects you expect the model to find.
- Change just one class name or list in
groups, run the script again, and inspect the saved image and printed rows. - Compare false positives, missed objects and scores. Keep the input and other settings fixed if you want an interpretable comparison.
For a real application, test a representative labelled set covering the relevant objects, viewpoints and conditions. This single synthetic scene is not an accuracy benchmark, a validated real-time system or a surveillance application. The OpenAI CLIP model card discusses research scope, limitations and potential bias.
Troubleshooting
- “Configure this project weights directory first”: run
setup_local.pyfrom the same project and then startworld_demo.pyin a separate process. Re-run setup after moving the project. - Missing checkpoint or image: inspect the file paths shown above; the script checks them before model initialization.
- CLIP import or installation problem: verify that the tested Ultralytics CLIP fork is installed in this virtual environment, and that the correct kernel or Python executable is used. The separately named PyPI
clipproject is not a substitute for the specified fork. - No detection or an unexpected box: check the input, class wording, visible output and threshold. A lower threshold may show additional weak candidates, but does not automatically improve correctness.
Sources and license
Both complete example scripts on this page are © 2026 ARTSCI - Author of the AI/ML/CV course materials, licensed under GNU AGPL-3.0 only, without warranty. Preserve applicable notices and provide corresponding source when sharing covered modifications. This code notice does not automatically license the course image, narration or video.
Ultralytics software and models retain their own terms; see the Ultralytics assets license and licensing information. Ultralytics states that its YOLO-World weights were migrated from the original YOLO-World project, which describes its own code as GPL-3.0. The Ultralytics CLIP fork and original OpenAI CLIP code have separate license texts; consult the upstream sources and model card for the specific components and your use.
To compare this prompt-based approach with adapting a model on labelled images, see how to fine-tune YOLO on your own images. The full English course covers these ideas and other projects: Computer Vision: OpenCV, Machine Learning and YOLO.
















