Sitemap

Getting Started with Object Detection: Concepts, Metrics and YOLOv8 in Python

8 min readOct 30, 2026

--

Note: I wrote this article as part of my own learning journey in computer vision. It’s meant for beginners who, like me, are just getting started with object detection. The concepts and code here are based on the Object Detection course by Murtaza’s Workshop — Robotics and AI on YouTube, which I followed while learning. I’ve added my own explanations and notes along the way, but full credit for the original course and project structure goes to Murtaza’s Workshop. If you want to learn this properly, I highly recommend watching the course yourself.

Object Detection is a Computer Vision technique for locating objects in an image or a video. Object detection gives us the bounding box information of the object (such as x, y, width, height) as well as classification of the object (like dog and cat).

Object detection showing the bounding box as well as classification of the object

Difference Between Object Classification, Object Detection and Object Segmentation

Object Classification: Object classification is a type of image recognition that identifies what type of object is present in an image. Here, the complete image is sent for classification, so the output is a single class.

Object Detection: Object detection is a type of image recognition that is used to identify and locate the presence of an object in the image. This gives us the bounding box information and the class as well. Here, the result can be multiple bounding boxes and classes.

Object Segmentation: It is a type of image recognition that is used to identify and separate the distinct objects in an image on a pixel level. We can get the exact shape of object detected rather than just the bounding box. Segmentation gives more detailed information than detection.”.

Press enter or click to view image in full size
Image showing the difference between object classification, object detection and object segmentation

A Brief History of Object Detection

Research on object detection began in the 1970s. Researchers started to develop the automated methods for object detection. The first automated object detection algorithm was based on simple features such as edges and corners. The first real-time object detector was Viola Jones developed in 2001. Viola Jones is a face detection algorithm published by Paul Viola and Michael Jones that detected faces in real time on an ordinary hardware. It used sliding windows to search for Haar-like features, which are simply rectangular features. This method was used for many years for face detection in smartphones and cameras.

The Histogram of Oriented Gradients was another method released in 2005. It focused on the shape of the object. It worked by extracting the gradient and orientation of the objects. This method was generally used to detect humans in an image.

Then came the revolution of AI with neural networks. The true potential was seen with Convolutional Neural Networks when AlexNet won the ImageNet Large Scale Visual Recognition Challenge (ILSVRC) in 2012. This however solved the classification problem and not the detection. Later Brute force methods were used to repurpose the CNN models to work as detection model. This was very inefficient approach, so later came the RCNN (Regions with Convolutional Neural Network) model, that used selective search to propose around 2,000 regions and ran a CNN on each one. Then later came the Fast R-CNN and Faster R-CNN, which were faster but still not real time.

In 2015 came the breakthrough of YOLO. This was far faster than earlier models while keeping competitive accuracy, making real-time detection possible. This used the single pass of input image to make predictions of the objects. Methods like RCNN ran the classifier separately on many proposed regions of the same image. While, YOLO gets it done in a single iteration. This makes YOLO more efficient even though the architecture of YOLO is based on convolutional layers similar to its predecessors.

Performance Evaluation Metrics

In order to evaluate our object detection models, there are two main metrics. First is to evaluate how good is the location and the second to evaluate how good is the classification.

I. IoU: measures overall detection performance

II. mAP: used for classification

IoU (Intersection Over Union)

It tells us how close the predicted bounding box is to the ground truth. Its a value between 0 and 1. If the two boxes overlap completely, it’s a perfect detection with an IoU of 1.If the boxes have some overlap, then the values are between 0 and 1, depending on how much the overlap is. However, if there is no overlap between the boxes, the IoU is 0.

Press enter or click to view image in full size
Images showing different criteria for IoU
Formula for IoU

IOU = Area of Overlap / Area of Union

mAP (mean Average Precision)

To understand the average precision, we need to know about the confusion matrix, precision and recall.

Get Dibika Dahal’s stories in your inbox

Join Medium for free to get updates from this writer.

Confusion matrix is a simple table that consists of actual classes on one side and the predicted classes on the other. It evaluates the performance of a machine learning classification model by comparing its predicted labels against the actual ground truth values.

Confusion matrix

Precision is defined as the correctly predicted positives out of total positive predictions.

Precision = TP / (TP + FP)

Recall is defined as the correctly predicted positives out of total actual positives.

Recall = TP / (TP + FN)

Both precision and recall provide valuable information, so we combine them into a single metric called Average Precision (AP). To compute it, we sweep through all the confidence thresholds, calculate precision and recall at each one, and plot them as a precision-recall curve. AP is the area under this curve. Because it captures the trade-off between precision and recall across every threshold, it gives a better idea of the model’s overall performance than either metric alone. This AP value is for a single class. If we have multiple classes, we calculate AP for each class and take their mean, which is called mean Average Precision (mAP).

Precision-Recall curve

Running YOLO

Ultralytics

Ultralytics is a company, and also the name of its Python package, that builds and maintains the most widely used versions of YOLO (including YOLOv5, YOLOv8, YOLOv11) and also gives a simple way to use them.

YOLO itself is just a family of detection models. The original YOLO was written by Joseph Redmon in Darknet, a framework written in C, which was hard to setup and train. Ultralytics reimplemented YOLO in PyTorch and wrapped everything in a clean API so that all the hard parts (such as: model architecture, pre-trained weights, data loading, augmentation, training loop, loss functions, evaluation metrics and exporting to other formats) were already done.

cv2

cv2 is the Python module name for OpenCV which is the most widely used library for working with images and videos. OpenCV handles most of the everyday image work around a model. It reads and saves an image (cv2.imread, cv2.imwrite), captures video from files or a webcam (cv2.VideoCapture), and displays results in windows (cv2.imshow). It also processes images: resizing, cropping, rotating, converting between color formats, blurring, sharpening and thresholding. On top of that, it has classic computer vision algorithms like edge detection (Canny), contour finding, feature matching and camera calibration. It even includes the Viola-Jones face detector as cv2.CascadeClassifier. And it can draw rectangles, circles and text on images, which is how bounding boxes get drawn.

Basic Image Detection with YOLOv8 and OpenCV

from ultralytics import YOLO
import cv2

model = YOLO('yolov8n.pt')
results = model("Images/1.png")
annotated = results[0].plot()
cv2.imshow("YOLO Detection", annotated)
cv2.waitKey(0)
cv2.destroyAllWindows()

cvzone

cvzone is a helper library built on top of OpenCV and MediaPipe, made by Murtaza Hassan. It does not add new computer vision abilities but just wraps common tasks into short, easy functions. Functions like cvzone.cornerRect() draws bounding boxes with highlighted corners, and cvzone.putTextRect() puts a label inside a filled rectangle so that it’s readable on any background. cvzone also provides with the readymade modules for MediaPipe features: such as hand tracking, face detection, face mesh and pose estimation.

YOLO with a webcam

from ultralytics import YOLO
import cv2
import cvzone
import math

cap = cv2.VideoCapture(0) # 0 is the id number of the webcam
cap.set(3, 1280) # (propid, width)
cap.set(4, 720) # (propid, height)

model = YOLO("../YOLO-Weights/yolov8n.pt")

classNames = ["person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat",
"traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
"dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella",
"handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
"baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
"fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli",
"carrot", "hot dog", "pizza", "donut", "cake", "chair", "sofa", "pottedplant", "bed",
"diningtable", "toilet", "tvmonitor", "laptop", "mouse", "remote", "keyboard", "cell phone",
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors",
"teddy bear", "hair drier", "toothbrush"]

while True:
success, img = cap.read()
results = model(img, stream=True)

for r in results:
boxes = r.boxes
for box in boxes:

#------------------For OpenCV bounding box---------------------
x1, y1, x2, y2 = box.xyxy[0]
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
# cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 255), 3)


#-----------------For cvzone bounding box----------------------
w, h = (x2-x1), (y2-y1)
cvzone.cornerRect(img, (x1, y1, w, h))

# -------------For the confidence score-----------------
conf = math.ceil((box.conf[0]*100))/100

# -------------For the class name------------------------
cls = int(box.cls[0])
cvzone.putTextRect(img, f'{classNames[cls]} {conf}', (max(0, x1), max(35, y1)), scale = 0.7, thickness = 2)


cv2.imshow("Image", img)
if cv2.waitKey(1) & 0xFF == ord('q'): break

Running YOLO on a video code

There is no significant difference in running YOLO on a webcam and a video. Only the path of the video has to be added, instead of locating it to the webcam.

from ultralytics import YOLO
import cv2
import cvzone
import math

cap = cv2.VideoCapture("../Videos/people.mp4") # this is the only part that is replaced

model = YOLO("../YOLO-Weights/yolov8l.pt")

classNames = ["person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat",
"traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
"dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella",
"handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
"baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
"fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli",
"carrot", "hot dog", "pizza", "donut", "cake", "chair", "sofa", "pottedplant", "bed",
"diningtable", "toilet", "tvmonitor", "laptop", "mouse", "remote", "keyboard", "cell phone",
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors",
"teddy bear", "hair drier", "toothbrush"]

while True:
success, img = cap.read()
if not success: # stop cleanly when the video ends
break
results = model(img, stream=True)

for r in results:
boxes = r.boxes
for box in boxes:

#------------------For OpenCV bounding box---------------------
x1, y1, x2, y2 = box.xyxy[0]
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
# cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 255), 3)


#-----------------For cvzone bounding box----------------------
w, h = (x2-x1), (y2-y1)
cvzone.cornerRect(img, (x1, y1, w, h))

# -------------For the confidence score-----------------
conf = math.ceil((box.conf[0]*100))/100

# -------------For the class name------------------------
cls = int(box.cls[0])
cvzone.putTextRect(img, f'{classNames[cls]} {conf}', (max(0, x1), max(35, y1)), scale = 0.7, thickness = 2)


cv2.imshow("Image", img)
cv2.waitKey(1)

--

--