WPF OpenCV 프로젝트 #3: OpenCVService 구현 및 이미지 로드

지난 포스팅에서 MVVM 구조를 잡았으니, 이제 WPF OpenCV 프로젝트의 심장이라고 할 수 있는 OpenCVService.cs를 작성할 차례입니다. 이 클래스는 OpenCV 라이브러리를 사용해 이미지를 불러오고, 영상처리를 수행하며, 결과를 UI에 보여줄 수 있는 형태로 변환하는 역할을 담당합니다 .

MVVM 패턴에서는 이 클래스를 Model 데이터를 다루는 서비스로 이해하시면 됩니다 .

영상처리를 위한 기능 설계

코드를 작성하기 전에 어떤 변수와 함수가 필요할지 먼저 정의해 보겠습니다 .

  • 원본 이미지 (_srcImage): 파일에서 불러온 Mat 형식의 원본 데이터입니다 .
  • 결과 이미지 (_destImage): 영상처리가 완료된 Mat 데이터입니다 .
  • UI 표시용 버퍼 (ImageSource): OpenCV의 Mat 데이터는 WPF UI(Image 컨트롤)에 바로 띄울 수 없습니다. 따라서 BitmapSource 형태로 변환된 별도의 버퍼가 필요합니다 .

필요한 핵심 기능(함수)은 다음과 같습니다.

  1. LoadImageAsync: 이미지를 비동기로 불러오는 함수 .
  2. ProcessImageAsync: 알고리즘을 적용하여 영상처리를 하는 함수 .
  3. Cleanup: 사용된 메모리(Mat)를 정리하는 함수 .

OpenCVService.cs 전체 코드 작성

설계한 내용을 바탕으로 코드를 구현해 보겠습니다. OpenCVService.cs 파일에 아래 코드를 작성합니다.

코드 핵심 포인트 분석

Taskasync/await를 사용했나요?

실무 프로그램을 개발할 때 가장 중요한 것 중 하나가 UI 응답성입니다. 용량이 큰 고화질 이미지를 불러오거나 복잡한 영상처리를 할 때, 메인 스레드(UI 스레드)에서 처리하면 작업이 끝날 때까지 화면이 멈춰버립니다(일명 ‘렉’ 걸림) .

이를 방지하기 위해 “오래 걸리는 작업은 뒤에서 처리하고 결과만 알려줘!”라고 맡기기 위해 Task를 사용했습니다 .

왜 흑백 영상 처리에도 컬러로 저장하나요?

_srcImage를 무조건 3채널 컬러로 불러오는 이유는 확장성 때문입니다. 나중에 영상처리 결과 위에 빨간색이나 파란색으로 검출 영역(ROI)을 표시해야 할 때, 원본이 그레이스케일(1채널)이면 색상을 입힐 수 없기 때문입니다 .

수동 메모리 관리 (Dispose)

C#은 가비지 컬렉터(GC)가 메모리를 관리해 주지만, **OpenCV의 Mat 데이터는 Unmanaged Memory(관리되지 않는 메모리)**를 사용합니다 . 따라서 사용이 끝난 이미지는 Dispose()를 호출하여 직접 메모리를 반환해주어야 메모리 누수(Memory Leak)를 막을 수 있습니다 .

🚀 다음 단계

이제 영상처리를 위한 로직인 ModelService가 완성되었습니다. 다음 포스팅에서는 이 기능들을 화면과 연결해 줄 ViewModel을 구현하여, 실제 버튼을 눌렀을 때 이미지가 보이도록 만들어 보겠습니다 .

댓글 남기기