WPF OpenCV 프로젝트 #9: ROI(관심 영역) 설정을 위한 UI 구성 (OverlayCanvas)

ROI(관심 영역) 설정을 위한 UI 구성(OverlayCanvas)WPF OpenCV 프로젝트에서 다루겠습니다.
지난 포스팅에서 우리는 이미지를 불러와 확대/축소(Zoom)하고, 휠 버튼으로 이동(Panning)하는 기능까지 구현했습니다.

이제 영상 처리의 핵심이라 할 수 있는 관심 영역(ROI, Region of Interest) 기능을 구현해 볼 차례입니다. 전체 이미지를 통째로 처리하는 경우도 있지만, 현업에서는 특정 부분만 잘라내서 검사하거나, 모델을 등록하는 경우가 훨씬 빈번하니까요. 아무튼 ROI 지정을 위한 UI 설계WPF의 그리기 철학(?)에 대해 이야기해 보겠습니다.

Border vs Image

본격적인 코딩에 앞서 구조를 잠깐 짚고 넘어가겠습니다. 이전 글에서 우리는 Border(액자) 안에 Canvas를 넣고 그 안에 Image를 넣었습니다. 확대/축소의 기준은 ‘액자(Border)’였죠.

하지만 ROI(관심 영역)는 다릅니다. ROI는 화면이 아니라 이미지 데이터 자체를 따라가야 합니다. 이미지를 10배 확대해서 강아지 얼굴에 사각형을 그렸다면, 축소했을 때도 그 사각형은 강아지 얼굴에 딱 붙어 있어야 하니까요.

그래서 우리는 기존 이미지 위에 투명한 도화지(Canvas)를 한 장 더 얹을 겁니다. 이 도화지는 이미지와 똑같은 크기와 변환(Transform) 속성을 가집니다.

ContextMenu

먼저 마우스 우클릭 시 사용할 메뉴를 정의하겠습니다. ROI 그리기, 지우기, 화면 맞춤 기능을 넣을 예정입니다. MainWindow.xaml<Window.Resources> 섹션(Section)에 아래 코드를 추가해 주세요.

OverlayCanvas와 IsHitTestVisible

이제 MainWindow.xaml의 메인 구조를 수정합니다. 기존 Image 컨트롤 바로 아래에, ROI를 그릴 CanvasRectangle을 추가합니다.

💡 IsHitTestVisible=”False”

위 코드에서 OverlayCanvasIsHitTestVisible="False" 속성을 준 것을 주목해주세요. 아주 중요합니다. 이 캔버스는 이미지 바로 위를 덮고 있습니다.
만약 이 속성이 True(기본 값)라면, 사용자가 이미지를 이동(Pan)하려고 클릭했을 때 투명한 캔버스가 클릭을 가로채 버립니다.
결국 뒤에 있는 이미지는 꼼짝도 하지 않는 ‘먹통’ 상태가 되죠. False로 설정해야 클릭 이벤트가 캔버스를 “뚫고 지나가” 뒤에 있는 ZoomBorder에 전달되어 줌/이동 기능이 정상 작동합니다.

개발자 노트: WPF에서 ‘그린다’는 것의 의미

잠깐 제 ‘썰’을 좀 풀고 가겠습니다. (WinForms이나 C++ GDI+ 경험자분들은 공감하실 겁니다.)

예전에 우리는 도형을 그릴 때 어떻게 했나요? 펜(Pen)을 잡고, 색상을 고르고, DrawRectangle() 같은 함수를 호출해서 직접 그렸습니다. 이를 명령형(Imperative) 방식이라고 합니다.

하지만 WPF는 선언 형(Declarative) 방식입니다. WPF에서 사각형은 ‘그리는 동작’이 아니라, ‘이미 만들어져 있는 물건’입니다. 위 코드의 Rectangle은 프로그램 시작과 동시에 이미 존재합니다.
다만 Visibility="Collapsed"로 설정해서 눈에 안 보이고 공간도 차지하지 않게 숨겨뒀을 뿐이죠.

우리는 나중에 C# 코드에서 이 녀석을 Visibility="Visible"로 바꾸고, 위치와 크기(Margin, Width, Height)만 조절해서 “짠!” 하고 보여줄 겁니다.

🧪 테스트: 진짜로 그려져 있나 확인하기

못 믿으시겠다면 Rectangle 태그의 속성을 아래처럼 바꾸고 실행해 보세요.

WPF Rectangle 테스트 화면

보시다시피 그리기 함수를 하나도 안 썼는데 빨간 사각형이 떡 하니 떠 있죠? 이 개념을 이해해야 나중에 코드를 짤 때 “도대체 이 사각형은 언제 그린 거야?” 하며 머리를 쥐어 짜지 않게 됩니다.

마무리

오늘은 ROI 구현을 위한 UI 뼈대를 튼튼하게 세웠습니다. OverlayCanvas 를 이용한 계층 구조와 IsHitTestVisible 을 이용한 이벤트 투과 처리, 그리고 WPF의 그리기 방식에 대해 알아봤습니다.

UI 설명 만으로도 글이 꽤 길어졌네요. 실제로 마우스를 드래그 해서 사각형을 그리고, 좌표를 계산하는 C# 코드(Code Behind)는 다음 포스팅에서 자세히 다루도록 하겠습니다.

참고 링크:

WPF Canvas:
https://learn.microsoft.com/ko-kr/dotnet/api/system.windows.controls.canvas
UIElement.IsHitTestVisible:
https://learn.microsoft.com/ko-kr/dotnet/api/system.windows.uielement.ishittestvisible
WPF ContextMenu:
https://learn.microsoft.com/ko-kr/dotnet/desktop/wpf/controls/contextmenu-overview

댓글 남기기