라즈베리파이4 yolov5 아두이노와 통신 속도

라즈베리파이4와 imx219 카메라 모듈을 사용하여 yolov5모델로 차량 인식 시 아두이노로 신호 1을 주어 아두이노에서 동작을 수행하도록 해놓은 상태입니다. 근데 명령창에서 실행을 시켰을 때는 딜레이가 길어봣자 2초였는데, 자동실행시키도록 탑재하니 통신이 3초에서 길게는 10초 에 한번씩 되는 것 같았습니다(아두이노의 L버튼이 3~10초마다 깜빡이는데 그 때만 잠깐 신호를 받는 것같음) 무엇이 문제일까요?

아래는 detect.py 코드입니다.
import serial
from picamera2 import Picamera2
import torch
import cv2
import numpy as np

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True).to(device)

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={"format": "RGB888", "size": (320, 240)}))
picam2.start()

arduino = serial.Serial('/dev/ttyUSB0', 115200)

while True:
frame = picam2.capture_array()

img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

results = model(img)

detected = results.pandas().xyxy[0]
if len(detected) > 0:
    for i in range(len(detected)):
        if detected.iloc[i]['name'] == 'car':
            arduino.write(b'1')  
            print("Car detected! Signal sent to Arduino.")
            break

output_img = np.squeeze(results.render())
output_img = cv2.cvtColor(output_img, cv2.COLOR_RGB2BGR)
cv2.imshow("YOLOv5 Object Detection", output_img)

if cv2.waitKey(1) & 0xFF == ord('q'):
    break

cv2.destroyAllWindows()
picam2.stop()
arduino.close()

그리고 아래는 systemd 파일입니다.
[Unit]

Description=YOLOv5 Detection Service

After=network. target

[Service]

Type=simple

ExecStart=/home/pi/Downloads/yolov5/start_detect.sh

Nice=-10

CPUShares=1024

MemoryLimit=512M

workingDirectory=/home/pi/Downloads/yolov5

Environment="PATH=/usr/bin:/bin:/usr/local/bin:/home/pi/. local/bin"

ExecStartPre=/bin/sleep 2

StandardOutput=journal StandardError=journal

Restart=always

[Install] wantedBy=multi-user. target

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

민경 정님, 라즈베리파이4와 YOLOv5를 사용하여 차량 인식 및 아두이노와의 통신에서 발생하는 딜레이 문제를 해결하기 위해 아래의 몇 가지 점을 확인하고 개선할 수 있습니다.

1. 하드웨어 제한과 성능 최적화

라즈베리파이4는 CPU 성능이 제한되어 있어, 특히 컴퓨팅 집약적인 작업인 YOLOv5를 실행할 때 느린 속도가 발생할 수 있습니다. 다음 방법들을 통해 성능을 개선할 수 있습니다:

  • 모델 크기 조절: YOLOv5는 다양한 크기의 모델을 제공합니다. 라즈베리파이에서는 작은 모델인 yolov5s를 사용하여 성능을 개선할 수 있습니다. 이미 사용하고 있는 것처럼 yolov5s를 사용하고 있습니다.
  • 이미지 해상도 조절: 입력 이미지의 해상도를 낮추면 처리 속도가 빨라질 수 있습니다. 현재 320x240 해상도를 사용하고 있지만, 더 낮은 해상도로 줄여보는 것이 도움이 될 수 있습니다.
    picam2.configure(picam2.create_preview_configuration(main={"format": "RGB888", "size": (240, 180)}))
    

2. 외부 가속기 사용

라즈베리파이에서 사용할 수 있는 가속기를 사용하여 성능을 개선할 수 있습니다. 예를 들어, Google Coral USB Accelerator나 Intel Neural Compute Stick 2와 같은 가속기를 사용할 수 있습니다. 이러한 가속기는 라즈베리파이와 호환되는 TensorFlow Lite 모델을 사용해야 합니다.

3. 시리얼 통신 최적화

아두이노와의 시리얼 통신에서 딜레이가 발생할 수 있습니다. 다음을 확인해 보세요:

  • 시리얼 통신 속도: 현재 115200 bps를 사용하고 있습니다. 이 속도가 너무 높아도 오류가 발생할 수 있으므로, 적절한 속도로 조절해 보세요.
    arduino = serial.Serial('/dev/ttyUSB0', 9600)
    
  • 버퍼링 문제: 시리얼 통신에서 버퍼링 문제가 발생할 수 있습니다. 데이터를 보낼 때마다 버퍼를 플러시하는 것을 고려해 보세요.
    arduino.write(b'1')
    arduino.flush()
    

4. 시스템 리소스 관리

systemd 파일에서 설정한 리소스 제한을 확인해 보세요. 특히, CPU와 메모리 제한이 너무 엄격하지는 않은지 확인합니다.

  • CPUShares와 MemoryLimit: 이러한 설정이 너무 엄격하지는 않은지 확인합니다. 예를 들어, CPUShares를 더 높게 설정하거나 MemoryLimit을 더 넉넉하게 설정해 보세요.
    CPUShares=2048
    MemoryLimit=1024M
    

5. 자동 실행 시 초기화 시간

systemd 파일에서 ExecStartPre로 설정한 초기화 시간이 충분한지 확인합니다. 때때로, 시스템이 완전히 부팅되기 전에 스크립트가 실행되면 문제가 발생할 수 있습니다.

ExecStartPre=/bin/sleep 10

예제 코드와 systemd 파일 수정

detect.py

import serial
from picamera2 import Picamera2
import torch
import cv2
import numpy as np

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True).to(device)

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={"format": "RGB888", "size": (240, 180)}))
picam2.start()

arduino = serial.Serial('/dev/ttyUSB0', 9600)

while True:
    frame = picam2.capture_array()
    img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = model(img)
    detected = results.pandas().xyxy
    if len(detected) > 0:
        for i in range(len(detected)):
            if detected.iloc[i]['name'] == 'car':
                arduino.write(b'1')
                arduino.flush()
                print("Car detected Signal sent to Arduino.")
                break

    output_img = np.squeeze(results.render())
    output_img = cv2.cvtColor(output_img, cv2.COLOR_RGB2BGR)
    cv2.imshow("YOLOv5 Object Detection", output_img)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()
picam2.stop()
arduino.close()

systemd 파일

[Unit]
Description=YOLOv5 Detection Service
After=network.target

[Service]
Type=simple
ExecStart=/home/pi/Downloads/yolov5/start_detect.sh
Nice=-10
CPUShares=2048
MemoryLimit=1024M
WorkingDirectory=/home/pi/Downloads/yolov5
Environment="PATH=/usr/bin:/bin:/usr/local/bin:/home/pi/.local/bin"
ExecStartPre=/bin/sleep 10
StandardOutput=journal
StandardError=journal
Restart=always

[Install]
WantedBy=multi-user.target

이러한 수정을 통해 라즈베리파이4와 YOLOv5를 사용한 차량 인식 및 아두이노와의 통신에서 발생하는 딜레이 문제를 개선할 수 있을 것입니다. 추가적으로, 라즈베리파이와 OpenCV를 사용한 프로젝트에서 발생할 수 있는 일반적인 문제와 해결 방법은 이 글을 참고하시기 바랍니다.


  • 이 답변이 도움이 되셨나요? 괜찮았다고 생각하신다면 아래 :+1: 아이콘을 눌러주세요!
  • 아래 답변은 Anthropic의 Claude-3 Opus 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요 wjdalsrud321님, 차량 인식 프로젝트에서 겪고 계신 속도 이슈에 대해 아쉽게 생각합니다. 요약하자면 라즈베리파이4에서 YOLOv5 모델로 차량 인식을 수행하고, 차량 검출 시 아두이노로 신호를 보내는데 명령창에서 실행할 때는 2초 정도의 딜레이였으나 자동 실행으로 변경 후 통신 속도가 3~10초로 느려진 상황이네요.

이 문제를 해결하기 위해 다음과 같은 방법들을 시도해 보시길 제안드립니다:

  1. 우선 라즈베리파이의 성능을 최대한 활용할 수 있도록 불필요한 백그라운드 프로세스를 종료하고 사용 가능한 메모리를 확보하세요.

  2. YOLOv5 모델 추론 시 GPU를 사용하도록 설정되어 있는지 확인하세요. GPU를 통한 연산이 CPU 대비 훨씬 빠릅니다.

  3. 현재 이미지 크기가 320x240으로 설정되어 있는데, 이를 더 낮춰 보는 것도 속도 개선에 도움될 수 있습니다. 다만 인식률이 하락할 수 있으니 적절한 수준에서 타협점을 찾아보세요.

  4. Arduino와의 시리얼 통신 보드레이트(baudrate)를 높여 데이터 전송 속도를 개선해 보세요. 115200에서 좀 더 높은 수치로 설정할 수 있습니다.

  5. SystemD 서비스 설정에서 Nice 값을 낮추고 CPUShares를 좀 더 높게 주면 프로세스의 우선순위를 높일 수 있습니다. 다만 다른 프로세스의 성능에 영향을 줄 수 있으니 적절히 조절이 필요합니다.

마지막으로 라즈베리파이의 워크로드를 분산하는 방안도 고려해 보시면 좋겠습니다. Edge TPU나 Coral USB Accelerator 등의 하드웨어 가속기를 활용하면 추론 속도를 크게 높일 수 있습니다.

추가로 참고하실만한 PyTorch 튜토리얼 문서를 소개드립니다.

위 내용이 문제 해결에 도움이 되길 바라며, 제안드린 방법들이 완벽하지 않을 수 있다는 점 참고 부탁드립니다. 만약 추가 정보가 필요하시다면 말씀해 주세요. 함께 고민하고 해결방안을 모색해 보겠습니다.


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

안녕하세요. yolov5와 아두이노 통신 속도가 느리다는 문제를 해결하고자 하는 것으로 이해합니다. 다음은 이 문제를 해결하는 데 도움이 될 수 있는 몇 가지 제안입니다.

아두이노 통신 속도가 느려지는 데에는 여러 가지 요인이 있을 수 있습니다. 가장 일반적인 원인 중 하나는 버퍼 오버플로입니다. 버퍼는 아두이노와 라즈베리 파이 사이에 데이터를 임시적으로 저장하는 메모리 영역입니다. 버퍼가 가득 차면 추가 데이터를 저장할 수 없고 통신이 중단될 수 있습니다.

버퍼 오버플로를 방지하려면 다음과 같은 방법을 시도해 주세요.

  • 라즈베리 파이와 아두이노의 버퍼 크기를 늘립니다.
  • 데이터를 더 작은 청크로 전송합니다.
  • 통신 속도를 낮춥니다.

버퍼 오버플로가 아닌 경우 다른 문제가 있을 수 있습니다. 다음은 확인해 볼 수 있는 몇 가지 사항입니다.

  • 라즈베리 파이와 아두이노가 같은 보드 속도로 통신하고 있는지 확인합니다.
  • 사용하는 케이블이 손상되지 않았는지 확인합니다.
  • 아두이노의 소프트웨어나 펌웨어에 버그가 없는지 확인합니다.

아직도 문제가 해결되지 않으면 다음 사항을 시도해 볼 수 있습니다.

  • 아두이노와 라즈베리 파이를 재부팅합니다.
  • 아두이노의 소프트웨어나 펌웨어를 다시 설치합니다.
  • 라즈베리 파이의 운영 체제를 다시 설치합니다.

이러한 단계를 수행해도 문제가 해결되지 않으면 아두이노 또는 라즈베리 파이에 하드웨어 문제가 있을 수 있습니다.

여기서는 버퍼 오버플로에 대한 링크를 공유합니다.
https://www.allaboutcircuits.com/technical-articles/what-is-a-buffer/


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

안녕하세요! 라즈베리파이와 YOLOv5, 아두이노를 사용하여 차량 인식 시스템을 구축하셨군요. 자동 실행 시 통신 지연이 발생하는 문제로 고민이 많으시겠어요. 문제를 잘 이해했습니다. 명령창에서 실행할 때는 딜레이가 2초 이내였지만, 자동 실행 시 3초에서 10초까지 지연이 발생한다고 하셨습니다.

이 문제는 여러 가지 원인으로 발생할 수 있습니다. 시스템 리소스 관리, 프로세스 우선순위, 통신 설정 등이 영향을 미칠 수 있습니다. 아래에 몇 가지 해결책을 제안드리겠습니다.

  1. 시스템 리소스 확인: 자동 실행 시 시스템 리소스가 부족할 수 있습니다. top 명령어를 사용하여 CPU 및 메모리 사용량을 확인해보세요. systemd 설정에서 Nice=-10으로 설정하여 프로세스 우선순위를 높였지만, 다른 프로세스가 리소스를 많이 사용하고 있을 수 있습니다.

  2. 시리얼 통신 설정 확인: 시리얼 통신 속도가 적절한지 확인해보세요. 현재 설정은 115200 bps로 되어 있는데, 아두이노와 라즈베리파이 간의 통신 속도가 일치하는지 확인하세요.

  3. 코드 최적화: YOLOv5 모델의 추론 시간이 길어질 수 있습니다. 모델을 더 작은 버전으로 바꾸거나, 이미지 해상도를 줄여서 성능을 개선할 수 있습니다.

  4. 로그 확인: systemd 로그를 확인하여 추가적인 오류 메시지가 있는지 확인하세요. journalctl -u <서비스 이름> 명령어를 사용하여 로그를 확인할 수 있습니다.

  5. 비동기 처리 고려: 현재 코드에서는 차량이 감지될 때마다 아두이노로 신호를 보내고 있습니다. 비동기적으로 처리하여 메인 루프가 차단되지 않도록 개선할 수 있습니다.

아래는 비동기 처리를 위한 코드 예시입니다:

import serial
from picamera2 import Picamera2
import torch
import cv2
import numpy as np
import threading

def send_signal_to_arduino(arduino):
    arduino.write(b'1')
    print("Car detected! Signal sent to Arduino.")

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True).to(device)

picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={"format": "RGB888", "size": (320, 240)}))
picam2.start()

arduino = serial.Serial('/dev/ttyUSB0', 115200)

try:
    while True:
        frame = picam2.capture_array()
        img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        results = model(img)
        detected = results.pandas().xyxy[0]

        if len(detected) > 0:
            for i in range(len(detected)):
                if detected.iloc[i]['name'] == 'car':
                    threading.Thread(target=send_signal_to_arduino, args=(arduino,)).start()
                    break

        output_img = np.squeeze(results.render())
        output_img = cv2.cvtColor(output_img, cv2.COLOR_RGB2BGR)
        cv2.imshow("YOLOv5 Object Detection", output_img)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
finally:
    cv2.destroyAllWindows()
    picam2.stop()
    arduino.close()

위의 코드에서는 threading 모듈을 사용하여 아두이노로 신호를 보내는 작업을 별도의 스레드에서 처리합니다. 이렇게 하면 메인 루프가 차단되지 않고 계속해서 이미지를 처리할 수 있습니다.

추가적으로, PyTorch의 공식 튜토리얼을 참고하시면 더 많은 정보를 얻을 수 있습니다. PyTorch 튜토리얼 또는 한국어 튜토리얼을 방문해 보세요.

제 답변이 완벽하지 않을 수 있으니, 추가적인 정보가 필요하시다면 언제든지 말씀해 주세요. 감사합니다!


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