yolov8 detection 된 class 이름 저장이 안됩니다.

from ultralytics.yolo.engine.model import YOLO
import RPi.GPIO as GPIO
import time

# LED의 핀 번호 (BCM)
led = 12

# GPIO 모드 설정
GPIO.setmode(GPIO.BCM)

# LED를 위한 GPIO 설정
GPIO.setup(led, GPIO.OUT)

# YOLO 객체 생성
model = YOLO("/home/esp/sharefolder/best.onnx")

# 객체 탐지 및 LED 제어
while True:
    results = model.predict(source="0", show=True, imgsz=[320, 320])
    for result in results:
        clist = result.boxes.cls
        cls = set()
        for cno in clist:
            cls.add(model.names[int(cno)])
        print(cls)
        print(clist)
        if 'person' in cls or 'vehicle' in cls:
            print("Detected person or vehicle, turning on LED...")
            # LED를 켜는 코드를 작성하세요
            GPIO.output(led, GPIO.HIGH)
            time.sleep(1)
            GPIO.output(led, GPIO.LOW)
        else:
            print("No person or vehicle detected.")
    time.sleep(1)

# GPIO 설정 초기화
GPIO.cleanup()

실시간으로 웹캠으로 객체 탐지를하고, person과 vehicle이 동시에 탐지가 되면 led가 작동하는것이 목표입니다.

근데 results = model.predict(source="0", show=True, imgsz=[320, 320])

여기까지 실행되고 그 아래가 실행이 안되는건지
아님 실행은 되지만 아예 비어있는건지 ..

0: 320x320 1 person, 1 vehicle, 164.5ms
0: 320x320 1 person, 1 vehicle, 158.8ms
0: 320x320 1 person, 1 vehicle, 157.0ms

이렇게 터미널에서 탐지 결과는 출력되는데

cls 이름들 출력이 안됩니다 이 부분이 출력이 안된다는건
저장이 안되었거나 아예 실행도 안된다는건데..

정말 스택오버플로우, 챗 지피티, 공식 깃헙에 이슈에도 등록했는데

갈피를 못잡겠습니다..저 class만 잘 저장되면
저장된 이름을 불러와서 여러조건에 따라 gpio들 제어할 수 있게 할려는건데 ..

  • 아래 답변은 OpenAI의 GPT-4 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

코드를 살펴보니, ultralytics.yolo.engine.model에서 YOLO 클래스를 사용하고 있는데, 이는 공식적인 YOLOv5 라이브러리가 아닌 것 같습니다. 따라서, 공식 YOLOv5 라이브러리를 사용하여 문제를 해결해 보겠습니다.

먼저, YOLOv5 라이브러리를 설치해야 합니다. 설치 방법은 다음과 같습니다.

pip install yolov5

그런 다음, 아래 코드를 사용하여 웹캠에서 실시간으로 객체를 탐지하고, person 또는 vehicle이 감지되면 LED를 켜는 작업을 수행할 수 있습니다.

import torch
from yolov5 import YOLOv5
import cv2
import RPi.GPIO as GPIO
import time

# LED의 핀 번호 (BCM)
led = 12

# GPIO 모드 설정
GPIO.setmode(GPIO.BCM)

# LED를 위한 GPIO 설정
GPIO.setup(led, GPIO.OUT)

# YOLO 객체 생성
model = YOLOv5("yolov5s.pt", device="cpu")

# 웹캠 객체 생성
cap = cv2.VideoCapture(0)

while True:
    # 웹캠에서 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 객체 탐지
    results = model(frame)

    # 탐지된 객체의 클래스 목록을 얻기
    detected_classes = set()
    for detection in results.xyxy[0]:
        class_id = int(detection[5])
        class_name = model.names[class_id]
        detected_classes.add(class_name)

    print(detected_classes)

    # person 또는 vehicle이 탐지되면 LED 켜기
    if 'person' in detected_classes or 'vehicle' in detected_classes:
        print("Detected person or vehicle, turning on LED...")
        GPIO.output(led, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(led, GPIO.LOW)
    else:
        print("No person or vehicle detected.")

    # 탐지 결과를 화면에 표시
    results.render()
    cv2.imshow("YOLOv5", frame)

    # 'q' 키를 누르면 종료
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 웹캠 및 OpenCV 창 종료
cap.release()
cv2.destroyAllWindows()

# GPIO 설정 초기화
GPIO.cleanup()

위 코드는 공식 YOLOv5 라이브러리를 사용하여 웹캠에서 실시간으로 객체를 탐지하고, 탐지된 객체의 클래스 이름을 얻어 LED를 제어하는 예제입니다. 이를 통해 원하시는 작업을 수행할 수 있을 것입니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 OpenAI의 GPT-3.5(ChatGPT) 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

ultralytics.yolo.engine.model의 YOLO 클래스를 사용하여 객체 탐지를 수행하고, 탐지된 객체의 클래스 이름을 저장하려고 합니다. 그러나 cls 변수에 저장된 클래스 이름이 출력되지 않는 문제가 발생하고 있습니다.

이 문제는 다음과 같은 이유로 발생할 수 있습니다.

  • result.boxes.cls가 비어 있거나 None일 수 있습니다.
  • model.names[int(cno)]에서 cno이 model.names의 인덱스 범위를 벗어날 수 있습니다.
  • cls 변수가 초기화되지 않았거나, cls.add() 함수가 제대로 작동하지 않을 수 있습니다.

따라서 다음과 같은 방법으로 문제를 해결할 수 있습니다.

  1. result.boxes.cls가 비어 있거나 None인 경우에 대한 예외 처리를 추가합니다.
for result in results:
    if result.boxes.cls is None:
        continue
    clist = result.boxes.cls
    cls = set()
    for cno in clist:
        if int(cno) >= len(model.names):
            continue
        cls.add(model.names[int(cno)])
    print(cls)
    print(clist)
    ...
  1. cls 변수가 초기화되지 않은 경우, 다음과 같이 초기화합니다.
for result in results:
    clist = result.boxes.cls
    cls = set(model.names[int(cno)] for cno in clist if int(cno) < len(model.names))
    print(cls)
    print(clist)
    ...

위의 방법으로 문제를 해결하지 못하면, YOLO 클래스의 predict() 함수에서 문제가 발생할 수 있습니다. 이 경우, YOLO 클래스의 predict() 함수를 직접 수정해야 할 수도 있습니다.

참고로, YOLO 클래스의 predict() 함수는 다음과 같이 정의되어 있습니다.

def predict(self, source, imgsz=(640, 640), augment=False, visualize=False):
    ...
    return results

이 함수는 입력 이미지(source)를 받아 객체 탐지 결과(results)를 반환합니다. 결과는 다음과 같은 형식으로 구성됩니다.

[
    Detection(image_id=i, bbox=bbox, scores=scores, cls=cls)
    for i, (bbox, scores, cls) in enumerate(zip(det_boxes, det_scores, det_class))
]

여기서 Detection 클래스는 다음과 같이 정의되어 있습니다.

class Detection:
    def __init__(self, image_id, bbox, scores, cls):
        self.image_id = image_id
        self.bbox = bbox
        self.scores = scores
        self.cls = cls

따라서, cls 변수는 Detection 클래스의 인스턴스 변수로 정의되어 있으며, 객체 탐지 결과가 올바르게 반환되는지 확인해야 합니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!

저 값들이 출력 안되는 건 results 배열이 비어 있어서 for문이 안 돌아가서 인 것 같고
results 값이 빈 배열로 나오는 이유는 아마 vehicle 객체가 잡혔는데 confidence 값이 낮아서 confidence threshold 값을 넘기지 못해 반환을 못하는 것 같습니다.
model.predict 함수에 confidence threshold 값을 제어하는 파라미터가 있을거에요. 0으로 낮춰보세요

1개의 좋아요

github에 문의해보니 model.predict 자체가 class 정보를 반환하지 않는다고 하네요!
탐지결과는 출력해주지만
그래서 opencv로 우선 작성해봤는데 잘 저장됩니다

다만,, pt 파일이라 라즈베리파이에 구동하기엔 onnx보단 느린데 혹시 도와주실 수 있으신가요?

이제 onnx 모델을 불러오고 실시간 출력해볼려고하는데 힘드네요..
"import cv2
import argparse
from ultralytics import YOLO
import supervision as sv
import numpy as np

import RPi.GPIO as GPIO

from time import sleep

# BCM 핀

led = 12

# Set GPIO mode

GPIO.setmode(GPIO.BCM)

# Set up GPIO for LED

GPIO.setup(led, GPIO.OUT)

def parse_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="YOLOv8Live")
parser.add_argument(
"--webcam-resolution",
default=[640,640],
nargs=2,
type=int
)

parser.add_argument(
    "--output-file",
    default="C:\\yolov8\\class_names.txt",
    type=str,
)
args = parser.parse_args()
return args

def save_class_names(class_names, output_file):
with open(output_file, "w") as f:
f.write("\n".join(class_names))

def main():
args = parse_arguments()
frame_width, frame_height = args.webcam_resolution

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, frame_width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_height)

model = YOLO("C:\\yolov8\\best.pt")

box_annotator = sv.BoxAnnotator(
    thickness=2,
    text_thickness=2,
    text_scale=1
)

while True:
    ret, frame = cap.read()
    class_names = []  # 빈 리스트 생성
    result = model(frame)[0]
    detections = sv.Detections.from_yolov8(result)
    #실시간 탐지된 class 정보들을 저장 = labels
    labels = [
        f"{model.model.names[class_id]} {confidence:0.2f}"
        for _, confidence, class_id, __build_class_ in detections
    ]

    for label in labels:
        class_name = label.split()[0]  # 클래스 이름 추출
        class_names.append(class_name)  # 클래스 이름을 class_names 리스트에 추가

    frame = box_annotator.annotate(
        scene=frame,
        detections=detections,
        labels=labels)
    # 창 이름, 실시간 탐지
    cv2.imshow("yolov8", frame)

    save_class_names(class_names, args.output_file)  # class_names 를 텍스트 파일로 저장

    if 'person' in class_names or 'mouse' in class_names:
        print("Detected person or vehicle, turning on LED...")
        # Write code to turn on the LED
        # GPIO.output(led, GPIO.HIGH)
        # sleep(1)
        # GPIO.output(led, GPIO.LOW)

    else:
        print("No person or vehicle detected.")


    if (cv2.waitKey(30) == 27):
        break

cap.release()
cv2.destroyAllWindows()

if name == "main":
main()
"

  • 아래 답변은 OpenAI의 GPT-4 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

코드를 살펴보니, results 객체에서 클래스 이름을 가져오는 부분이 잘못된 것 같습니다. ultralytics/yolov5 저장소를 기준으로 설명드리겠습니다. results 객체는 Result 클래스의 인스턴스이며, 이 클래스는 ultralytics/yolov5 저장소의 utils/plots.py 파일에 정의되어 있습니다.

Result 클래스의 인스턴스에서 클래스 이름을 가져오려면, result.xyxy를 사용해야 합니다. 이를 사용하여 코드를 수정하면 다음과 같습니다.

from ultralytics.yolo.engine.model import YOLO
import RPi.GPIO as GPIO
import time

# LED의 핀 번호 (BCM)
led = 12

# GPIO 모드 설정
GPIO.setmode(GPIO.BCM)

# LED를 위한 GPIO 설정
GPIO.setup(led, GPIO.OUT)

# YOLO 객체 생성
model = YOLO("/home/esp/sharefolder/best.onnx")

# 객체 탐지 및 LED 제어
while True:
    results = model.predict(source="0", show=True, imgsz=[320, 320])
    for result in results:
        clist = result.xyxy[:, -1].tolist()
        cls = set()
        for cno in clist:
            cls.add(model.names[int(cno)])
        print(cls)
        print(clist)
        if 'person' in cls or 'vehicle' in cls:
            print("Detected person or vehicle, turning on LED...")
            # LED를 켜는 코드를 작성하세요
            GPIO.output(led, GPIO.HIGH)
            time.sleep(1)
            GPIO.output(led, GPIO.LOW)
        else:
            print("No person or vehicle detected.")
    time.sleep(1)

# GPIO 설정 초기화
GPIO.cleanup()

위 코드에서 result.xyxy[:, -1].tolist()를 사용하여 각 객체의 클래스 인덱스를 가져옵니다. 이 인덱스를 사용하여 클래스 이름을 가져올 수 있습니다. 이렇게 수정하면 클래스 이름이 올바르게 출력되어야 합니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 OpenAI의 GPT-4 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

코드를 살펴보니, ultralytics.yolo.engine.model에서 YOLO 클래스를 사용하고 있는데, 이는 YOLOv5의 공식 저장소에서 제공하는 클래스가 아닙니다. 따라서, 이 클래스의 구현에 따라 결과가 달라질 수 있습니다. YOLOv5 공식 저장소에서 제공하는 방식을 사용하여 코드를 수정하겠습니다.

먼저, YOLOv5 공식 저장소를 클론하고 필요한 패키지를 설치해주세요.

git clone https://github.com/ultralytics/yolov5.git
cd yolov5
pip install -r requirements.txt

그런 다음, 다음과 같이 코드를 수정하여 실행해보세요.

import torch
from pathlib import Path
import RPi.GPIO as GPIO
import time

# LED의 핀 번호 (BCM)
led = 12

# GPIO 모드 설정
GPIO.setmode(GPIO.BCM)

# LED를 위한 GPIO 설정
GPIO.setup(led, GPIO.OUT)

# YOLO 객체 생성
model = torch.hub.load('ultralytics/yolov5', 'custom', path_or_model=Path("/home/esp/sharefolder/best.onnx").as_posix())

# 객체 탐지 및 LED 제어
while True:
    results = model("0", size=320)
    results.display(save=False)
    clist = results.xyxy[0][:, -1].tolist()
    cls = set()
    for cno in clist:
        cls.add(model.names[int(cno)])
    print(cls)
    print(clist)
    if 'person' in cls or 'vehicle' in cls:
        print("Detected person or vehicle, turning on LED...")
        # LED를 켜는 코드를 작성하세요
        GPIO.output(led, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(led, GPIO.LOW)
    else:
        print("No person or vehicle detected.")
    time.sleep(1)

# GPIO 설정 초기화
GPIO.cleanup()

위 코드는 YOLOv5 공식 저장소에서 제공하는 방식을 사용하여 웹캠에서 실시간으로 객체를 탐지하고, personvehicle이 탐지되면 LED를 켜는 코드입니다. 이 코드를 사용하여 원하는 결과를 얻을 수 있을 것입니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!