개발 관련/SW, App 관련

Yolov3을 이용한 Unity 사물인식 제작 정리(4)

by 소서리스25 2024. 11. 12.
반응형

Yolov3을 이용한 Unity 사물인식 제작 정리(4)

 

7. ONNX 컨버팅

 

이제 다음 단계는 onnx로 컨버팅 하는 사항이다. 최근에야 비로소 unity에서 인식 가능하도록 진행되었다. 아마도 상위 버전의 프로그램들을 사용했다면 더 빨리 진행되었을 것이다.

우선 Darknet의 실행파일이 있는 폴더에서 backup 폴더로 가보면 가중치 결과 파일이 저장되어 있을 것이다.

 

steps 값이 있어 여러 파일이 생성되어 있겠지만 실제적으로 사용할 파일은 yolov3-tiny_final.weights 가중치 파일이다.

 

일단 파일은 그대로 두고 아래의 git에서 keras-yolo3을 가져온다.

즉, Darknet의 weights(가중치) 파일을 keras 모델로 변형(재훈련?)하는 것이다. 여기서 그 형식을 CoreML로 컨버팅 하는 것이다.

GitHub - qqwweee/keras-yolo3: A Keras implementation of YOLOv3 (Tensorflow backend)

 

GitHub - qqwweee/keras-yolo3: A Keras implementation of YOLOv3 (Tensorflow backend)

A Keras implementation of YOLOv3 (Tensorflow backend) - qqwweee/keras-yolo3

github.com

 

yolo3에 대해서는 위 깃에서의 데이터를 이용할 것이다.

 

그리고 이제 CoreML로 컨버팅 하는 것은 아래의 깃을  확인해 보면 된다.

Convert darknet pre-trained model to CoreML model · GitHub

 

Convert darknet pre-trained model to CoreML model

Convert darknet pre-trained model to CoreML model. GitHub Gist: instantly share code, notes, and snippets.

gist.github.com

 

이 두 깃을 조합으로 컨버팅이 가능해졌다. python을 잘 모르니 시행착오를 많이 겪으면서 어떻게든 했던 것 같다.

위의 두 개의 깃을 공개한 것에 대해 매우 감사하다.

 

아무튼 CoreML 변환 내용을 convert.py로 되어 있지만 단계별 컨버팅을 해야 하니 convert2CoreML.py 로 변경하여 저장한다.

그다음 내용을 수정해 줘야 한다. 예전 포스팅에도 있던 내용이지만 다시 확인한다.

 

전체 내용 중 274줄 아래에 다음의 내용을 삽입한다.

        elif section.startswith('region'):
            with open('{}_anchors.txt'.format(output_root), 'w') as f:
                print(cfg_parser[section]['anchors'], file=f)

 

삽입하는 이유는 yolov3-tiny.cfg에서 저 "region"이란 항목이 있기 때문에 처리를 해 주어야 한다. 없으면 오류가 발생한다.

anchors에 대한 것으로 결과에는 영향이 없겠지만 삭제하는 것보단 유지하는 것이 좋을 것 같다. anchors값을 추출하여 텍스트로 저장하는 것이니 그냥 추가해 주자.

 

그다음으로 원래 내용의 291줄 아래를 다음과 같이 변경해 준다. 불필요한 것은 주석처리 하는 것이다.

#        input_names='input1', image_input_names='input1', output_names='output1', image_scale=1/255.,
         input_names='input1', image_input_names='input1', output_names=['output1', 'output2'], image_scale=1/255.,
#        input_names='input1', image_input_names='input1', output_names=['output3', 'output2', 'output1'], image_scale=1/255.,		
        add_custom_layers=True,custom_conversion_functions={ "Mish": convert_mish })
    coreml_model.input_description['input1'] = 'Input image'
    coreml_model.output_description['output1'] = 'The 13x13 grid (Scale1)'
    coreml_model.output_description['output2'] = 'The 26x26 grid (Scale2)'
#    coreml_model.output_description['output3'] = 'The 52x52 grid (Scale3)'
    coreml_model.save(output_path)

 

위의 내용은 yolov3-tiny의 경우 2개의 출력을 갖는다. 따라서 마지막 한 개는 사용하지 않도록 한다.

 

아울러 yolov2-tiny로 사용하려면 1개의 출력으로 변경해 주어야 한다. 만약 yolov2-tiny로 weights를 뽑았다면 아래와 같이 수정한다.

         input_names='input1', image_input_names='input1', output_names='output1', image_scale=1/255.,
#         input_names='input1', image_input_names='input1', output_names=['output1', 'output2'], image_scale=1/255.,
#        input_names='input1', image_input_names='input1', output_names=['output3', 'output2', 'output1'], image_scale=1/255.,		
        add_custom_layers=True,custom_conversion_functions={ "Mish": convert_mish })
    coreml_model.input_description['input1'] = 'Input image'
    coreml_model.output_description['output1'] = 'The 13x13 grid (Scale1)'
#    coreml_model.output_description['output2'] = 'The 26x26 grid (Scale2)'
#    coreml_model.output_description['output3'] = 'The 52x52 grid (Scale3)'
    coreml_model.save(output_path)

 

간단하게 주석처리 정도만 변경한 것이다.

 

CoreML 컨버팅에 대한 예전 포스팅 참고하기

Darknet 사물인식 진행 상황

 

Darknet 사물인식 진행 상황

Darknet 사물인식 진행 상황 지난번 커스텀데이터로 Darknet 훈련을 통해 가중치(.weights) 파일을 얻고 이 가중치를 통한 테스트는 정상적으로 잘되었었다. 문제는 이 가중치 파일을 다이렉트로 on

tipon.tistory.com

 

그러면 yolov3-tiny로 CoreML 컨버팅 할 전체 코드를 convert2CoreML.py로 저장한다. 저장위치는 keras-yolo3 폴더이다.

 

그리고 컨버팅 전에 아까 훈련했던 폴더에서 weights 가중치 파일과 yolov3-tiny.cfg를 컨버팅 할 폴더에 복사한다. 

이제 다음의 컨버팅 명령어로 python에서 실행한다.

python convert2CoreML.py yolov3-tiny.cfg yolov3-tiny_final.weights yolov3-tiny_final.mlmodel

 

컨버팅은 GPU가 아닌 CPU로도 충분하기 때문에 GPU와 관련된 경고 메시지(파일이 없다는 둥...)가 나와도 무시하면 된다. 생각보다 금방 끝난다.

컨버팅 진행중...
컨버팅 진행중...

 

컨버팅이 완료되면 기존의 weights 파일외에 CoreML 모델 파일이 생성된다.

생성된 coreml 모델 파일

 

이제 이 모델을 onnx로 컨버팅 할 텐데 아래의 내용을 convert_ml2onnx.py로 저장하자

import onnxmltools
import coremltools

# Load a Core ML model
coreml_model = coremltools.utils.load_spec('yolov3-tiny_final.mlmodel')

# Convert the Core ML model into ONNX
onnx_model = onnxmltools.convert_coreml(coreml_model, 'yolov3-tiny')

# Save as protobuf
onnxmltools.utils.save_model(onnx_model, 'yolov3-tiny_final.onnx')

 

혹시나 컨버팅 하다가 분명 설치했는데 모듈이 없다고 나오거나 오류가 날 수 있다. 그러면 패키지를 uninstall 한 다음 다시 버전에 맞춰 설치하면 된다.(이것저것 하다가 의도치 않게 버전이 업그레이드될 수 있다.)

import 된 모듈은 onnx의 opset 버전이 9까지만 된다. unity에서 9까지로 하라고 되어 있어서 일단 설치 버전에 맞추도록 한다.

 

위의 내용은 잘 보면 쉽게 알 수 있다. 변경할 모델과 내용, 그리고 저장할 onnx 파일명이다.

 

다음의 명령어로 컨비팅 해보자

python convert_ml2onnx.py

 

그러면 아래와 같이 진행되며 변환된 onnx를 확인할 수 있다.

컨버팅 진행중...

 

onnx 컨버팅 결과

 

그러면 컨버팅이 정말로 잘 되었는지 netron에서 확인해 보자. netro은 다음의 사이트에서 확인.

Netron

 

Netron

 

netron.app

 

사이트에 접속한 후 open model..로 클릭하여 최종 컨버팅된 onnx 파일을 선택하면 업로드되고 내용을 확인해 볼 수 있다.

netron으로 onnx 모델 확인
netron으로 onnx 모델 확인

 

일단 unity에서 잘되는지를 확인해 보는 것은 unity에서도 확인이 가능하겠지만 먼저 inputs의 내용 형식과 outputs의 형식에 이름이 제대로 들어가 있는지, tensor의 값이 잘못된 값(unity에서 인식 불가능)으로 되어 있는지 확인해 볼 수 있다.

컨버팅은 잘 되어도 인식을 안 하면 쓸 수 없다.

 

이제부터는 unity에서 진행할 차례이다.

준비할 것은 classes label 내용이 있는 텍스트 파일과 컨버팅 한 onnx 파일이다.

 

 

다음 포스팅에서 계속...

 

반응형

댓글