diff --git a/examples/README.md b/examples/README.md
index ec9c5268af..7c5c8aae0a 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -15,6 +15,7 @@ This repository features a collection of real-world applications and walkthrough
| [YOLOv8 ONNXRuntime CPP](./YOLOv8-ONNXRuntime-CPP) | C++/ONNXRuntime | [DennisJcy](https://github.com/DennisJcy), [Onuralp Sezer](https://github.com/onuralpszr) |
| [RTDETR ONNXRuntime C#](https://github.com/Kayzwer/yolo-cs/blob/master/RTDETR.cs) | C#/ONNX | [Kayzwer](https://github.com/Kayzwer) |
| [YOLOv8 SAHI Video Inference](https://github.com/RizwanMunawar/ultralytics/blob/main/examples/YOLOv8-SAHI-Inference-Video/yolov8_sahi.py) | Python | [Muhammad Rizwan Munawar](https://github.com/RizwanMunawar) |
+| [YOLOv8 Region Counter](https://github.com/RizwanMunawar/ultralytics/blob/main/examples/YOLOv8-Region-Counter/yolov8_region_counter.py) | Python | [Muhammad Rizwan Munawar](https://github.com/RizwanMunawar) |
### How to Contribute
diff --git a/examples/YOLOv8-Region-Counter/readme.md b/examples/YOLOv8-Region-Counter/readme.md
new file mode 100644
index 0000000000..2ce093aa29
--- /dev/null
+++ b/examples/YOLOv8-Region-Counter/readme.md
@@ -0,0 +1,84 @@
+# Regions Counting Using YOLOv8 (Inference on Video)
+
+- Region counting is a method employed to tally the objects within a specified area, allowing for more sophisticated analyses when multiple regions are considered. These regions can be adjusted interactively using a Left Mouse Click, and the counting process occurs in real time.
+- Regions can be adjusted to suit the user's preferences and requirements.
+
+
+
+
+
+
+
+
+
+## Table of Contents
+
+- [Step 1: Install the Required Libraries](#step-1-install-the-required-libraries)
+- [Step 2: Run the Region Counting Using Ultralytics YOLOv8](#step-2-run-the-region-counting-using-ultralytics-yolov8)
+- [Usage Options](#usage-options)
+- [FAQ](#faq)
+
+## Step 1: Install the Required Libraries
+
+Clone the repository, install dependencies and `cd` to this local directory for commands in Step 2.
+
+```bash
+# Clone ultralytics repo
+git clone https://github.com/ultralytics/ultralytics
+
+# cd to local directory
+cd ultralytics/examples/YOLOv8-Region-Counter
+```
+
+## Step 2: Run the Region Counting Using Ultralytics YOLOv8
+
+Here are the basic commands for running the inference:
+
+### Note
+
+After the video begins playing, you can freely move the region anywhere within the video by simply clicking and dragging using the left mouse button.
+
+```bash
+# If you want to save results
+python yolov8_region_counter.py --source "path/to/video.mp4" --save-img --view-img
+
+# If you want to change model file
+python yolov8_region_counter.py --source "path/to/video.mp4" --save-img --weights "path/to/model.pt"
+
+# If you dont want to save results
+python yolov8_region_counter.py --source "path/to/video.mp4" --view-img
+```
+
+## Usage Options
+
+- `--source`: Specifies the path to the video file you want to run inference on.
+- `--save-img`: Flag to save the detection results as images.
+- `--weights`: Specifies a different YOLOv8 model file (e.g., `yolov8n.pt`, `yolov8s.pt`, `yolov8m.pt`, `yolov8l.pt`, `yolov8x.pt`).
+- `--line-thickness`: Specifies the bounding box thickness
+- `--region-thickness`: Specific the region boxes thickness
+
+## FAQ
+
+**1. What Does Region Counting Involve?**
+
+Region counting is a computational method utilized to ascertain the quantity of objects within a specific area in recorded video or real-time streams. This technique finds frequent application in image processing, computer vision, and pattern recognition, facilitating the analysis and segmentation of objects or features based on their spatial relationships.
+
+**2. Why Combine Region Counting with YOLOv8?**
+
+YOLOv8 specializes in the detection and tracking of objects in video streams. Region counting complements this by enabling object counting within designated areas, making it a valuable application of YOLOv8.
+
+**3. How Can I Troubleshoot Issues?**
+
+To gain more insights during inference, you can include the `--debug` flag in your command:
+
+```bash
+python yolov8_region_counter.py --source "path to video file" --debug
+```
+
+**4. Can I Employ Other YOLO Versions?**
+
+Certainly, you have the flexibility to specify different YOLO model weights using the `--weights` option.
+
+**5. Where Can I Access Additional Information?**
+
+For a comprehensive guide on using YOLOv8 with Object Tracking, please refer to [Multi-Object Tracking with Ultralytics YOLO](https://docs.ultralytics.com/modes/track/).
diff --git a/examples/YOLOv8-Region-Counter/yolov8_region_counter.py b/examples/YOLOv8-Region-Counter/yolov8_region_counter.py
new file mode 100644
index 0000000000..07567e557b
--- /dev/null
+++ b/examples/YOLOv8-Region-Counter/yolov8_region_counter.py
@@ -0,0 +1,201 @@
+import argparse
+from collections import defaultdict
+from pathlib import Path
+
+import cv2
+import numpy as np
+
+from ultralytics import YOLO
+
+track_history = defaultdict(lambda: [])
+
+from ultralytics.utils.files import increment_path
+from ultralytics.utils.plotting import Annotator, colors
+
+# Region utils
+current_region = None
+counting_regions = [{
+ 'name': 'YOLOv8 Region A',
+ 'roi': (50, 100, 240, 300),
+ 'counts': 0,
+ 'dragging': False,
+ 'region_color': (0, 255, 0)}, {
+ 'name': 'YOLOv8 Region B',
+ 'roi': (200, 250, 240, 300),
+ 'counts': 0,
+ 'dragging': False,
+ 'region_color': (255, 144, 31)}]
+
+
+def is_inside_roi(box, roi):
+ """Compare bbox with region box."""
+ x, y, _, _ = box
+ roi_x, roi_y, roi_w, roi_h = roi
+ return roi_x < x < roi_x + roi_w and roi_y < y < roi_y + roi_h
+
+
+def mouse_callback(event, x, y, flags, param):
+ """Mouse call back event."""
+ global current_region
+
+ # Mouse left button down event
+ if event == cv2.EVENT_LBUTTONDOWN:
+ for region in counting_regions:
+ roi_x, roi_y, roi_w, roi_h = region['roi']
+ if roi_x < x < roi_x + roi_w and roi_y < y < roi_y + roi_h:
+ current_region = region
+ current_region['dragging'] = True
+ current_region['offset_x'] = x - roi_x
+ current_region['offset_y'] = y - roi_y
+
+ # Mouse move event
+ elif event == cv2.EVENT_MOUSEMOVE:
+ if current_region is not None and current_region['dragging']:
+ current_region['roi'] = (x - current_region['offset_x'], y - current_region['offset_y'],
+ current_region['roi'][2], current_region['roi'][3])
+
+ # Mouse left button up event
+ elif event == cv2.EVENT_LBUTTONUP:
+ if current_region is not None and current_region['dragging']:
+ current_region['dragging'] = False
+
+
+def run(weights='yolov8n.pt',
+ source='test.mp4',
+ view_img=False,
+ save_img=False,
+ exist_ok=False,
+ line_thickness=2,
+ region_thickness=2):
+ """
+ Run Region counting on a video using YOLOv8 and ByteTrack.
+
+ Supports movable region for real time counting inside specific area.
+ Supports multiple regions counting.
+
+ Args:
+ weights (str): Model weights path.
+ source (str): Video file path.
+ view_img (bool): Show results.
+ save_img (bool): Save results.
+ exist_ok (bool): Overwrite existing files.
+ line_thickness (int): Bounding box thickness.
+ region_thickness (int): Region thickness.
+ """
+ vid_frame_count = 0
+
+ # Check source path
+ if not Path(source).exists():
+ raise FileNotFoundError(f"Source path '{source}' does not exist.")
+
+ # Setup Model
+ model = YOLO(f'{weights}')
+
+ # Video setup
+ videocapture = cv2.VideoCapture(source)
+ frame_width, frame_height = int(videocapture.get(3)), int(videocapture.get(4))
+ fps, fourcc = int(videocapture.get(5)), cv2.VideoWriter_fourcc(*'mp4v')
+
+ # Output setup
+ save_dir = increment_path(Path('ultralytics_rc_output') / 'exp', exist_ok)
+ save_dir.mkdir(parents=True, exist_ok=True)
+ video_writer = cv2.VideoWriter(str(save_dir / f'{Path(source).stem}.mp4'), fourcc, fps, (frame_width, frame_height))
+
+ # Iterate over video frames
+ while videocapture.isOpened():
+ success, frame = videocapture.read()
+ if not success:
+ break
+ vid_frame_count += 1
+
+ # Extract the results
+ results = model.track(frame, persist=True)
+ boxes = results[0].boxes.xywh.cpu()
+ track_ids = results[0].boxes.id.int().cpu().tolist()
+ clss = results[0].boxes.cls.cpu().tolist()
+ names = results[0].names
+
+ annotator = Annotator(frame, line_width=line_thickness, example=str(names))
+
+ for box, track_id, cls in zip(boxes, track_ids, clss):
+ x, y, w, h = box
+ label = str(names[cls])
+ xyxy = (x - w / 2), (y - h / 2), (x + w / 2), (y + h / 2)
+
+ # Bounding box
+ bbox_color = colors(cls, True)
+ annotator.box_label(xyxy, label, color=bbox_color)
+
+ # Tracking Lines
+ track = track_history[track_id]
+ track.append((float(x), float(y)))
+ if len(track) > 30:
+ track.pop(0)
+ points = np.hstack(track).astype(np.int32).reshape((-1, 1, 2))
+ cv2.polylines(frame, [points], isClosed=False, color=bbox_color, thickness=line_thickness)
+
+ # Check If detection inside region
+ for region in counting_regions:
+ if is_inside_roi(box, region['roi']):
+ region['counts'] += 1
+
+ # Draw region boxes
+ for region in counting_regions:
+ region_label = str(region['counts'])
+ roi_x, roi_y, roi_w, roi_h = region['roi']
+ region_color = region['region_color']
+ center_x = roi_x + roi_w // 2
+ center_y = roi_y + roi_h // 2
+ text_margin = 15
+
+ # Region plotting
+ cv2.rectangle(frame, (roi_x, roi_y), (roi_x + roi_w, roi_y + roi_h), region_color, region_thickness)
+ t_size, _ = cv2.getTextSize(region_label, cv2.FONT_HERSHEY_SIMPLEX, fontScale=1.0, thickness=line_thickness)
+ text_x = center_x - t_size[0] // 2 - text_margin
+ text_y = center_y + t_size[1] // 2 + text_margin
+ cv2.rectangle(frame, (text_x - text_margin, text_y - t_size[1] - text_margin),
+ (text_x + t_size[0] + text_margin, text_y + text_margin), region_color, -1)
+ cv2.putText(frame, region_label, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), line_thickness)
+
+ if view_img:
+ if vid_frame_count == 1:
+ cv2.namedWindow('Ultralytics YOLOv8 Region Counter Movable')
+ cv2.setMouseCallback('Ultralytics YOLOv8 Region Counter Movable', mouse_callback)
+ cv2.imshow('Ultralytics YOLOv8 Region Counter Movable', frame)
+
+ if save_img:
+ video_writer.write(frame)
+
+ for region in counting_regions: # Reinitialize count for each region
+ region['counts'] = 0
+
+ if cv2.waitKey(1) & 0xFF == ord('q'):
+ break
+
+ del vid_frame_count
+ video_writer.release()
+ videocapture.release()
+ cv2.destroyAllWindows()
+
+
+def parse_opt():
+ """Parse command line arguments."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--weights', type=str, default='yolov8n.pt', help='initial weights path')
+ parser.add_argument('--source', type=str, required=True, help='video file path')
+ parser.add_argument('--view-img', action='store_true', help='show results')
+ parser.add_argument('--save-img', action='store_true', help='save results')
+ parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
+ parser.add_argument('--line-thickness', type=int, default=2, help='bounding box thickness')
+ parser.add_argument('--region-thickness', type=int, default=4, help='Region thickness')
+ return parser.parse_args()
+
+
+def main(opt):
+ """Main function."""
+ run(**vars(opt))
+
+
+if __name__ == '__main__':
+ opt = parse_opt()
+ main(opt)