[객체인식 & Depth Estimation 프로젝트] 2. YOLO v3 tiny 실행 전체 과정

happy_quokka·2024년 1월 5일
0

자율주행 프로젝트

목록 보기
8/15

YOLO v3 tiny 모델을 사용하여 모델을 학습하고 자이카에서 사용하기 위해 onnx, tensorRT 변환을 수행해야 한다.

0. 모델 사용 과정

  1. YOLO v3 tiny 모델 학습
  2. darknet weight로 변환 & onnx 모델 변환
  3. onnx weight 변환 & tensorRT로 변환
  4. trt 모델을 이용한 detection + ROS

1. model 학습

1-1. model download

https://github.com/2damin/yolov3-pytorch 에서 clone 받아온다

$ git clone https://github.com/2damin/yolov3-pytorch.git
  • onnx-1.6 branch 사용 (자이카에 맞게 update된 버전이다)

1-2. 환경 설정

  • linux의 경우 docker를 사용하여 환경 설정
  1. docker 이미지 pull
$ docker pull nvcr.io/nvidia/pytorch:21.12-py3
  1. container 생성
$ docker run -it -v ${PWD}/deep_learning_project:/yolov3-pytorch --name yolo_torch nvcr.io/nvidia/pytorch:21.12-py3 /bin/bash
  1. vscode에서 생성한 container와 연결
  2. 라이브러리 설치
# pip install -r requirements.txt

1-3. model 실행

  • 먼저 수정해야하는 사항
    • yolov3.py의 ONNX_EXPORT = False
      • 학습할 때는 무조건 이 값이 False여야한다
    • yolodata.py의 데이터 경로 변경
  • train
# python main.py --mode train --cfg yolov3-tiny_tstl_352.cfg --pretrained yolov3-tiny.weights

cv2 관련 에러

  • 에러
AttributeError: partially initialized module 'cv2' has no attribute '_registerMatType' (most likely due to a circular import)
  • 해결
pip install "opencv-python-headless<4.3"

import onnx 사용시 에러

  • 에러
Traceback (most recent call last):
  File "main.py", line 20, in <module>
    import onnx,onnxruntime
  File "/opt/conda/lib/python3.8/site-packages/onnx/__init__.py", line 11, in <module>
    from onnx.external_data_helper import load_external_data_for_model, write_external_data_tensors, convert_model_to_external_data
  File "/opt/conda/lib/python3.8/site-packages/onnx/external_data_helper.py", line 14, in <module>
    from .onnx_pb import TensorProto, ModelProto
  File "/opt/conda/lib/python3.8/site-packages/onnx/onnx_pb.py", line 8, in <module>
    from .onnx_ml_pb2 import *  # noqa
  File "/opt/conda/lib/python3.8/site-packages/onnx/onnx_ml_pb2.py", line 32, in <module>
    _descriptor.EnumValueDescriptor(
  File "/opt/conda/lib/python3.8/site-packages/google/protobuf/descriptor.py", line 789, in __new__
    _message.Message._CheckCalledFromGeneratedFile()
TypeError: Descriptors cannot be created directly.
If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
If you cannot immediately regenerate your protos, some other possible workarounds are:
 1. Downgrade the protobuf package to 3.20.x or lower.
 2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).

More information: https://developers.google.com/protocol-buffers/docs/news/2022-05-06#python-updates
  • 해결
pip install protobuf==3.20

2. darknet weight 변환 & onnx 모델 변환

학습한 model weight를 darknet 형식의 weight로 변환하고, pytorch model을 onnx 형식의 model로 변환하는 부분

설정

  • yolov3.py에서 ONNX_EXPORT = True로 설정
  • yololayer에서 이 조건으로 인해 forward할 때 입력을 그대로 출력으로 보낸다
    • tensorRT의 postprocess로 기존의 yololayer가 작동하기 때문이다
  • model의 결과가 list로 return 된다
    • 원래를 torch.cat을 한 결과가 return된다

코드 설명

  • model.save_darknet_weights()를 통해 pytorch model를 darknet weight로 변환해준다
    • onnx의 경우 하드웨어에 올릴 때 tensorRT 라이브러리 버전에 따라 onnx가 호환이 되는 버전이 있고 안되는 경우가 있다
    • 이를 피하기 위해 darknet을 통해 onnx로 변환한다
  • torch.onnx.export(model, 값, 원하는 파일 이름) 를 통해 pytorch model을 onnx 형식의 model로 변환
  • onnx 검증 코드
    • ort_session을 연 후 onnx 모델에 똑같은 input을 넣어서 onnx의 결과와 torch의 결과를 비교한다
    • np.testing.assert_allclose() 함수 사용
    • 내부적인 알고리즘이 다르고, onnx로 변환되면서 최적화되는 layer들이 있어서 완전히 두 결과가 같을 수는 없다

실행 및 결과

python main.py --mode onnx --cfg ./cfg/yolov3.cfg --checkpoint ${saved_checkpoint_path}
  • onnx와 darknet의 weight가 저장된다
    • .onnx 파일, .weights 파일

3. onnx weight 변환 & tensorRT로 변환

https://github.com/2damin/yolov3_onnx_rt 에서 tensorrt-8.2.1 branch 사용

  • guide부분은 자이카에서 진행하면된다

3-1. onnx weight 변환

  • yolov3_to_onnx.py
  • darknet에서 onnx weight로 바꿔주는 부분
  • cfg 파일, weight 파일(앞에서 만들어준 darknet weight), num_classes만 잘 넣어주면 실행된다
  • darknet weight를 불러와서 각 layer에 맞게 onnx node를 만들어주고 최종적으로 onnx weight를 만든다

3-2. tensorRT로 변환

  • onnx_to_tensorrt.py
  • onnx를 tensorRT로 반환
  • 자이카에서 작업해야한다
  • tensorRT 엔진을 만드는 경우에 tensorRT는 해당 하드웨어에 최적화되게끔 만들기 때문에 local 환경에서는 안된다
  • get_engine()
    • onnx -> tensorRT
    • 자이카의 메모리 계산
    • output 계산
    • 결과 show

4. trt 모델을 이용한 detection + ROS

  • 주행코드를 짜는 부분

  • trt_detection.py

    • cfg, trt 경로 넣어주기
  • 이때 코드가 python2로 구현되어 있는데 실제 환경은 python3이기 때문에 에러가 발생할 수 있다

  • cv2.bridge를 사용할 수 없다는 에러인데 아래와 같이 변경하면 해결된다

0개의 댓글