WPF OpenCV 프로젝트 #17: Histogram (히스토그램) 분석 및 그래프 그리기 (Cv2.CalcHist)


영상에서 Histogram (히스토그램) 분석 및 Histogram 데이터를 이용하여 그래프를 그려 분석 할 수 있도록 WPF OpenCV 프로젝트에 구현하겠습니다.
지난 포스팅(#15, #16)에서 OtsuAdaptive Threshold를 다루면서 “히스토그램(Histogram)”이라는 단어를 스치듯 언급했었습니다. 기억나시나요?

“히스토그램에서 두 개의 산봉우리(Bimodal)가 생길 때, Otsu 알고리즘은 그 사이 골짜기를 찾아냅니다.” (Post #15 참조)

오늘은 바로 그 히스토그램을 직접 구현해 볼 차례입니다. 단순히 “어떤 색이 많다”를 넘어서, 영상의 명암 분포나 조명의 균일성을 파악하는 아주 중요한 기초 분석 도구입니다.

이번 편은 구현할 내용이 조금 있습니다. 흠… 하지만 우려할 만큼 엄청난 양이 아니니까 걱정은 저 너머에 두고, 시작해 보도록 하겠습니다.

Histogram

아주 간단히 말해서 “이미지 안에 픽셀 값이 몇 개씩 있는지 세어서 그래프로 그린 것”입니다.

  • X축: 픽셀의 밝기 값 (0 ~ 255)
  • Y축: 해당 밝기를 가진 픽셀의 개수 (Count)

이것을 분석하면 사진이 전체적으로 어두운지, 밝은지, 명암 대비(Contrast)가 뚜렷한지 한눈에 알 수 있습니다. OpenCV에서는 Cv2.CalcHist()라는 함수를 제공합니다.

구현 단계 정리

이번 기능은 단순히 알고리즘만 돌리는 게 아니라, 결과를 그래프로 보여줄 팝업 창(Window)까지 만들어야 해서 수정할 파일이 좀 많습니다.

  1. AlgorithmParameters.cs: 히스토그램 설정값(채널, 마스크 등) 정의
  2. HistogramWindow.xaml: 그래프를 보여줄 팝업 창 UI 생성
  3. HistogramWindow.xaml.cs: 데이터를 받아 직접 그래프를 그리는 로직 구현
  4. OpenCVService.cs: Cv2.CalcHist로 데이터 분석 및 저장
  5. MainViewModel & View: 파라미터 연결 및 팝업 띄우기

자, 심호흡 한번 하고 하나씩 진행해 보도록 하죠.

Step 1: 파라미터 클래스 정의 (Model)

먼저 AlgorithmParameters.cs에 히스토그램 분석에 필요한 설정 값들을 정의합니다.

  • Channel: 분석할 색상 채널 (Blue, Green, Red, Gray)
  • HistSize (Bins): 몇 개의 구간으로 나눌 것인가? (보통 256개)
  • Range: 분석할 밝기 범위 (0~256)
  • MaskMode: 특정 영역(원, 절반 등)만 분석할지 여부

Step 2 & 3: 그래프 팝업 창 만들기 (View & Logic)

분석된 데이터를 메인 화면에 띄우기엔 공간이 부족하니, 별도의 팝업 창(HistogramWindow)을 띄워서 보여주겠습니다.

HistogramWindow.xaml : 윈도우 생성

프로젝트 우클릭 > 추가 > 새 항목 > 창(WPF) > 이름: HistogramWindow.xaml 의 순서로 프로젝트 솔루션에 파일을 추가합니다. 아래의 그림을 참고해 주세요.

WPF의 강력한 점은 차트 라이브러리 없이도 CanvasPolyline만 있으면 멋진 그래프를 그릴 수 있다는 점입니다. 사실 그래프나 차트를 그리기를 제공하는 패키지들이 있긴 한데, 여기서는 기본 WPF 만으로 작성하도록 할게요. 아래 코드를 그래로 복사하여 사용하면 됩니다.

HistogramWindow.xaml.cs : 그래프 그리기 로직

여기가 이번 포스팅의 하이라이트입니다. 데이터를 받아서 Polyline으로 그래프를 그리는 DrawGraph 함수입니다. (코드가 조금 길지만, 주석을 보면 단순히 좌표를 찍어서 선을 잇는 원리입니다.)
새로 생성한 파일이라 아래에 전체 코드를 추가하였습니다. 중간 중간에 주석도 넣어 두었습니다. 어려운 부분은 딱히 보이지 않으니까 전체를 복사하여 붙여 넣어 주세요.

Key Point: (현재 값 / 최대 값) * 높이 공식을 사용해 어떤 크기의 데이터가 들어와도 화면 꽉 차게 정규화(Scaling)해서 그립니다.

Step 4: OpenCVService

이제 OpenCVService.cs에서 실제로 Cv2.CalcHist() 함수를 통해 히스토그램 처리를 구현합니다. 아래와 같이 OpenCVService.cs 파일 중에서 ProcessImageAsync() 함수 내에 switch 구문에 추가해 주세요.

Step 5: ViewModel 및 View 연결

마지막으로 Step1 ~ Step4 까지 진행하였던 내용들을 UI(View)와 연결하도록 하겠습니다.

  1. MainViewModel.cs:
    • MainViewModel 생성자 함수에 Histogram 항목을 추가합니다. 그리고 사용자가 Histogram을 선택하였을 때 CreateParametersForAlgorithm() 함수에서 HistogramParams 객체를 생성하도록 코드를 추가합니다.
    • ApplyAlgorithm 함수 마지막에 “알고리즘이 Histogram이면 팝업창을 띄워라“라는 로직을 추가합니다.
    • HistogramWindow 객체를 생성할 때 Service에 저장해둔 LastHistogramData를 넘겨줍니다.
  2. MainWindow.xaml:
    • DataTemplate을 추가하여 히스토그램 파라미터(슬라이더, 콤보박스)가 화면에 보이도록 합니다. <Window.Resource> </Window.Resource> 사이에 Histogram DataTemplate 를 추가합니다.

실행

흠… 조금 길었습니다. 이제 빌드 후 실행해 볼까요? 이미지를 불러오고 Histogram 알고리즘을 선택한 뒤 [적용 (Apply)] 버튼을 눌러보세요. 아래의 이미지는 히스토그램 분석을 위해 로딩한 원본 이미지와 Default 파라미터로 적용하였을 때 Histogram 그래프를 나타내었습니다.


아래 이미지부터는 동일한 이미지에 대한 Histogram Analysis 윈도우만 갭쳐해서 올립니다.참고해 주세요. (일부 파라미터 조절 이미지만 올리니까, 각자 조정하면서 그래프를 분석해보세요)

이번 포스팅은 그래프 그리기 때문에 코드가 좀 길어졌습니다. 하지만 외부 차트 라이브러리 없이 순수 WPF 기능만으로 이렇게 깔끔한 분석 도구를 만들 수 있다는 점이 매력적이지 않나요?

다음 시간에는 이렇게 분석한 데이터를 바탕으로 이미지를 선명하게 만드는 정규화(Normalization)에 대해 다뤄보겠습니다. 다음 편은 아주 간단하니 걱정 마세요! ^^

참고 자료

OpenCV API: Cv2.CalcHist: OpenCV 공식 문서 (CalcHist) – 함수 파라미터 상세 설명.
WPF Graphics: Polyline Class: MS Docs (Polyline) – 점들을 연결하여 선을 그리는 WPF 도형 객체

댓글 남기기