WPF OpenCV 프로젝트 #14: Bug 수정 (Zoom 측정 시 ROI 좌표 틀어짐 해결) 및 Line Distance (직선 거리 측정) 구현


Bug 수정 (Zoom 측정 시 ROI 좌표 틀어짐 해결)직선 거리 측정WPF OpenCV 프로젝트에 구현하겠습니다.
지난 13편까지 우리는 도형 그리기ROI 설정까지 정말 많은 기능을 숨 가쁘게 구현해 왔습니다. 그런데 혹시… 뭔가 이상한 점 못 느끼셨나요? (12편부터 계속되던 문제였는데 말이죠.)

ROI 사각형을 예쁘게 그려 놓고, 마우스 휠을 돌려 이미지를 확대/축소(Zoom In/Out) 했을 때, 빨간색 ROI 사각형이 얌전히 있던가요? 아니면 배경 이미지만 확대 축소 되고, ROI 사각형은 전혀 변경되지 않는 문제와 ROI 사각형이 엉뚱한 곳으로 날아가 버리지 않던가요?

“어라? 이런 미친 ROI 사각형이 이미지를 안 따라가네?”

사실 이미지 줌/이동을 먼저 구현하고 ROI를 나중에 얹다 보니, 줌 이벤트 발생 시 ROI 좌표를 재 계산하는 로직을 빠뜨렸습니다. (개발하다 보면 흔히 있는 일이죠? 제가 찾았으니 다행입니다. 하하.)

오늘은 이 치명적인 버그를 수정하고, 기왕 손대는 김에 직선을 그렸을 때 길이(Distance)를 측정해서 보여주는 멋진 기능까지 추가해 보겠습니다.

Bug 수정: 확대/축소 시 ROI가 따라오지 않는 문제

원인 분석

위에 첨부된 동작 영상을 보면 작업하고 있는 WPF OpenCV 프로젝트의 ZoomBorder에서 마우스 휠 이벤트를 받아 이미지를 확대(ScaleTransform)하고 있습니다. 하지만 OverlayCanvas 위에 그려진 ROI 사각형(RoiRect)은 “화면상(Screen)의 절대 좌표“를 가지고 있습니다.

이미지는 커졌는데 사각형의 위치와 크기는 그대로라면? 당연히 사각형이 이미지의 엉뚱한 위치를 가리키게 되겠죠. 따라서 휠 을 돌릴 때마다 ROI 사각형의 위치와 크기도 배율에 맞춰 다시 계산(Update) 해줘야 합니다.

ZoomBorder_MouseWheel 수정

MainWindow.xaml.csZoomBorder_MouseWheel 함수를 찾아가서, 마지막 부분에 아래 코드를 추가하여 정상적인 동작을 하지 못하던 버그를 수정하도록 하죠.

Bug 수정 내용

UpdateRoiVisual(...) 호출: 이 함수 기억나시죠? “이미지 기준 좌표”를 입력 받아 현재의 줌/이동 상태를 반영해 “화면 좌표”로 변환해 주는 핵심 함수입니다. 마우스 휠(Mouse Wheel)을 돌려 imgScaleimgTranslate 값이 바뀌었으니, 이 바뀐 값을 기준으로 UpdateRoiVisual을 강제로 한 번 더 호출해 주는 것입니다. 이렇게 하면 이미지가 커지는 만큼 ROI 사각형도 정확히 커지고 이동이 가능하게 됩니다.

이제 빌드 해서 실행해 보세요. 앞선 실행 영상의 문제들이 깔끔하게 해결이 됐음을 보게 될 거에요 ^^;
이미지를 아무리 확대하고 축소해도 ROI 사각형이 껌딱지처럼 이미지에 딱 붙어있는 놀라운 경험을 하시게 될 겁니다.


Line Distance (직선 거리 측정 및 값 표시)

영상 처리를 하다 보면 두 지점 사이의 거리를 측정할 때가 많습니다. 지난 시간에 Draw Line 기능을 만들었으니, 이번엔 선을 다 그렸을 때 “이 선의 길이는 OO px입니다”라고 알려주는 그다지 특별하지 않는 기능을 넣어 보겠습니다.

구현 위치 (ZoomBorder_MouseUp)

도형 그리기가 끝나는 시점은 마우스 버튼을 뗄 때, 즉 MainWindow.xaml.cs 파일에서 ZoomBorder_MouseUp 이벤트입니다. 해당 이벤트에 다음의 코드를 추가하도록 하죠.


특별히 어려운 내용은 없지만, 주석에 사용된 용어들에 대해 한번 짚어 보고 가도록 하죠 .

유클리드 거리 (Euclidean Distance):

  • 중학교 수학 시간에 배운 피타고라스 정리를 사용합니다. Math.Sqrt (루트)와 Math.Pow (제곱)를 이용해 두 점 사이의 최단 거리를 구합니다.
  • 영상처리에서 픽셀 간 거리를 잴 때 가장 기본이 되는 공식입니다.

동적 컨트롤 생성 (Dynamic Control):

  • XAML에 미리 만들어두지 않고, C# 코드에서 new TextBlock()을 통해 실시간으로 글자 상자를 만듭니다.
  • 가독성 확보: 글자가 잘 보이도록 노란색 글씨(Foreground)에 반투명 검은색 배경(Background)을 깔아주었습니다. Color.FromArgb(128,0,0,0)에서 128이 투명도(Alpha)입니다.

오버레이 추가:

  • OverlayCanvas.Children.Add(tb)를 통해 방금 만든 텍스트를 화면에 띄웁니다.

실행

자, 이제 프로그램을 실행하고 직선을 그어보세요. 마우스를 놓는 순간, 선 끝 부분에 노란색 글씨로 거리(px)가 짠! 하고 나타날 겁니다. 확대/축소 버그도 잡고, 거리 측정 기능도 넣으니 이제 제법 그럴싸한 계측 프로그램 같지 않나요?

참고 사항

WPF MouseWheelEventArgs: 마우스 휠 이벤트 처리 및 Delta 값에 대한 공식 문서입니다.
https://learn.microsoft.com/ko-kr/dotnet/api/system.windows.input.mousewheeleventargs
Math.Sqrt Method: 거리 계산에 사용된 제곱근 함수 설명입니다.
https://learn.microsoft.com/ko-kr/dotnet/api/system.math.sqrt
WPF TextBlock Class: 코드 비하인드에서 텍스트 블록을 동적으로 생성하는 방법에 대한 정보입니다.
https://learn.microsoft.com/ko-kr/dotnet/api/system.windows.controls.textblock

댓글 남기기