[C#, WPF] OpenCvSharp을 활용하여 얼굴 검출 기능 구현하기

2023. 11. 10. 22:39C#,WPF

OpenCvSharp을 활용하여 얼굴 검출 기능을 가진 WPF 애플리케이션을 작성하겠습니다. OpenCvSharp은 OpenCV를 .NET 환경에서 사용할 수 있게 해주는 라이브러리로서 OpenCV와 관련된 라이브러리 중에서 가장 많이 사용됩니다. 2023년 11월 9일 기준으로 OpenCVSharp4(4.8.0.20230708)가 NuGet 패키지 매니저에 게시되어 있습니다. 
 
본 프로젝트는 Visual Studio 2022, .NET7 환경에서 WPF 애플리케이션을 생성하는 것으로 시작합니다. 
 
chaewonki/FaceDetectionWithOpenCvSharp (github.com)

GitHub - chaewonki/FaceDetectionWithOpenCvSharp

Contribute to chaewonki/FaceDetectionWithOpenCvSharp development by creating an account on GitHub.

github.com

 
먼저 적절한 Nuget 패키지 설치부터 진행하겠습니다.
 

Nuget 패키지 매니저에서 OpenCvSharp을 검색했을 때 모습

 
기본적으로 OpenCvSharp4를 설치하고 윈도우 환경, WPF 애플리케이션임을 고려하여 OpenCvSharp4.runtime.win과 OpenCvSharp4.WpfExtensions 추가로 설치합니다. 
 
이제 프로젝트를 위해 기본 UI를 작성하겠습니다. 다음은 MainWindow.xaml 파일의 일부와 스크린샷입니다.
 

    <StackPanel>
        <Border BorderBrush="Black"
                Margin="10"
                BorderThickness="1"
                Width="500" Height="500">
            <Image x:Name="imgMain"/>
        </Border>
        <Button x:Name="btnLoad" 
                Width="50"
                Content="Load"
                Click="btnLoad_Click"/>
    </StackPanel>

 

애플리케이션의 기본 UI 레이아웃

 
Border 컨트롤로 감싼 Image 컨트롤에 얼굴 검출을 적용할 이미지를 로드하겠습니다. 
 
OpenCV에서는 특정 대상을 검출하기 위해 XML 파일로 작성된 Haar Cascade Classifier(하르 분류기)를 사용합니다. OpenCV 4.7.0 기준, 이 라이브러리에서 제공하는 얼굴 검출을 위한 Haar Cascade Classifier XML 파일은 다음과 같습니다. 
 

OpenCV가 제공하는 Haar Cascade Claasifier XML 파일들

 
이 파일들을 복사하여 프로젝트 소스코드가 있는 티렉터리에 붙여넣기 합니다. 다음으로 비주얼 스튜디오에서 각 파일의 속성 창을 열고 '출력 디렉터리로 복사' 항목을 '새 버전이면 복사'로 바꿔 줍니다. 이렇게 설정하면 빌드 시 생성된 실행파일과 같은 디렉터리에 XML 파일들이 복사됩니다. 이로써 WPF 애플리케이션에서 OpenCV를 활용하여 얼굴 검출 기능을 구현할 기본 세팅을 마쳤습니다.
 
이제 기본 UI에서 Load 버튼을 눌렀을 때 대화 상자를 띄워 사용자가 이미지 파일을 선택할 수 있게 하고 선택된 이미지를 Image 컨트롤에 불러오는 기능을 구현하겠습니다. 먼저 MainWindow.xaml.cs 코드 비하인드 파일의 일부를 살펴보겠습니다.
 

MainWindow.xaml.cs 코드 비하인드 파일 시작 부분

 
대화상자를 사용하기 위해 Microsoft.Win32 네임스페이스를 추가하였고 이어 WPF 애플리케이션 환경에서 OpenCV를 활용하기 위해 OpenCvSharp 네임스페이스와 OpenCvSharp.WpfExtensions 네임스페이스를 추가하였습니다. OpenCvSharp 네임스페이스와 System.Windows 네임스페이스 모두 Window 클래스가 존재합니다. 따라서 어느 네임스페이스의 Window 클래스를 사용할지 명시적으로 밝혀줘야 합니다. 그렇지 않으면 컴파일 에러가 발생합니다. 
 

        CascadeClassifier faceCascade = new CascadeClassifier("haarcascade_frontalface_alt2.xml");

        private void btnLoad_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Image files | *.jpg;*jpeg;*.png;*.bmp";
            
            if(openFileDialog.ShowDialog() == true)
            {
                using Mat image = new Mat(openFileDialog.FileName, ImreadModes.Color);
                OpenCvSharp.Rect[] faces = faceCascade.DetectMultiScale(image);

                foreach (OpenCvSharp.Rect face in faces)
                {
                    image.Rectangle(face, new Scalar(0, 0, 255), 3);
                }

                imgMain.Source = image.ToBitmapSource();

            }
        }

 
적절한 XML 파일을 이용하기 위해 CascadeClassifier 클래스를 사용하였습니다. 제가 가지고 있는 이미지들을 프로젝트에 적용해 봤을 때 가장 좋은 결과가 나온 haarcascade_frontalface._alt2.xml 파일을 사용했습니다. 그리고 버튼을 눌렀을 때 대화상자를 띄우고 로드할 이미지를 사용자가 선택할 수 있도록 구현하였습니다. 
Mat 클래스는 OpenCvSharp에서 제공하는 중요한 클래스로 다차원 배열정보를 저장하고 조작하는 기능을 가지고 있습니다. 대화상자에서 선택된 이미지 파일을 컬러모드로 열어 이미지 정보를 image 변수에 저장했습니다. 이어서 하르 분류기를 통해 얼굴에 해당하는 부분을 검출하고 불러온 이미지에 표시했습니다. 이제 이 이미지를 Image 컨트롤에 저장하기 위해 비트맵으로 변환한 뒤 대입했습니다. 
 
Unsplash에서 샘플이미지 3장을 다운로드 받아 프로젝트를 실행해 보겠습니다.
 

이미지1

 

이미지2

 
 

이미지3

 
얼굴이 아닌 곳을 얼굴로 인식(이미지2)하기도 하고 얼굴을 제대로 인식하지 못하는(이미지3) 경우도 발생했습니다. 이와 같은 문제는 사용할 이미지를 특정 범위로 제한하거나 더 나은 하르 분류기를 사용하면 해결할 수 있습니다. 
 
OpenCV 라이브러리를 C#, WPF 환경에서 사용할 수 있는 OpenCvSharp을 사용하여 얼굴 검출 기능을 구현했습니다. 이 프로젝트의 핵심은 OpenCV를 활용할 수 있는 환경을 C#, WPF 환경으로 이식하는 과정에 대한 이해를 바탕으로 하르 분류기를 이용하여 특정 기능(얼굴 검출)을 구현하는 데 있습니다.
만약 얼굴 검출 기능을 위와 다른 방식으로 구현하고 싶다면 도형의 내부를 채우는 방식으로 검출된 이미지를 가리거나 사각형 대신 원형 모양으로 얼굴을 검출할 수 있습니다. 아래는 테스트를 위해 사용한 이미지를 받은 Unslpash의 홈페이지 주소입니다.
 
아름다운 무료 이미지 및 사진 | Unsplash

아름다운 무료 이미지 및 사진 | Unsplash

어떤 프로젝트를 위해서든 다운로드 및 사용할 수 있는 아름다운 무료 이미지 및 사진입니다. 어떤 로열티 프리 또는 스톡 사진보다 좋습니다.

unsplash.com