MainWindow.xaml
<Window x:Class="Splash.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="OpenCVの行人检测" Icon="FR.ico" WindowStartupLocation="CenterScreen" WindowState="Maximized" Loaded="Window_Loaded" Closing="Window_Closing">
<Grid>
<TabControl Margin="4" SelectionChanged="TabControl_SelectionChanged">
<TabItem Header="视频检测" Padding="8" Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Margin="4" Content="选择摄像头" VerticalContentAlignment="Center"/>
<ComboBox Grid.Column="1" Margin="4" HorizontalAlignment="Left" VerticalContentAlignment="Center" Width="320" Name="ComboBoxCameraDevices"/>
<Button Grid.Column="2" Margin="4" Padding="16,8" Foreground="Brown" Content="开启摄像头" Name="ButtonCaputre" Click="ButtonCaputre_Click"/>
</Grid>
<ScrollViewer Grid.Row="1" Margin="4" Background="Black" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Image Stretch="None" Margin="4" Name="ImageVideo"/>
</ScrollViewer>
</Grid>
</TabItem>
<TabItem Header="图像检测" Padding="8" Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Margin="4" Padding="16,8" HorizontalAlignment="Center" Foreground="Brown" Content="选择图像…" Name="ButtonSelect" Click="ButtonSelect_Click"/>
<ScrollViewer Grid.Row="1" Margin="4" Background="Black" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Image Stretch="None" Margin="4" Name="ImagePhoto"/>
</ScrollViewer>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
MainWindow.xaml.cs
/* ----------------------------------------------------------
* 文件名称:MainWindow.xaml.cs
*
* 作者:秦建辉
*
* 微信:splashcn
*
* 博客:http://www.firstsolver.com/wordpress/
*
* 开发环境:
* Visual Studio V2017
* .NET Framework 4.7.2
* OpenCvSharp 4.0.30319
*
* 版本历史:
* V1.0 2019年01月22日
* OpenCVの行人检测
*
* 参考资料:
* https://www.cnblogs.com/alexanderkun/p/4426021.html
* https://www.cnblogs.com/tornadomeet/archive/2012/08/03/2621814.html
* https://blog.csdn.net/qq_37753409/article/details/79047063
* ---------------------------------------------------------- */
using Com.FirstSolver.Splash;
using Newtonsoft.Json.Linq;
using OpenCvSharp.Extensions;
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
namespace Splash
{
public partial class MainWindow : System.Windows.Window
{
/// <summary>
/// 检测是否正在进行
/// </summary>
private bool IsRunning = false;
/// <summary>
/// 视频捕获设备
/// </summary>
private OpenCvSharp.VideoCapture Capture = null;
/// <summary>
/// 是否停止检测
/// </summary>
private volatile bool ShouldStop = true;
/// <summary>
/// 是否停止等待下一帧
/// </summary>
private ManualResetEvent WakeupResetEvent = new ManualResetEvent(true);
/// <summary>
/// HOG行人检测器
/// </summary>
private OpenCvSharp.HOGDescriptor Detector = null;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{ // 获取摄像头列表
int ErrorCode = MF_GetDeviceSources(out IntPtr devices, out int cch, true);
if (ErrorCode >= 0)
{
string json = Marshal.PtrToStringUni(devices, cch);
FreeMemory(devices);
JArray Devices = JArray.Parse(json.Replace("\\", "\\\\"));
ComboBoxCameraDevices.ItemsSource = Devices;
ComboBoxCameraDevices.DisplayMemberPath = "Name"; // 显示成员路径
ComboBoxCameraDevices.SelectedValuePath = "Moniker"; // 选择值成员路径
ComboBoxCameraDevices.SelectedIndex = 0;
if (Devices.Count == 1) ComboBoxCameraDevices.IsEnabled = false;
}
else
{ // 没有摄像头
ButtonCaputre.IsEnabled = false;
}
// 初始化行人检测器
Detector = new OpenCvSharp.HOGDescriptor();
Detector.SetSVMDetector(OpenCvSharp.HOGDescriptor.GetDefaultPeopleDetector()); // SVM分类器
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
CloseCapture();
if (Detector != null) { Detector.Dispose(); Detector = null; }
}
private void CloseCapture()
{
ShouldStop = true; // 停止检测
WakeupResetEvent.Set(); // 停止等待下一帧
if (Capture != null)
{
Capture.Release(); // 释放捕获设备
Capture = null;
}
}
private void ButtonCaputre_Click(object sender, RoutedEventArgs e)
{
if (IsRunning)
{ // 关闭检测
CloseCapture();
ButtonCaputre.Content = "开启摄像头";
IsRunning = false;
}
else
{ // 开启人脸检测
Capture = OpenCvSharp.VideoCapture.FromCamera(ComboBoxCameraDevices.SelectedIndex);
ShouldStop = false;
WakeupResetEvent.Reset();
if (ThreadPool.QueueUserWorkItem(new WaitCallback((state) => {
try
{
int millisecondsTimeout = (int)Math.Round(1000.0 / Capture.Fps); // 计算间隔
while (true)
{
if (ShouldStop) break; // 是否停止人脸检测
// 获取图像帧
OpenCvSharp.Mat Bgr = new OpenCvSharp.Mat();
if (Capture.Read(Bgr))
{
if (!Bgr.Empty())
{ // 检测行人
OpenCvSharp.Rect[] Pedestrians = Detector.DetectMultiScale(Bgr, 0, new OpenCvSharp.Size(8, 8), new OpenCvSharp.Size(32, 32));
// 消除嵌套的矩形框
foreach (var r in Pedestrians)
{
bool IsOK = true;
foreach (var t in Pedestrians)
{
if ((r != t) && ((r & t) == r))
{
IsOK = false;
break;
}
}
if (IsOK)
{
Bgr.Rectangle(r, new OpenCvSharp.Scalar(0, 0, 255), 3); // 红框标注
}
}
// 线程安全性
this.Dispatcher.BeginInvoke(new Action(() => {
ImageVideo.Source = Bgr.ToBitmapSource();
}));
}
}
// 是否停止等待下一帧
if (WakeupResetEvent.WaitOne(millisecondsTimeout)) break;
}
}
catch
{
// 屏蔽异常
}
})))
{
ButtonCaputre.Content = "关闭摄像头";
IsRunning = true;
}
else
{ // 启动人脸检测线程失败
ShouldStop = true;
WakeupResetEvent.Set();
}
}
}
// 基于单个图像的行人检测
private void ButtonSelect_Click(object sender, RoutedEventArgs e)
{
try
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog
{
Filter = "Image|*.jpg;*.bmp;*.png;*.tif;*.tga;*.ras;*.jp2;*.j2k;*.jpe",
DereferenceLinks = true
};
this.CenterChild();
if (dlg.ShowDialog(Owner).Value == true)
{
ThreadPool.QueueUserWorkItem(new WaitCallback((state) => {
OpenCvSharp.Mat Bgr = OpenCvSharp.Cv2.ImRead(dlg.FileName); // 装载彩色图像
if (!Bgr.Empty())
{ // 检测行人
OpenCvSharp.Rect[] Pedestrians = Detector.DetectMultiScale(Bgr, 0, new OpenCvSharp.Size(8, 8), new OpenCvSharp.Size(32, 32));
// 消除嵌套的矩形框
foreach (var r in Pedestrians)
{
bool IsOK = true;
foreach (var t in Pedestrians)
{
if ((r != t) && ((r & t) == r))
{
IsOK = false;
break;
}
}
if (IsOK)
{
Bgr.Rectangle(r, new OpenCvSharp.Scalar(0, 0, 255), 3); // 红框标注
}
}
// 线程安全性
this.Dispatcher.BeginInvoke(new Action(() => {
ImagePhoto.Source = Bgr.ToBitmapSource();
}));
}
}));
}
}
catch (System.Exception exception)
{
MessageBoxPlus.Show(this, exception.Message, "图像文件异常", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void TabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (((System.Windows.Controls.TabControl)sender).SelectedIndex == 1)
{
if (IsRunning) ButtonCaputre.RaiseEvent(new RoutedEventArgs(System.Windows.Controls.Button.ClickEvent));
}
}
#region MF_AudioVideoDevices
[DllImport("MF_AudioVideoDevices.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool Prepare();
[DllImport("MF_AudioVideoDevices.dll")]
public static extern int MF_GetDeviceSources(out IntPtr devices, out int cch, [MarshalAs(UnmanagedType.Bool)]bool video);
[DllImport("MF_AudioVideoDevices.dll")]
public static extern void FreeMemory(IntPtr p);
#endregion
}
}
运行结果