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 훈련을 통해 가중치(.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 모델 파일이 생성된다.
이제 이 모델을 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를 확인할 수 있다.
그러면 컨버팅이 정말로 잘 되었는지 netron에서 확인해 보자. netro은 다음의 사이트에서 확인.
Netron
netron.app
사이트에 접속한 후 open model..로 클릭하여 최종 컨버팅된 onnx 파일을 선택하면 업로드되고 내용을 확인해 볼 수 있다.
일단 unity에서 잘되는지를 확인해 보는 것은 unity에서도 확인이 가능하겠지만 먼저 inputs의 내용 형식과 outputs의 형식에 이름이 제대로 들어가 있는지, tensor의 값이 잘못된 값(unity에서 인식 불가능)으로 되어 있는지 확인해 볼 수 있다.
컨버팅은 잘 되어도 인식을 안 하면 쓸 수 없다.
이제부터는 unity에서 진행할 차례이다.
준비할 것은 classes label 내용이 있는 텍스트 파일과 컨버팅 한 onnx 파일이다.
다음 포스팅에서 계속...
'개발 관련 > SW, App 관련' 카테고리의 다른 글
Unity6 설치(Sentis를 위해) 시도 (0) | 2024.11.18 |
---|---|
Yolov3을 이용한 Unity 사물인식 제작 정리(5) (1) | 2024.11.14 |
Yolov3을 이용한 Unity 사물인식 제작 정리(3) (5) | 2024.11.11 |
Yolov3을 이용한 Unity 사물인식 제작 정리(2) (3) | 2024.11.10 |
Yolov3을 이용한 Unity 사물인식 제작 정리(1) (7) | 2024.11.08 |
댓글