본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 15. 14:16

데스크톱을 캡처하여 이미지 인식 모델을 테스트하는 도구

요약

데스크톱 화면을 캡처하여 RF-DETR, SAM2, MediaPipe 등 다양한 이미지 인식 모델을 즉시 테스트할 수 있는 Python 기반 도구입니다. 별도의 데이터셋 준비 없이 GUI를 통해 모델별 성능을 비교하고 아이디어를 검증할 수 있습니다.

핵심 포인트

  • 데스크톱 화면 영역을 실시간 입력 소스로 활용하여 테스트 편의성 증대
  • RF-DETR, SAM2, MediaPipe 등 다양한 모델을 하나의 GUI에서 전환하며 비교 가능
  • 라이선스 제약이 적은 Apache/MIT 라이선스 모델 중심의 구성
  • uv를 이용한 간편한 환경 구축 및 설치 지원

화면상의 임의 영역을 캡처하여 RF-DETR / SAM2 / MediaPipe로 해석하고 별도의 창에 표시하는 Python 애플리케이션 capture-recognizer1을 만들었습니다.

이미지 인식 모델을 비교 검증하고, 무언가에 활용할 수 없을지 아이디어를 낼 때 유용한 도구입니다. 동영상 파일을 준비하거나, 카메라를 연결하거나, 입력 소스마다 스크립트를 작성하기 전에, 데스크톱 상의 GUI로 대략적으로 테스트할 수 있도록 하는 것을 목적으로 하고 있습니다.

예를 들어 Web 브라우저, 동영상 플레이어, PDF, 게임 화면, 기존 앱의 화면 등 데스크톱에 표시할 수 있는 것이라면 그대로 인식 대상으로 삼을 수 있습니다. 실험용으로는 이것만으로도 충분히 편리합니다.

이미지 인식 모델을 테스트할 때 의외로 번거로운 것이 입력 데이터의 준비입니다.

이미지 1장이면 아직 간단하지만, 동영상으로 테스트할 경우에는 동영상 파일을 준비하고, 프레임을 추출하여, 추론 (Inference) 스크립트에 전달하고, 결과를 그려서 확인하는 흐름이 됩니다. 카메라 입력으로 테스트할 경우에는 카메라를 연결하고, 디바이스 번호를 확인하고, 해상도나 권한 관련 설정을 조정해야 합니다.

조금 테스트해보고 싶을 뿐인데, 입력 부분에서 수고가 많이 듭니다.

그래서 화면에 표시되어 있는 것을 그대로 입력으로 사용하면 되지 않을까 생각했습니다. 동영상 파일도, YouTube도, Web 카메라 영상도, 기존 앱의 화면도 일단 데스크톱에 표시되어 있다면 동일하게 다룰 수 있습니다.

하고 싶은 일은 단순합니다.

  • 캡처 창에서 인식하고 싶은 범위를 지정
  • 시작 버튼을 누름
  • 별도의 창에 인식 결과(Recognition result)를 겹쳐서 표시
  • 모델과 태스크(Task)를 전환하며 비교

이러한 용도라면 학습 데이터셋(Dataset)의 정비나 동영상 파이프라인(Pipeline) 구축까지는 필요하지 않습니다. 우선 실행해서 살펴보고 싶다는 단계에 맞춘 도구입니다.

처음에 생각한 것은 YOLO 계열 모델을 사용하는 것이었습니다. 객체 탐지 (Object Detection) 샘플이 많고 동작도 가벼워 실험에 적합합니다.

하지만 Ultralytics YOLO 계열에는 AGPL-3.0이라는 라이선스상의 제약이 있습니다. 개인적인 실험뿐이라면 문제가 되지 않는 경우도 많겠지만, 만든 도구를 공개하거나 나중에 다른 용도로 전용하는 것을 고려하면 처음부터 라이선스 취급이 쉬운 모델을 사용해 두고 싶습니다.

그래서 이 프로젝트에서는 Apache License나 MIT 라이선스의 모델·라이브러리를 중심으로 구성했습니다.

  • RF-DETR

  • 객체 탐지 (Object Detection)에 사용합니다.

  • 본 프로젝트에서는 경량 모델인 RFDETRNano를 사용합니다.

  • detect에서는 사각형(Rectangle), 라벨(Label), 신뢰도(Confidence)를 표시합니다.

  • classify에서는 검출 결과의 라벨을 집계하여 화면 내에 무엇이 있는지 목록으로 표시합니다.

  • SAM2

  • 세그멘테이션 (Segmentation)에 사용합니다.

  • segment로 화면 영역을 자동 마스크 생성하여 반투명한 색으로 겹쳐 표시합니다. 클래스명을 출력하기보다는 어떤 영역이 분할되는지를 보는 용도입니다.

  • MediaPipe

  • 자세 (Pose), 손 (Hand), 얼굴 (Face)의 랜드마크 검출에 사용합니다.

  • pose, hands, facemesh를 구현하고 있습니다. 가볍게 동작하므로 실시간 표시와 궁합이 좋습니다.

하나의 모델로 모든 것을 하는 것이 아니라, 용도가 다른 모델을 동일한 GUI에서 전환할 수 있도록 했습니다. 객체 탐지, 세그멘테이션, 자세 추정 (Pose Estimation)을 동일한 입력 화면에서 비교할 수 있으면 아이디어를 내기가 훨씬 수월해집니다.

설치는 uv를 사용합니다.

cd capture-recognizer1
uv sync

백엔드별로 추가 의존성을 넣는 경우는 다음과 같이 지정합니다.

uv sync --extra mediapipe
uv sync --extra rfdetr
uv sync --extra sam2
...

GPU를 포함하여 사용하는 경우에는 all-gpu를 지정합니다.

uv sync --extra all-gpu
uv run python scripts/verify_gpu.py

실행 예시입니다.

uv run capture-recognizer1 --model mediapipe --task pose --device auto
uv run capture-recognizer1 --model rfdetr --task detect --device cpu
uv run capture-recognizer1 --model sam2 --task segment --device cuda

실행하면 캡처 창과 분석 창이 표시됩니다. 캡처 창의 투명한 본체 부분을 인식하고자 하는 화면 위에 겹쳐 놓고 '시작'을 누르면 분석이 시작됩니다.

캡처 창은 타이틀 바를 드래그하여 이동할 수 있습니다. 프레임 근처를 드래그하면 크기를 조절할 수 있습니다. 너비와 높이 입력란은 타이틀 바와 프레임을 제외한 캡처 대상 본체의 크기입니다.

GUI는 PySide6로 구현했습니다. 캡처 범위를 나타내는 창은 독자적인 타이틀 바와 프레임을 가진 프레임리스 윈도우 (frameless window)입니다.

투명한 본체 부분을 캡처 대상으로 삼고, 분석 결과는 별도의 일반 창에 표시합니다. 캡처 창 자체에 결과를 그리는 대신 별도의 창으로 분리한 이유는 원본 화면과 분석 결과를 비교하기 쉽게 하기 위해서입니다.

전체 흐름은 다음과 같습니다.

  • 실행 시 INI 설정을 읽어옴
  • CLI 인수로 모델, 태스크 (task), 디바이스 (device) 설정을 덮어씀
  • 모델과 태스크의 조합을 검증함
  • 플랫폼별 캡처 백엔드 (capture backend)를 생성함
  • 추론 러너 (inference runner)를 생성함
  • 캡처 창과 분석 창을 생성함
  • 시작 버튼으로 캡처 루프를 시작함
  • 캡처한 프레임을 추론 러너로 전달함
  • 추론 결과를 공통 형식으로 변환함
  • OpenCV로 결과를 그려서 분석 창에 표시함

추론 결과는 모델별 로우 데이터 (raw value)를 그대로 GUI로 흘려보내지 않고, 공통의 InferenceResult로 변환합니다.

  • boxes: RF-DETR의 검출 사각형
  • labels: RF-DETR의 분류 스타일 라벨 표시
  • masks: SAM2의 세그멘테이션 마스크 (segmentation mask)
  • landmarks: MediaPipe의 자세, 손, 얼굴의 키포인트 (keypoint)

그리기 측은 이 공통 형식만 확인합니다. 모델을 추가하는 경우에도 추론 러너가 InferenceResult를 반환하면 동일한 분석 창에 표시할 수 있습니다.

캡처 처리는 OS마다 조금씩 다릅니다.

Windows에서는 pywin32를 사용하여 Qt 창의 클라이언트 좌표를 스크린 좌표로 변환하고, mss로 획득합니다.

Linux X11에서는 QWidget.mapToGlobal()mss를 사용합니다. HiDPI 환경에서는 Qt 좌표와 물리 픽셀 좌표가 어긋나기 때문에 DPR 보정을 적용했습니다.

Linux Wayland에서는 mss를 통한 임의 영역 캡처를 사용하기 어렵기 때문에, Qt의 QScreen.grabWindow()를 사용합니다. 내부적으로는 xdg-desktop-portal을 경유하므로, 최초 실행 시 화면 공유 허용 다이얼로그가 나타날 수 있습니다.

화면 캡처는 OS나 데스크톱 환경에 따라 차이가 발생하기 쉬운 부분입니다. 생각보다 은근히 까다로웠습니다.

모델 파일은 리포지토리 직하단의 models/에 배치합니다. 부족한 경우 최초 실행 시 자동으로 다운로드를 시도합니다.

  • MediaPipe: pose_landmarker.task, hand_landmarker.task, face_landmarker.task
  • SAM2: sam2.1_hiera_small.pt
  • RF-DETR: rf-detr-nano.pth

다운로드는 우선 curl을 사용하며, curl이 없는 환경에서는 Python 표준 라이브러리인 urllib로 폴백 (fallback)합니다. Windows 환경에서는 OpenSSL이나 HTTPS 관련 라이브러리 호환성 문제가 발생할 수 있어, 모델 파일 취득을 앱 측에서 제어할 수 있도록 했습니다.

생각보다 편리했습니다.

특히 브라우저에서 동영상을 재생하면서 mediapipe/pose를 겹치거나, 웹 페이지나 사진 뷰어에 rfdetr/detect를 적용하거나, UI 화면에 sam2/segment를 적용할 수 있는 점이 좋습니다.

모델을 비교할 때는 입력 데이터를 통일해야 합니다. 이 도구에서는 동일한 데스크톱 영역을 유지한 채 실행 옵션만 변경하면, 모델별로 어떻게 보이는지 즉시 확인할 수 있습니다.

예를 들어 다음과 같이 사용할 수 있습니다.

  • 웹캠 (Web camera) 영상을 표시하여 MediaPipe의 자세 추정 (Pose estimation)을 테스트
  • 동영상 플레이어 상의 인물이나 물체를 RF-DETR로 검출
  • 이미지 뷰어 상의 사진을 SAM2로 세그멘테이션 (Segmentation)
  • 직접 만든 앱의 화면을 캡처하여 UI 요소가 어느 정도 인식되는지 확인
  • 인식 모델을 사용한 새로운 기능의 아이디어 구상

제대로 된 평가를 위해서는 전용 데이터셋과 지표가 필요하지만, 초기 아이디어 단계에서는 "일단 화면에 적용해 보는 것"만으로도 충분한 정보를 얻을 수 있습니다.

아직 실험용 도구입니다.

SAM2와 RF-DETR은 CPU에서 무겁고, 캡처 크기를 크게 하면 응답이 느려집니다. GPU를 사용하면 개선되지만, 모델이나 화면 크기에 따라 프레임 레이트 (Frame rate)는 상당히 달라집니다.

또한, 캡처 창의 바디 (Body) 부분은 시각적으로는 투명하지만, OS 레벨에서 마우스 이벤트를 백그라운드 앱으로 완전히 투과시키는 것까지는 구현되지 않았습니다. Qt의 WA_TransparentForMouseEvents는 Qt 앱 내부의 이벤트 투과를 의미하며, Windows, X11, Wayland에서 동일한 동작을 기대할 수 있는 것이 아닙니다.

Wayland에서는 화면 캡처 권한 관리도 있어, X11이나 Windows와는 다른 구현이 필요합니다. 이 부분은 데스크톱 앱으로서 피할 수 없는 부분이었습니다.

capture-recognizer1은 데스크톱 상의 임의 영역을 그대로 이미지 인식 모델에 전달하기 위한 작은 GUI 도구입니다.

동영상 파일이나 카메라 입력 준비 과정을 생략하고, 화면에 표시되는 것을 그대로 입력으로 사용할 수 있습니다. RF-DETR, SAM2, MediaPipe를 동일한 GUI에서 전환할 수 있으므로, 이미지 인식 모델을 비교 검증하며 활용 방안에 대한 아이디어를 내는 단계에서는 매우 편리합니다.

YOLO 계열의 간편함도 매력적이지만, 라이선스 제약을 피하기 위해 Apache License나 MIT 라이선스의 모델 및 라이브러리를 중심으로 구성했습니다. 공개하기 쉽고, 나중에 다른 용도로 확장하기 용이한 실험 도구가 되었다고 생각합니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0