지금까지 완성된 프로그램을 실행했을때, 게임화면을 보여줘도 아무런 테두리도 나오지 않아서 미니맵 영역이 인식이 되었는지 여부를 직관적으로 확인하기 어렵다. 따라서 미니맵 영역이 인식되지 않을 때 사용자에게 시각적인 피드백을 제공하도록 기능을 추가한다.
미니맵 영역이 인식되지 않을 때 사용자에게 시각적인 피드백을 제공하면 프로그램의 상태를 더 명확하게 파악할 수 있고, 디버깅에도 도움이 될 수 있다.
GameInfo 클래스에 IsMinimapDetected 속성 추가: GameInfo 클래스에 미니맵 인식 여부를 나타내는 IsMinimapDetected 속성을 추가합니다.
// Models/GameInfo.cs
public class GameInfo
{
// ...
public bool IsMinimapDetected { get; set; } // 미니맵 인식 여부
}
ImageProcessingService에서 IsMinimapDetected 값 설정: ImageProcessingService 클래스의 ProcessImage() 메서드에서 미니맵 영역 검출 성공 여부에 따라 IsMinimapDetected 값을 true 또는 false로 설정합니다.
// Services/ImageProcessingService.cs
public GameInfo ProcessImage(Mat image)
{
// ...
// 미니맵 영역 검출
if (/* 미니맵 영역 검출 성공 */)
{
gameInfo.IsMinimapDetected = true;
// ...
}
else
{
gameInfo.IsMinimapDetected = false;
}
// ...
}
MainWindowViewModel에 IsMinimapDetected 속성 추가: MainWindowViewModel 클래스에 IsMinimapDetected 속성을 추가하고, GameInfo 객체의 IsMinimapDetected 값을 바인딩합니다.
// ViewModels/MainWindowViewModel.cs
public partial class MainWindowViewModel : ObservableObject
{
// ...
[ObservableProperty]
private bool isMinimapDetected;
// ...
private async void UpdateFrame(object? sender, EventArgs e)
{
// ...
await Task.Run(() =>
{
// ...
IsMinimapDetected = gameInfo.IsMinimapDetected; // 바인딩
});
// ...
}
}
MainWindow.xaml에 TextBlock 추가: MainWindow.xaml에 TextBlock 컨트롤을 추가하고, Text 속성을 IsMinimapDetected 속성에 바인딩합니다. BooleanToVisibilityConverter를 사용하여 IsMinimapDetected 값에 따라 TextBlock의 표시 여부를 제어합니다.
<Window ...>
<Grid>
<TextBlock Text="미니맵을 찾을 수 없습니다." Foreground="Red"
Visibility="{Binding IsMinimapDetected, Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</Window>
추가 정보
BooleanToVisibilityConverter는 true 값을 Visibility.Visible로, false 값을 Visibility.Collapsed로 변환하는 컨버터입니다. 이 컨버터를 사용하면 IsMinimapDetected 값에 따라 TextBlock의 표시 여부를 쉽게 제어할 수 있습니다.TextBlock의 Foreground 속성을 "Red"로 설정하여 오류 메시지를 빨간색으로 표시합니다.TextBlock의 스타일을 변경하여 메시지의 디자인을 변경할 수 있습니다.BooleanToVisibilityConverter를 새로 생성해야 한다.
BooleanToVisibilityConverter는 bool 값을 Visibility 값으로 변환하는 컨버터입니다. IsMinimapDetected 속성은 bool 타입이므로, XAML에서 Visibility 속성에 바인딩하려면 BooleanToVisibilityConverter와 같은 컨버터가 필요합니다.
BooleanToVisibilityConverter 생성 방법
Converters 폴더에 클래스 추가: 솔루션 탐색기에서 Converters 폴더를 마우스 오른쪽 버튼으로 클릭하고 "추가" > "클래스"를 선택합니다.
클래스 이름 지정: 클래스 이름을 BooleanToVisibilityConverter로 입력하고 "추가" 버튼을 클릭합니다.
코드 작성: 생성된 BooleanToVisibilityConverter.cs 파일에 다음 코드를 작성합니다.
// Converters/BooleanToVisibilityConverter.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace OpenCvSharpProjects.Converters
{
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean && boolean)
{
return Visibility.Visible; // bool 값이 true이면 Visibility.Visible을 반환합니다.
}
else
{
return Visibility.Collapsed; // bool 값이 false이면 Visibility.Collapsed를 반환합니다.
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException(); // ConvertBack 메서드는 구현하지 않습니다.
}
}
}
App.xaml에 리소스 추가: BooleanToVisibilityConverter를 사용하기 위해 App.xaml에 리소스로 추가합니다.
<Application ...>
<Application.Resources>
<local:RectToThicknessConverter x:Key="RectToThicknessConverter" />
<local:RectToVisibilityConverter x:Key="RectToVisibilityConverter" />
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Application.Resources>
</Application>
추가 정보
BooleanToVisibilityConverter 클래스는 IValueConverter 인터페이스를 구현하여 값을 변환하는 컨버터를 정의합니다.Convert 메서드는 bool 값을 Visibility 값으로 변환합니다.ConvertBack 메서드는 Visibility 값을 bool 값으로 변환합니다. (이 예제에서는 사용하지 않습니다.)App.xaml에 리소스로 추가하면 XAML에서 컨버터를 사용할 수 있습니다.이렇게 BooleanToVisibilityConverter를 생성하고 App.xaml에 리소스로 추가하면, MainWindow.xaml에서 TextBlock의 Visibility 속성을 IsMinimapDetected 속성에 바인딩하여 미니맵 인식 여부를 표시할 수 있습니다. 😊
네, 맞습니다. BooleanToVisibilityConverter를 새로 생성해야 합니다.
BooleanToVisibilityConverter는 bool 값을 Visibility 값으로 변환하는 컨버터입니다. IsMinimapDetected 속성은 bool 타입이므로, XAML에서 Visibility 속성에 바인딩하려면 BooleanToVisibilityConverter와 같은 컨버터가 필요합니다.
BooleanToVisibilityConverter 생성 방법
Converters 폴더에 클래스 추가: 솔루션 탐색기에서 Converters 폴더를 마우스 오른쪽 버튼으로 클릭하고 "추가" > "클래스"를 선택합니다.
클래스 이름 지정: 클래스 이름을 BooleanToVisibilityConverter로 입력하고 "추가" 버튼을 클릭합니다.
코드 작성: 생성된 BooleanToVisibilityConverter.cs 파일에 다음 코드를 작성합니다.
// Converters/BooleanToVisibilityConverter.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace OpenCvSharpProjects.Converters
{
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean && boolean)
{
return Visibility.Visible; // bool 값이 true이면 Visibility.Visible을 반환합니다.
}
else
{
return Visibility.Collapsed; // bool 값이 false이면 Visibility.Collapsed를 반환합니다.
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException(); // ConvertBack 메서드는 구현하지 않습니다.
}
}
}
App.xaml에 리소스 추가: BooleanToVisibilityConverter를 사용하기 위해 App.xaml에 리소스로 추가합니다.
<Application ...>
<Application.Resources>
<local:RectToThicknessConverter x:Key="RectToThicknessConverter" />
<local:RectToVisibilityConverter x:Key="RectToVisibilityConverter" />
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Application.Resources>
</Application>
추가 정보
BooleanToVisibilityConverter 클래스는 IValueConverter 인터페이스를 구현하여 값을 변환하는 컨버터를 정의합니다.Convert 메서드는 bool 값을 Visibility 값으로 변환합니다.ConvertBack 메서드는 Visibility 값을 bool 값으로 변환합니다. (이 예제에서는 사용하지 않습니다.)App.xaml에 리소스로 추가하면 XAML에서 컨버터를 사용할 수 있습니다.이렇게 BooleanToVisibilityConverter를 생성하고 App.xaml에 리소스로 추가하면, MainWindow.xaml에서 TextBlock의 Visibility 속성을 IsMinimapDetected 속성에 바인딩하여 미니맵 인식 여부를 표시할 수 있습니다.

오류 발생
프로그램을 실행해서 미니맵이 인식되지 않아도 '미니맵을 찾을 수 없습니다.'라는 문구가 나오지 않음.
오류 원인
1. 바인딩 오류
MainWindow.xaml에서 TextBlock의 Visibility 속성이 MainWindowViewModel의 IsMinimapDetected 속성에 올바르게 바인딩되었는지 확인합니다.TextBlock의 Visibility 속성에 BooleanToVisibilityConverter를 적용했는지 확인합니다.App.xaml에서 BooleanToVisibilityConverter를 리소스로 추가했는지 확인합니다.<Window ...>
<Grid>
<TextBlock Text="미니맵을 찾을 수 없습니다." Foreground="Red"
Visibility="{Binding IsMinimapDetected, Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</Window>
2. IsMinimapDetected 속성 값
MainWindowViewModel의 IsMinimapDetected 속성이 ImageProcessingService에서 미니맵 검출 실패 시 false로 설정되는지 확인합니다.ImageProcessingService의 ProcessImage() 메서드에서 미니맵 영역 검출 로직이 올바르게 동작하는지 확인합니다.IsMinimapDetected 속성 값이 제대로 변경되는지 확인합니다.
3. 컨버터 오류
BooleanToVisibilityConverter 클래스가 제대로 구현되었는지 확인합니다.Convert 메서드에서 bool 값이 false일 때 Visibility.Collapsed를 반환하는지 확인합니다.// Converters/BooleanToVisibilityConverter.cs
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean && boolean)
{
return Visibility.Visible;
}
else
{
return Visibility.Collapsed; // bool 값이 false이면 Visibility.Collapsed를 반환합니다.
}
}
4. UI 스레드 문제
IsMinimapDetected 속성 값이 변경될 때 UI 스레드에서 TextBlock의 Visibility 속성이 업데이트되는지 확인합니다.Dispatcher.Invoke를 사용하여 UI 스레드에서 TextBlock의 Visibility 속성을 업데이트해야 할 수도 있습니다.추가적인 정보
MainWindowViewModel의 UpdateFrame() 메서드에서 IsMinimapDetected 속성 값이 변경되는 시점과 TextBlock의 Visibility 속성이 업데이트되는 시점을 확인합니다.ImageProcessingService의 ProcessImage() 메서드에서 미니맵 영역 검출 로직을 디버깅하여 문제를 파악합니다.TextBlock의 Visibility 속성을 직접 변경하여 컨버터가 제대로 동작하는지 확인합니다.해결

오류 발생
심각도 개수 데이터 컨텍스트 바인딩 경로 대상 대상 형식 설명 파일 줄 프로젝트
오류 2 Rect Width Rectangle.Width Double Rect 형식의 개체에서 Width 속성을 찾을 수 없습니다. C:\Users\M\source\repos\OpenCvSharpProjects\Views\MainWindow.xaml 30 OpenCvSharpProjects
심각도 개수 데이터 컨텍스트 바인딩 경로 대상 대상 형식 설명 파일 줄 프로젝트
오류 2 Rect Height Rectangle.Height Double Rect 형식의 개체에서 Height 속성을 찾을 수 없습니다. C:\Users\M\source\repos\OpenCvSharpProjects\Views\MainWindow.xaml 30 OpenCvSharpProjects
해당 오류는 Rectangle의 Width 속성과 Height 속성에 Rect 형식의 GameWindowRect 속성을 직접 바인딩하려고 해서 발생하는 문제입니다. Rect 형식에는 Width 속성과 Height 속성이 없기 때문에 발생하는 오류입니다.
해결 방법
Rectangle의 Width 속성과 Height 속성에 GameWindowRect 속성의 Width 속성과 Height 속성을 각각 바인딩해야 합니다. 즉, GameWindowRect.Width와 GameWindowRect.Height를 사용해야 합니다.
<Rectangle Stroke="Red" StrokeThickness="2"
Visibility="{Binding GameWindowRect, Converter={StaticResource RectToVisibilityConverter}}"
Width="{Binding GameWindowRect.Width}"
Height="{Binding GameWindowRect.Height}"
Margin="{Binding GameWindowRect, Converter={StaticResource RectToThicknessConverter}}" />
코드 설명
Width="{Binding GameWindowRect.Width}": Rectangle의 Width 속성을 GameWindowRect 속성의 Width 속성에 바인딩합니다.Height="{Binding GameWindowRect.Height}": Rectangle의 Height 속성을 GameWindowRect 속성의 Height 속성에 바인딩합니다.해결 방법 2
GameWindowRect 속성에 사용된 Rect 유형에는 XAML 바인딩에서 직접 액세스할 수 있는 Width 및 Height 속성이 없기 때문에 이러한 오류가 발생합니다. GameWindowRect는 Width 및 Height 속성이 있는 System.Windows.Rect 유형이지만 변환기 없이는 XAML에서 직접 바인딩할 수 없기 때문에 이러한 현상이 발생할 수 있습니다.
코드를 수정한 방법은 다음과 같습니다. Rect 속성을 XAML에서 Rectangle의 Width 및 Height 속성에 바인딩할 수 있는 Double 값으로 변환하기 위해 RectToDoubleConverter 변환기를 추가했습니다. 이렇게 하면 Rectangle의 Width 및 Height 속성이 Rect 개체의 Width 및 Height 속성에 올바르게 바인딩됩니다.
<Window x:Class="OpenCvSharpProjects.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:OpenCvSharpProjects.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image x:Name="CameraImage" Grid.Row="0" Source="{Binding CameraImage}" Stretch="Uniform" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10">
<Button Content="캡처 시작" Command="{Binding StartCaptureCommand}" Margin="5" />
<Button Content="캡처 중지" Command="{Binding StopCaptureCommand}" Margin="5" />
<Button Content="게임 시작" Command="{Binding StartGameCommand}" Margin="5" />
<Button Content="게임 중지" Command="{Binding StopGameCommand}" Margin="5" />
</StackPanel>
<Rectangle Stroke="Red" StrokeThickness="2"
Visibility="{Binding GameWindowRect, Converter={StaticResource RectToVisibilityConverter}}"
Width="{Binding GameWindowRect.Width, Converter={StaticResource RectToDoubleConverter}}"
Height="{Binding GameWindowRect.Height, Converter={StaticResource RectToDoubleConverter}}"
Margin="{Binding GameWindowRect, Converter={StaticResource RectToThicknessConverter}}" />
<TextBlock Text="미니맵을 찾을 수 없습니다." Foreground="Red"
Visibility="{Binding IsMinimapDetected, Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</Window>
RectToDoubleConverter를 만들어 적용.
Rectangle의 Width와 Height 속성은 double 타입의 값을 기대하는데, GameWindowRect 속성은 Rect 타입이기 때문에 직접 바인딩할 수 없습니다. 따라서 Rect 객체의 Width와 Height 값을 double 타입으로 변환해주는 RectToDoubleConverter를 사용하는 것이 좋습니다.
RectToDoubleConverter 작성
// Converters/RectToDoubleConverter.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace OpenCvSharpProjects.Converters
{
public class RectToDoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Rect rect)
{
// parameter에 따라 Width 또는 Height 값을 반환합니다.
if (parameter is string str && str == "Height")
{
return rect.Height;
}
else
{
return rect.Width;
}
}
return 0; // 기본값으로 0을 반환합니다.
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
App.xaml에 컨버터 추가
RectToDoubleConverter를 사용하기 위해 App.xaml에 리소스로 추가합니다.
<Application ...>
<Application.Resources>
<local:RectToThicknessConverter x:Key="RectToThicknessConverter" />
<local:RectToVisibilityConverter x:Key="RectToVisibilityConverter" />
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<local:RectToDoubleConverter x:Key="RectToDoubleConverter" />
</Application.Resources>
</Application>
MainWindow.xaml에서 컨버터 사용
MainWindow.xaml에서 Rectangle의 Width 속성과 Height 속성에 RectToDoubleConverter를 사용하여 GameWindowRect 속성의 Width 값과 Height 값을 바인딩합니다.
<Rectangle Stroke="Red" StrokeThickness="2"
Visibility="{Binding GameWindowRect, Converter={StaticResource RectToVisibilityConverter}}"
Width="{Binding GameWindowRect, Converter={StaticResource RectToDoubleConverter}}"
Height="{Binding GameWindowRect, Converter={StaticResource RectToDoubleConverter}, ConverterParameter=Height}"
Margin="{Binding GameWindowRect, Converter={StaticResource RectToThicknessConverter}}" />
ConverterParameter=Height: Height 속성에 바인딩할 때는 ConverterParameter를 "Height"로 설정하여 RectToDoubleConverter가 Rect 객체의 Height 값을 반환하도록 합니다.이렇게 RectToDoubleConverter를 사용하면 Rectangle의 Width 속성과 Height 속성에 GameWindowRect 속성의 Width 값과 Height 값을 제대로 바인딩할 수 있습니다.
오류 발생3

Application.Current.Dispatcher.Invoke(() =>
{
IsMinimapDetected = gameInfo.IsMinimapDetected;// GameInfo 객체의 IsMinimapDetected 값을 바인딩한다.
});
위 코드에서 아래와 같은 문제가 발생
System.NullReferenceException: 'Object reference not set to an instance of an object.'
System.Windows.Application.Current.get이(가) null을(를) 반환했습니다.
원인
This error happens because the Application.Current object is null, leading to a System.NullReferenceException when trying to access Dispatcher.Invoke.
This might be happening because the Application.Current object is not initialized or is being accessed from a non-UI thread. In WPF applications, Application.Current should always be available, but if the code is running in a context where the application is not fully initialized or is being accessed from a background thread, it can be null.
To fix this issue, ensure that the code accessing Application.Current.Dispatcher is running on the UI thread. You can check if Application.Current is null before calling Dispatcher.Invoke:
이 오류는 Application.Current 개체가 null이므로 Dispatcher.Invoke에 액세스하려고 할 때 System.NullReferenceException이 발생하기 때문에 발생합니다.
이는 Application.Current 개체가 초기화되지 않았거나 UI가 아닌 스레드에서 액세스되고 있기 때문에 발생할 수 있습니다. WPF 애플리케이션에서 Application.Current는 항상 사용할 수 있어야 하지만 애플리케이션이 완전히 초기화되지 않았거나 백그라운드 스레드에서 액세스되는 컨텍스트에서 코드가 실행 중인 경우 null이 될 수 있습니다.
이 문제를 해결하려면 Application.Current.Dispatcher에 액세스하는 코드가 UI 스레드에서 실행되고 있는지 확인하세요. Dispatcher.Invoke를 호출하기 전에 Application.Current가 null인지 확인할 수 있습니다.
Additionally, ensure that the WPF application is properly initialized and that no code is trying to access Application.Current before the application startup is complete.
또한 WPF 애플리케이션이 제대로 초기화되었는지, 애플리케이션 시작이 완료되기 전에 Application.Current에 액세스하려는 코드가 없는지 확인하세요.
발생 원인
NullReferenceException은 프로그램이 null 참조를 역참조하려고 할 때 발생하는 예외입니다. 즉, 어떤 변수가 객체를 가리키고 있지 않은데 해당 변수를 사용하려고 할 때 발생합니다.
이 경우 Application.Current.Dispatcher를 호출할 때 Application.Current가 null을 반환하여 예외가 발생했습니다. 이는 WPF 응용 프로그램이 아직 완전히 초기화되지 않은 상태에서 Application.Current에 접근하려고 할 때 발생할 수 있습니다.
해결 방법
Application.Current가 null이 아닌지 확인: Application.Current가 null인지 확인하고, null이면 초기화될 때까지 기다립니다. Application.Current.Dispatcher를 호출하기 전에 다음과 같이 조건문을 추가할 수 있습니다.if (Application.Current != null)
{
Application.Current.Dispatcher.Invoke(() =>
{
IsMinimapDetected = gameInfo.IsMinimapDetected;
});
}
Dispatcher를 직접 가져오기: Application.Current.Dispatcher 대신 Dispatcher를 직접 가져와서 사용합니다. UpdateFrame 메서드는 CompositionTarget.Rendering 이벤트 핸들러이므로, 이벤트가 발생한 요소의 Dispatcher를 사용할 수 있습니다.if (sender is System.Windows.Media.CompositionTarget target)
{
target.Dispatcher.Invoke(() =>
{
IsMinimapDetected = gameInfo.IsMinimapDetected;
});
}
Initialized 이벤트 활용: Application 클래스의 Initialized 이벤트를 사용하여 응용 프로그램이 초기화된 후에 Dispatcher를 호출합니다.// MainWindowViewModel 생성자에서
Application.Current.Initialized += (s, e) =>
{
Application.Current.Dispatcher.Invoke(() =>
{
IsMinimapDetected = gameInfo.IsMinimapDetected;
});
};
IsMinimapDetected 속성 값을 변경하는 코드를 UI 스레드에서 직접 실행합니다. UpdateFrame 메서드는 이미 UI 스레드에서 실행되므로, Dispatcher.Invoke를 사용하지 않고 직접 속성 값을 변경할 수 있습니다.IsMinimapDetected = gameInfo.IsMinimapDetected; // Dispatcher.Invoke 없이 직접 설정
어떤 방법을 선택해야 할까요?
Application.Current가 null인 경우 처리가 누락될 수 있습니다.Dispatcher를 직접 가져와서 사용하므로 안전하고 효율적입니다.Dispatcher를 호출하므로 안전하지만, 초기화 전에는 IsMinimapDetected 값이 업데이트되지 않습니다.UpdateFrame 메서드가 UI 스레드에서 실행된다는 것을 전제로 합니다.현재 상황에서는 2번 또는 4번 방법을 사용하는 것을 추천합니다.
Dispatcher를 명시적으로 가져와서 사용하므로 안전하고, Dispatcher.Invoke를 사용하지 않으므로 성능 측면에서 유리합니다.추가 정보
Application.Current 속성은 현재 실행 중인 WPF 응용 프로그램을 나타냅니다.Dispatcher 클래스는 UI 스레드에서 작업을 실행하고 동기화하는 데 사용됩니다.Initialized 이벤트는 WPF 응용 프로그램이 초기화된 후 발생합니다.오류 발생
"미니맵을 찾을 수 없습니다." 메시지가 안뜸.
발생 원인
"미니맵을 찾을 수 없습니다."라는 메시지가 표시되지 않는 문제는 다음과 같은 원인으로 발생할 수 있습니다.
IsMinimapDetected 속성이 항상 true: ImageProcessingService의 ProcessImage() 메서드에서 미니맵 영역이 검출되지 않아도 IsMinimapDetected 속성이 항상 true로 설정될 수 있습니다. 이 경우 "미니맵을 찾을 수 없습니다."라는 메시지는 표시되지 않습니다.
TextBlock의 Visibility 속성이 항상 Visible: BooleanToVisibilityConverter가 올바르게 작동하지 않아 IsMinimapDetected 속성이 false일 때에도 TextBlock의 Visibility 속성이 Visible로 설정될 수 있습니다.
해결 방법
IsMinimapDetected 속성 검사: ImageProcessingService의 ProcessImage() 메서드에서 미니맵 영역 검출이 성공했을 때만 IsMinimapDetected 속성을 true로 설정하고, 실패한 경우에는 false로 설정합니다.
BooleanToVisibilityConverter 확인: BooleanToVisibilityConverter 클래스가 제대로 구현되었는지 확인합니다. 특히, Convert 메서드에서 bool 값이 false일 때 Visibility.Collapsed를 반환하는지 확인합니다.
// Converters/BooleanToVisibilityConverter.cs
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean && boolean)
{
return Visibility.Visible; // bool 값이 true이면 Visibility.Visible을 반환합니다.
}
else
{
return Visibility.Collapsed; // bool 값이 false이면 Visibility.Collapsed를 반환합니다.
}
}
IsMinimapDetected 속성 값과 TextBlock의 Visibility 속성 값이 변경되는 과정을 확인합니다. 이를 통해 문제가 발생하는 위치를 파악할 수 있습니다.추가적인 정보
BooleanToVisibilityConverter 클래스의 Convert 메서드에서 false 값을 Visibility.Collapsed로 반환하지 않으면, IsMinimapDetected 속성이 false일 때에도 TextBlock이 표시됩니다.ImageProcessingService의 ProcessImage() 메서드에서 미니맵 영역 검출 로직이 올바르게 동작하지 않으면 IsMinimapDetected 속성이 항상 false로 설정됩니다.시도
BooleanToVisibilityConverter 클래스가 제대로 구현되었는지 확인했다. 특히, Convert 메서드에서 bool 값이 false일 때 Visibility.Collapsed를 반환하는지 확인했다. 문제가 없었다.
또한 아래 코드에서 중단점 설정해서 봤는데, IsMinimapDetected 변수 값이 false로 뜬다. 하지만 여전히 "미니맵을 찾을 수 없습니다."라는 메시지는 표시되지 않는다.
// 미니맵 영역 검출
if (gameInfo.GameWindowRect.Width > 0 && gameInfo.GameWindowRect.Height > 0) // 미니맵 영역이 검출되었다면
{
gameInfo.IsMinimapDetected = true;
}
else
{
gameInfo.IsMinimapDetected = false;
}
해결
BooleanToVisibilityConverter에서 false 값을 Visibility.Collapsed로 변환하면, IsMinimapDetected 속성이 false일 때 TextBlock이 숨겨져서 메시지가 표시되지 않습니다.
TextBlock을 표시하려면 false 값을 Visibility.Visible로, true 값을 Visibility.Collapsed로 변환해야 합니다.
BooleanToVisibilityConverter.cs 코드 수정
// Converters/BooleanToVisibilityConverter.cs
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean && boolean)
{
return Visibility.Collapsed; // bool 값이 true이면 Visibility.Collapsed를 반환합니다.
}
else
{
return Visibility.Visible; // bool 값이 false이면 Visibility.Visible을 반환합니다.
}
}
이렇게 수정하면 IsMinimapDetected 속성이 false일 때, 즉 미니맵이 인식되지 않았을 때 "미니맵을 찾을 수 없습니다."라는 메시지가 표시된다.

노트북 내장 웹캠은 화질이 너무 떨어져서 핸드폰 카메라를 웹캠으로 사용하기로 했다.
오류 발생
await Task.Run(() => capture.Read(frame)); // 웹캠에서 프레임을 읽어옵니다.
위 코드에서 아래와 같은 오류가 발생한다. 카메라 화면에 사물이 비치는 순간 예외발생 디버그 메시지가 엄청나게 많이 뜬다.
처리되지 않은 'System.ExecutionEngineException' 형식의 예외가 OpenCvSharp.dll에서 발생했습니다.
System.ExecutionEngineException은 .NET 런타임에서 심각한 오류가 발생했을 때 발생하는 예외입니다. 이 예외는 일반적으로 메모리 손상, 스택 오버플로, 또는 런타임 자체의 버그와 같은 심각한 문제를 나타냅니다.
이 경우 capture.Read(frame) 메서드를 호출할 때 예외가 발생하는 것으로 보아 OpenCvSharp 라이브러리 또는 웹캠 드라이버와 관련된 문제일 가능성이 높습니다.
문제 해결을 위한 단계
OpenCvSharp 버전 확인 및 업데이트: OpenCvSharp 라이브러리의 버전을 확인하고 최신 버전으로 업데이트합니다. 최신 버전에서는 버그가 수정되었거나 성능이 개선되었을 수 있습니다. -> 업데이트 완료
웹캠 드라이버 업데이트: 웹캠 드라이버를 최신 버전으로 업데이트합니다. 오래된 드라이버는 호환성 문제를 일으키거나 오류를 발생시킬 수 있습니다.
다른 웹캠 테스트: 가능하다면 다른 웹캠을 사용하여 테스트해 봅니다. 이를 통해 현재 웹캠에 문제가 있는지 확인할 수 있습니다. -> 현재 웹캠에 문제가 있는 것으로 확인됨.
코드 검토: capture.Read(frame) 메서드를 호출하기 전에 capture 객체가 올바르게 초기화되었는지 확인합니다. 또한, frame 객체가 유효한 Mat 객체인지 확인합니다.
예외 처리: try-catch 블록을 사용하여 ExecutionEngineException 예외를 처리하고, 예외 발생 시 로그를 기록하거나 사용자에게 오류 메시지를 표시합니다.
메모리 부족 확인: ExecutionEngineException 예외는 메모리 부족으로 인해 발생할 수도 있습니다. 프로그램 실행 중 메모리 사용량을 모니터링하고, 메모리 부족이 발생하는지 확인합니다. -> 메모리 74%로 나옴. 메모리 사용량이 74%라면, 일반적인 상황에서는 System.ExecutionEngineException 예외의 직접적인 원인이 되지는 않습니다.
추가 정보
System.ExecutionEngineException 예외는 일반적으로 심각한 문제를 나타내므로, 문제를 해결하기 위해서는 근본 원인을 파악하는 것이 중요합니다.