이번에는
카메라 영상출력, YOLO-NAS 객체 탐지, 바운딩 박스 오버레이, 메타데이터 추출까지
겪었던 모든 과정을 공유하려고 한다.
Rubik Pi 보드 기반으로 이 작업을 시도한 사례는
한국은 물론, 해외 커뮤니티에서도 찾기 힘들다.
그만큼 의미있는 도전이라고 생각한다.
목표(Rubikl Pi 보드 위에서)
- YOLO-NAS모델을 돌려 객체를 실시간으로 탐지
- 카메라 영상 디스플레이 출력
- 탐지된 객체 바운딩 박스 화면에 overlay
- 메타데이터(라벨, 좌표 정보)를 별도로 추출
초기 과정
처음에는 비교적 단순해 보였다.
GStreamer 하나만으로 메타데이터를 받아오고, 오버레이까지 처리할 생각이었다.
하지만 곧 문제가 발생했다.
이전 글에서도 다뤘듯이,
GStreamer만으로 메타데이터를 받아오는 시도는 실패했고,
대안으로 OpenCV를 이용한 후처리 방식을 시도했다.
OpenCV에서 바운딩 박스를 직접 그리는 것에는 성공했지만,
문제는 배경이 검정색으로 출력된다는 점이었다.
문제의 원인
Rubik Pi 보드는 GStreamer 파이프라인에서
GBM 메모리를 사용한다.
이를 OpenCV로 직접 넘길 때,
포맷 변환(NV12 → BGR) 과정이 제대로 되지 않아
OpenCV에서는 검정색 배경만 출력되었다.
생각보다 메모리 변환은 까다로웠다.
GStreamer에서 시스템 메모리로 변환해주려 했지만,
호환성, caps negotiation 오류 등으로
안정적으로 연결되지 않았다.
시도한 방법들
1. GSteamer에서 video/x-raw와 text/x-raw를 동시에 사용.
불가능하다.
위 그림에서 볼 수 있듯이.
한 qtimlvdetection에서는 video/x-raw, text/x-raw중 둘중 하나만 가능하다.
즉, 하나의 qtimlvdetection를 2개의 video, text브랜치로 나눌 수 없다는 것.
그래서 이 방법은 일찌감치 버렸다.
2. GStreamer -> OpenCV 후처리
GStreamer에서 프레임을 받아, OpenCV에서 bounding obx를 직접 그리면 된다고 생각했다.
실제로
- OpenCV에서 appsink로 프레임받아
- 바운딩 박스 그리고
- 라벨과 좌표까지 출력 성공
하지만, 배경은 검정색.
Rubik Pi는 GBM 메모리 포맷을 사용한다.
이를 OpenCV에서 바로 받아 처리하려면
NV12 -> BGR 변환이 필요한데,
이 과정에서 변환이 실패하거나 깨져서
OpenCV에서는 검정색 배경만 출력되었다.
근데 화면이 검정색이어도, 객체탐지, 바운딩박스, 여기서 좌표출력까지 되긴하니까
그냥 이대로 할까?... 싶었지만, 프로젝트 시연 시 문제가 될 수 있으므로 버렸다.
3. GStreamer내부에서 메타데이터만 받기
그럼 화면 출력은 GStreamer에서 하고,
메타데이터만 따로 Python으로 받자!
실패했다.
공식문서가 너무 부실하고, 공식문서대로 했지만 그것조차 문서대로 되지 않았다.
메타데이터를 받아오는것 자체가 안됐다.
그건 이전 포스팅에 적혀있다.
https://gstreamer.freedesktop.org/documentation/gstreamer/gstbuffer.html?gi-language=python
GstBuffer
GstBuffer Buffers are the basic unit of data transfer in GStreamer. They contain the timing and offset along with other arbitrary metadata that is associated with the GstMemory blocks that the buffer contains. Buffers are usually created with gst_buffer_ne
gstreamer.freedesktop.org
이 공식문서를 참고 했었다.
하지만, 여러번 시도 끝에 안됐음.. 이 방법도.
4. C언어 + 소켓 통신 (시도 직전까지 간 방법)
[C언어]
GStreamer 내부에서 buffer 직접 접근 → 메타데이터 추출 → JSON 변환
↓
↓ [socket]
↓
[Python]
JSON 수신 → OpenCV 렌더링 or 처리
이 방식은 아마 확실히 동작했을 것이다.
근데,
발표까지 한 달 정도 남은 시점에서, 이 방법을 시도하기엔 부담이 있었다.
그래서 버렸다.
최종 성공 과정 (qtimetamux + qtioverlay)
qtimetamux 로 detection 메타정보를 영상에 합치고,
qtioverlay로 GPU 바운딩 박스를 출력하는 방식
이런 방식의 파이프라인으로 수정을 했다.
결과적으로, 카메라 영상+바운딩박스+메타데이터 출력이 가능하게 되었다.
qtiqmmfsrc
→ qtivtransform
→ tee
├─> qtivtransform → qtimetamux → qtioverlay → waylandsink
└─> qtivtransform → qtimlvconverter → qtimlsnpe
→ qtimlvdetection
├─> text/x-raw → qtimetamux (메타 오버레이용)
└─> appsink name=meta_sink (Python 추출용)
최종적인 파이프라인은 이렇다.
근데, text/x-raw와 video/x-raw는 함께 출력할 수 없다고 했는데,
이건 어떻게 비디오와 메타데이터를 합쳤는가?
이 파이프라인은 text/x-raw만 사용한다.
text/x-raw는 메타데이터를 qtimetamux로 보내고, 영상 프레임도 qtimetamux로 보낸다.
qtimetamux는 두 데이터를 합치고, qtioverlay가 영상위에 메타정보(바운딩박스)를 그려준다.
'Qualcomm 기업과제' 카테고리의 다른 글
Rubik Pi 3 프레임 드랍 문제 해결, 멀티스레딩 (2) | 2025.05.07 |
---|---|
Rubik Pi 3 - 현재까지 진행 상황 (0) | 2025.05.04 |
Rubik Pi3 보드에서 객체 탐지 후, 메타데이터 받기 (0) | 2025.04.14 |
Rubik Pi 3에 Yolo v8 detection Quantized모델 올리기 (0) | 2025.04.11 |
Rubik Pi3 보드로 개발하기 (2) | 2025.04.10 |