소스 : CsharpFramework/CameraCapture at main · tjdskaqks/CsharpFramework · GitHub
1. .NET Framework 4.8
2. Visual Studio 16.9.4
- 카메라 디바이스 리스트 가져오기 (LINQ)
using DirectShowLib;
// 카메라 리스트 가져오기
private void GetCameraList() => cameraDevices.AddRange(from DsDevice dsDevice in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
where !dsDevice.DevicePath.Contains("device:sw")
select dsDevice);
- DispatcherTimer 사용해 UI 변경, MainWindow 전체 코드
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using DirectShowLib;
using OpenCvSharp;
using OpenCvSharp.WpfExtensions;
namespace CameraCaptureWPF
{
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
///
/// </summary>
public partial class MainWindow : System.Windows.Window
{
private VideoCapture _videoCapture = null; // 캠 캡쳐
private DispatcherTimer _dispatcherTimer = null; // 디스패쳐 타이머
public List<DsDevice> cameraDevices = null; // 캠 리스트
private WindowOption windowOption = null; // 옵션 서브 폼
private int selectDeviceIndex = -1; // 옵션 폼에서 설정시 변경에 필요한 변수
public int SelectDeviceIndex { get => selectDeviceIndex; set => SetMainUI(value); } // 옵션 폼에서 카메라 인덱스가 변경하면 SetUI에서 초기화
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
this.Closed += MainWindow_Closed;
btn_OpenOption.Click += Btn_OpenOption_Click;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.Topmost = true; // 기본 탑
btn_OpenOption.Cursor = Cursors.Hand;
cameraDevices = new List<DsDevice>();
GetCameraList();
if (cameraDevices.Count > 0)
{
InitSetting();
SetMainUI();
}
else
{
MessageBox.Show("등록된 카메라가 없습니다.", "주의", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
private void MainWindow_Closed(object sender, EventArgs e)
{
TimerStop(ref _dispatcherTimer);
if (_videoCapture != null)
{
if (_videoCapture.IsOpened())
_videoCapture.Release();
_videoCapture.Dispose();
}
if (windowOption != null)
windowOption.Close();
}
private void Btn_OpenOption_Click(object sender, RoutedEventArgs e)
{
if (windowOption == null) // null 일때만 옵션 창 오픈
{
windowOption = new WindowOption(this);
windowOption.Left = this.Left + this.Width;
windowOption.Top = this.Top;
windowOption.Closed += (s, args) => windowOption = null; // 닫히면 null로 초기화
windowOption.Show();
}
else
{
windowOption.Left = this.Left + this.Width;
windowOption.Top = this.Top;
windowOption.Activate();
}
}
// 타이머 초기화
public void InitSetting()
{
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Interval = TimeSpan.FromMilliseconds(50);
_dispatcherTimer.Tick += _dispatcherTimer_Tick;
}
// 타이머 동작
private void _dispatcherTimer_Tick(object sender, EventArgs e)
{
if (_videoCapture != null)
{
using (Mat mat = new Mat()) // 캠 캡쳐 후 이미지 소스 지정
{
if (_videoCapture.Read(mat))
{
var wb = WriteableBitmapConverter.ToWriteableBitmap(mat, 1024, 1024, PixelFormats.Bgr24, null);
img_Camera.Source = wb;
}
}
}
}
// 카메라 리스트 가져오기 LINQ
private void GetCameraList() => cameraDevices.AddRange(from DsDevice dsDevice in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
where !dsDevice.DevicePath.Contains("device:sw")
select dsDevice);
// MainUI 설정
private void SetMainUI(int index = 0)
{
TimerStop(ref _dispatcherTimer);
if (cameraDevices.Count > 0 && index >= 0)
{
selectDeviceIndex = index;
if (_videoCapture != null && _videoCapture.IsOpened())
_videoCapture.Release();
_videoCapture = VideoCapture.FromCamera(index, VideoCaptureAPIs.ANY);
if (_videoCapture.Open(index, VideoCaptureAPIs.ANY))
this.Title = $"Camera - {cameraDevices[index].Name}";
else
this.Title = $"Camera - 연결에 실패했습니다.";
}
TimerStart(ref _dispatcherTimer);
}
private void TimerStart(ref DispatcherTimer dispatcherTimer)
{
if (dispatcherTimer != null && !dispatcherTimer.IsEnabled)
dispatcherTimer.Start();
}
private void TimerStop(ref DispatcherTimer dispatcherTimer)
{
if (dispatcherTimer != null && dispatcherTimer.IsEnabled)
dispatcherTimer.Stop();
}
}
}
- 옵션 폼 코드
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DirectShowLib;
namespace CameraCaptureWPF
{
/// <summary>
/// WindowOption.xaml에 대한 상호 작용 논리
/// </summary>
public partial class WindowOption : System.Windows.Window
{
List<DsDevice> cameraDevices = null; // 메인 폼에서 받아올 리스트
MainWindow _mainWindow = null;
public WindowOption(MainWindow mainWindow)
{
InitializeComponent();
this._mainWindow = mainWindow;
this.Loaded += WindowOption_Loaded;
chkb_IsStayOnTop.Click += (s, e) => { this.Topmost = (bool)chkb_IsStayOnTop.IsChecked; _mainWindow.Topmost = (bool)chkb_IsStayOnTop.IsChecked; }; // 체크박스 이벤트
cbb_ListCamera.SelectionChanged += Cbb_ListCamera_SelectionChanged;
}
private void WindowOption_Loaded(object sender, RoutedEventArgs e)
{
chkb_IsStayOnTop.Cursor = Cursors.Hand;
cbb_ListCamera.Cursor = Cursors.Hand;
chkb_IsStayOnTop.IsChecked = _mainWindow.Topmost; // 부모폼의 Topmost 설정 받아오기
this.Topmost = _mainWindow.Topmost; // 부모폼의 Topmost 설정 받아오기
cameraDevices = _mainWindow.cameraDevices; // 부모폼에 있는 카메라 리스트를 가져오기(폼이 열릴 때마다 오픈하면 메인폼과 옵션폼의 카메라 리스트가 달라질 수 있음)
SetOptionUI();
}
private void Cbb_ListCamera_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cbb_ListCamera.SelectedIndex > -1)
_mainWindow.SelectDeviceIndex = cbb_ListCamera.SelectedIndex; // 부모 폼에서 카메라 디바이스 선택해 변경하기 위해
}
// 옵션 폼 UI 설정
private void SetOptionUI(int index = 0)
{
if (cameraDevices.Count > 0 && index >= 0)
{
cbb_ListCamera.Items.Clear();
foreach (var cameraDevice in cameraDevices)
cbb_ListCamera.Items.Add(cameraDevice.Name);
if (_mainWindow.SelectDeviceIndex > -1)
cbb_ListCamera.SelectedIndex = _mainWindow.SelectDeviceIndex;
}
}
}
}
'C#' 카테고리의 다른 글
[C#] Mail 보내기 (0) | 2021.05.04 |
---|---|
[C#] .NET Framework 버전 확인 (0) | 2021.04.27 |
[C#] 윈도우 마이크 컨트롤 2 (AudioSwitcher, NAudio) (0) | 2021.04.13 |
[C#] Async/Await, Task.result (0) | 2021.04.12 |
[C#] Best Way Byte To Hex (0) | 2021.04.11 |