• yolov8 区域多类别计数


    1. 基础

    本项目是在 Windows+YOLOV8环境配置 的基础上实现的,测距原理可见上边文章

    2. 计数功能

    2.1 计数模块

    在指定区域内计数模块
    region_points为指定区域,可设置为任意形状

    region_points = [(20, 20), (20, 600), (1200, 600), (1200, 20)]
    count_class1 = 0
    count_class2 = 0
    for i, box in enumerate(boxes):
       x1, y1, x2, y2 = box[:4]
       x_center = (x1 + x2) / 2
       y_center = (y1 + y2) / 2
       center_point = (int(x_center), int(y_center))
       if is_inside_region(center_point, region_points):
           if box[-1] == 0:  # 类别1的标签.人
               count_class1 += 1
           elif  box[-1] == 2:  # 类别2的标签,车
               count_class2 += 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.2 判断模块

    def is_inside_region(point, region_points):
        """
        判断点是否在指定区域内
        """
        return cv2.pointPolygonTest(np.array(region_points), point, False) >= 0
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. 初始代码

    
    import cv2
    import numpy as np
    from ultralytics import YOLO
    
    
    def is_inside_region(point, region_points):
        """
        判断点是否在指定区域内
        """
        return cv2.pointPolygonTest(np.array(region_points), point, False) >= 0
    
    def detect():
    
        model = YOLO("yolov8n.pt")
        cv2.namedWindow('region couter', cv2.WINDOW_NORMAL)
        cv2.resizeWindow('region couter', 1280, 360)  # 设置宽高
        cap = cv2.VideoCapture('ultralytics/assets/a3.mp4')
        out_video = cv2.VideoWriter('output.avi', cv2.VideoWriter_fourcc(*'XVID'), 30, (2560, 720))
    
        region_points = [(20, 20), (20, 600), (1200, 600), (1200, 20)]
        region_points_np = np.array(region_points)
    
        assert cap.isOpened(), "Error reading video file"
        while cap.isOpened():
            success, im0 = cap.read()
            if not success:
                print("Video frame is empty or video processing has been successfully completed.")
                break
            tracks = model.track(im0, persist=True)
            annotated_frame = tracks[0].plot()
            boxes = tracks[0].boxes.data
            count_class1 = 0
            count_class2 = 0
            for i, box in enumerate(boxes):
                x1, y1, x2, y2 = box[:4]
                x_center = (x1 + x2) / 2
                y_center = (y1 + y2) / 2
                center_point = (int(x_center), int(y_center))
                if is_inside_region(center_point, region_points):
                    if box[-1] == 0:  # 类别1的标签.人
                        count_class1 += 1
                    elif  box[-1] == 2:  # 类别2的标签,车
                        count_class2 += 1
            cv2.polylines(annotated_frame, [region_points_np], isClosed=True, color=(255, 0, 0), thickness=2)
            print("Number of objects in class 1:", count_class1)
            print("Number of objects in class 2:", count_class2)
    
            cv2.imshow("region couter", annotated_frame)
            out_video.write(annotated_frame)
            if cv2.waitKey(1) == ord('q'):
                break
        out_video.release()
        cap.release()
        cv2.destroyAllWindows()
    if __name__ == '__main__':
        detect()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    4. 实验结果

    本实验可以计数多种类别
    (1)区域计数实验
    在这里插入图片描述
    (2)如需把区域背景换成填充色,可将上边代码里的

    cv2.polylines(annotated_frame, [region_points_np], isClosed=True, color=(255, 0, 0), thickness=2)
    
    • 1

    替换为

    region_mask = np.zeros_like(annotated_frame)
    cv2.fillPoly(region_mask, [region_points_np], color=(255, 0, 0))
    # 使用透明度将填充后的区域与原始帧混合
    alpha = 0.2  # 调整透明度
    annotated_frame = cv2.addWeighted(annotated_frame, 1 - alpha, region_mask, alpha, 0)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    请添加图片描述
    (3)计数在图上显示
    annotated_frame = cv2.addWeighted(annotated_frame, 1 - alpha, region_mask, alpha, 0)添加

    text1 = "count_class1:%d" % count_class1
    text2 = "count_class2:%d" % count_class2
    cv2.putText(annotated_frame, text1, (20, 30), cv2.FONT_ITALIC, 1.0, (0, 255, 255), 2)
    cv2.putText(annotated_frame, text2, (20, 60), cv2.FONT_ITALIC, 1.0, (0, 255, 255), 2)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    5. 完整代码

    import cv2
    import numpy as np
    from ultralytics import YOLO
    
    
    def is_inside_region(point, region_points):
        """
        判断点是否在指定区域内
        """
        return cv2.pointPolygonTest(np.array(region_points), point, False) >= 0
    
    def detect():
    
        model = YOLO("yolov8n.pt")
        cv2.namedWindow('region couter', cv2.WINDOW_NORMAL)
        cv2.resizeWindow('region couter', 1280, 360)  # 设置宽高
        cap = cv2.VideoCapture('ultralytics/assets/a3.mp4')
        out_video = cv2.VideoWriter('output.avi', cv2.VideoWriter_fourcc(*'XVID'), 30, (2560, 720))
    
        region_points = [(20, 20), (20, 600), (1200, 600), (1200, 20)]
        region_points_np = np.array(region_points)
    
        assert cap.isOpened(), "Error reading video file"
        while cap.isOpened():
            success, im0 = cap.read()
            if not success:
                print("Video frame is empty or video processing has been successfully completed.")
                break
            tracks = model.track(im0, persist=True)
            annotated_frame = tracks[0].plot()
            boxes = tracks[0].boxes.data
            count_class1 = 0
            count_class2 = 0
            for i, box in enumerate(boxes):
                x1, y1, x2, y2 = box[:4]
                x_center = (x1 + x2) / 2
                y_center = (y1 + y2) / 2
                center_point = (int(x_center), int(y_center))
                if is_inside_region(center_point, region_points):
                    if box[-1] == 0:  # 类别1的标签.人
                        count_class1 += 1
                    elif  box[-1] == 2:  # 类别2的标签,车
                        count_class2 += 1
            # cv2.polylines(annotated_frame, [region_points_np], isClosed=True, color=(255, 0, 0), thickness=2)
            region_mask = np.zeros_like(annotated_frame)
            cv2.fillPoly(region_mask, [region_points_np], color=(255, 0, 0))
            # 使用透明度将填充后的区域与原始帧混合
            alpha = 0.2  # 调整透明度
            annotated_frame = cv2.addWeighted(annotated_frame, 1 - alpha, region_mask, alpha, 0)
    
            text1 = "count_class1:%d" % count_class1
            text2 = "count_class2:%d" % count_class2
            cv2.putText(annotated_frame, text1, (20, 30), cv2.FONT_ITALIC, 1.0, (0, 255, 255), 2)
            cv2.putText(annotated_frame, text2, (20, 60), cv2.FONT_ITALIC, 1.0, (0, 255, 255), 2)
            print("Number of objects in class 1:", count_class1)
            print("Number of objects in class 2:", count_class2)
    
            cv2.imshow("region couter", annotated_frame)
            out_video.write(annotated_frame)
            if cv2.waitKey(1) == ord('q'):
                break
        out_video.release()
        cap.release()
        cv2.destroyAllWindows()
    if __name__ == '__main__':
        detect()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    6. 源码

    可以去 Windows+YOLOV8环境配置 下载源码,然后把上边主代码贴进去运行即可

  • 相关阅读:
    部署你自己的导航站-dashy
    a+b(暑假每日一题 45)
    深入理解AQS
    41、二叉树-二叉树的层序遍历
    484-红黑树
    从零开始—仿牛客网讨论社区项目(一)
    SpringCloud - Spring Cloud Alibaba 之 Seata分布式事务服务;Seata TC Server集群部署(二十二)
    【Spring AI 来了】
    【算法】Inclusion of a Shuffled String Into another String
    【Jenkins】关于账号,证书验证的设置问题
  • 原文地址:https://blog.csdn.net/qq_45077760/article/details/137972314