・インメモリでやれば良いがc:\にテンポラリ吐いてます。
・特定の区域を検査する事によりドアを開けた、通過した等検知できます。
・Webカメラがないので動画ファイルの再生でやってますがカメラによる
リアルタイム検知が可能。
・差分1の画像で黒以外のドット数を調べてその数から大体の人数が出せる。
・カメラから遠い所は一人分の面積が小さくなるのでエリア別に計算すると
尚よい。
・差分1をよく見ると横線が出ているので風か何かで揺れている事がわかる。
・差分法など使わず独自のアルゴリズムで解析してみたい。(考案中)
1. 1フレーム目
2. 数フレーム先
3. 差分1
4. 差分2
5. 差分1と差分2の論理積
6. WPF
/////////////////////////////////////
// WPF+OpenCvSharp 動画解析 R1.00
// (c)inf102 2024.
// https://github.com/opencv/opencv/blob/master/samples/data/vtest.avi
/////////////////////////////////////
using OpenCvSharp;
using OpenCvSharp.WpfExtensions;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
namespace openCV4 {
public partial class MainWindow : System.Windows.Window {
static int ch=0;
public MainWindow() {
InitializeComponent();
}
private async void Window_Loaded(object sender, RoutedEventArgs e) {
VideoCapture capture = new VideoCapture("C:\\vtest.avi");
var img = new Mat();
// 再生フレームカウンタ
int cnt=0;
// フレーム間隔 管理用
int cr=0;
while (capture.Read(img)){
BitmapSource x=BitmapSourceConverter.ToBitmapSource(img);
PngBitmapEncoder encoder = new PngBitmapEncoder();
cr++;
// フレーム保存
if (cr==1){
using (Stream stream = new FileStream("c:\\1st.jpg", FileMode.Create)){
encoder.Frames.Add (BitmapFrame.Create(x));
encoder.Save(stream);
}
}
// +4フレーム目保存
if (cr==5){
cr=0;
using (Stream stream = new FileStream("c:\\2nd.jpg", FileMode.Create)){
encoder.Frames.Add (BitmapFrame.Create(x));
encoder.Save(stream);
}
// 差分
Sa();
}
imageL.Source=x;
await Task.Delay(100);
cnt++;
}
imageL.Source=null;
}
// 差分+AND
public void Sa() {
Mat image1 = Cv2.ImRead("C:\\1st.jpg");
Mat image2 = Cv2.ImRead("C:\\2nd.jpg");
Mat diff = new Mat(new OpenCvSharp.Size(image1.Cols, image1.Rows), MatType.CV_8UC3);
var dst = new Mat();
Cv2.Absdiff(image1, image2, diff);
var xx=BitmapSourceConverter.ToBitmapSource(diff);
if (ch==0){
using (Stream stream = new FileStream("c:\\diff_1st.jpg", FileMode.Create)){
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(xx));
encoder.Save(stream);
}
ch=1;
}
else {
using (Stream stream = new FileStream("c:\\diff_2nd.jpg", FileMode.Create)){
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(xx));
encoder.Save(stream);
}
ch=0;
var file1 = "c:\\diff_1st.jpg";
var file2 = "c:\\diff_2nd.jpg";
var imgA = new Mat(file1);
var imgB = new Mat(file2);
Cv2.BitwiseAnd(imgA, imgB, dst);
var xx2=BitmapSourceConverter.ToBitmapSource(dst);
imageR.Source=xx2;
//////////////// 差分2枚のANDを算出保存
using (Stream stream = new FileStream("c:\\AND.jpg", FileMode.Create)){
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(xx2));
encoder.Save(stream);
}
//////////////////////////////////////////
int c=0;
int f=0;
for (int y = 0; y < dst.Height; y++){
for (int x = 0; x < dst.Width; x++){
byte b = dst.At<byte>(y, x);
if ((int)b!=0) c++;
else f++;
}
}
double tt=c/8000;
int cx=(int)tt;
cx=cx/2;
Title="["+cx.ToString()+"人] 人DAT"+c+" 以外F"+f.ToString();
}
}
}
}
7.XAML
<Window x:Class="openCV4.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:openCV4"
mc:Ignorable="d"
Title="MainWindow" Height="340" Width="830" Loaded="Window_Loaded">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width= "407"/>
<ColumnDefinition Width= "*"/>
</Grid.ColumnDefinitions>
<Image x:Name="imageL" Grid.Column="0"/>
<Image x:Name="imageR" Grid.Column="1"/>
</Grid>
</Window>