我制作了一台录像机,它可以拍摄每一帧的截图,并将其保存在一个临时文件夹中.当我按下停止录制按钮时,它将所有内容放在一个视频中.我现在需要让我的程序判断最新的2个截图,并进行比较,以找到变化,如果没有找到变化的最后一个图像应该删除.另一方面,如果两个图像有任何差异,两个图像都会保持不变.

谢谢你帮我!

Forms1.cs[Design] Forms1.cs[Design]

下面是我的屏幕录制脚本

ScreenRecorder.cs

using System.IO;
using System.Drawing;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Accord.Video;
using Accord.Video.FFMPEG;
using GroupDocs.Comparison.Options;
using GroupDocs.Comparison;

namespace Timelapser_version_1._2
{
    class ScreenRecorder
    {
        //Video variables:
        private Rectangle bounds;
        private string outputPath = "";
        private string tempPath = "";
        private int fileCount = 1;
        private List<string> inputImageSequence = new List<string>();

        //File variables:
        private string audioName = "mic.wav";
        private string videoName = "video.mp4";
        private string finalName = "FinalVideo.mp4";

        //Time variable:
        Stopwatch watch = new Stopwatch();

        //Audio variables:
        public static class NativeMethods
        {
            [DllImport("winmm.dll", EntryPoint = "mciSendStringA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
            public static extern int record(string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback);
        }

        //ScreenRecorder Object:
        public ScreenRecorder(Rectangle b, string outPath)
        {
            //Create temporary folder for screenshots:
            CreateTempFolder("tempScreenCaps");

            //Set variables:
            bounds = b;
            outputPath = outPath;
        }

        //Create temporary folder:
        private void CreateTempFolder(string name)
        {
            //Check if a C or D drive exists:
            if (Directory.Exists("D://"))
            {
                string pathName = $"D://{name}";
                Directory.CreateDirectory(pathName);
                tempPath = pathName;
            }
            else
            {
                string pathName = $"C://Documents//{name}";
                Directory.CreateDirectory(pathName);
                tempPath = pathName;
            }
        }

        //Change final video name:
        public void setVideoName(string name)
        {
            finalName = name;
        }

        //Delete all files and directory:
        private void DeletePath(string targetDir)
        {
            string[] files = Directory.GetFiles(targetDir);
            string[] dirs = Directory.GetDirectories(targetDir);

            //Delete each file:
            foreach (string file in files)
            {
                File.SetAttributes(file, FileAttributes.Normal);
                File.Delete(file);
            }

            //Delete the path:
            foreach (string dir in dirs)
            {
                DeletePath(dir);
            }

            Directory.Delete(targetDir, false);
        }

        //Delete all files except the one specified:
        private void DeleteFilesExcept(string targetDir, string excDir)
        {
            string[] files = Directory.GetFiles(targetDir);

            //Delete each file except specified:
            foreach (string file in files)
            {
                if (file != excDir)
                {
                    File.SetAttributes(file, FileAttributes.Normal);
                    File.Delete(file);
                }
            }
        }

        //Clean up program on crash:
        public void cleanUp()
        {
            if (Directory.Exists(tempPath))
            {
                DeletePath(tempPath);
            }
        }

        //Return elapsed time:
        public string getElapsed()
        {
            return string.Format("{0:D2}:{1:D2}:{2:D2}", watch.Elapsed.Hours, watch.Elapsed.Minutes, watch.Elapsed.Seconds);
        }

        //Record video:
        public void RecordVideo()
        {
            //Keep track of time:
            watch.Start();
            int blac=0;
            string a ="screenshot-1+%d";
            using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    //Add screen to bitmap:
                    g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
                }
                //Save screenshot:
                string name = tempPath + "//screenshot-" + fileCount + ".png";
                bitmap.Save(name, ImageFormat.Png);
                inputImageSequence.Add(name);
                fileCount++;

                //Dispose of bitmap:
                bitmap.Dispose();
            }
        }

        //Record audio:
        public void RecordAudio()
        {
            NativeMethods.record("open new Type waveaudio Alias recsound", "", 0, 0);
            NativeMethods.record("record recsound", "", 0, 0);
        }

        //Save audio file:
        private void SaveAudio()
        {
            string audioPath = "save recsound " + outputPath + "//" + audioName;
            NativeMethods.record(audioPath, "", 0, 0);
            NativeMethods.record("close recsound", "", 0, 0);
        }

        
        //Save video file:
        public void SaveVideo(int width, int height, int frameRate)
        {

            using (VideoFileWriter vFWriter = new VideoFileWriter())
            {
                
                vFWriter.Open(outputPath + "//"+ videoName, width, height, frameRate, VideoCodec.MPEG4);

                //Make each screenshot into a video frame:
                foreach (string imageLocation in inputImageSequence)
                {
                    Bitmap imageFrame = System.Drawing.Image.FromFile(imageLocation) as Bitmap;
                    vFWriter.WriteVideoFrame(imageFrame);
                    imageFrame.Dispose();
                }

                //Close:
                vFWriter.Close();
            }
        }

        //Combine video and audio files:
        private void CombineVideoAndAudio(string video, string audio)
        {
            //FFMPEG command to combine video and audio:
            string args = $"/c ffmpeg -i \"{video}\" -i \"{audio}\" -shortest {finalName}";
            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                CreateNoWindow = false,
                FileName = "cmd.exe",
                WorkingDirectory = outputPath,
                Arguments = args
            };

            //Execute command:
            using (Process exeProcess = Process.Start(startInfo))
            {
                exeProcess.WaitForExit();
            }
        }
       
        public void Stop()
        {
            //Stop watch:
            watch.Stop();

            //Video variables:
            int width = bounds.Width;
            int height = bounds.Height;
            int frameRate = 10;

            //Save audio:
            SaveAudio();

            //Save video:
            SaveVideo(width, height, frameRate);

            //Combine audio and video files:
            CombineVideoAndAudio(videoName, audioName);

            //Delete the screenshots and temporary folder:
            DeletePath(tempPath);

            //Delete separated video and audio files:
            DeleteFilesExcept(outputPath, outputPath + "\\" + finalName);
        }
    }
}

forms1.cs

using System;
using System.Drawing;
using System.Windows.Forms;
namespace Timelapser_version_1._2
{
    public partial class Timelapser : Form
    {
        string outputPath = "";
        bool folderSelected = false;
        string finalVidName = "FinalVideo.mp4";
        // Screen recorder object:
        ScreenRecorder screenRec = new ScreenRecorder(new Rectangle(), " ");
        public Timelapser()
        {
            InitializeComponent();
        }
       

        private void Start_Click(object sender, EventArgs e)
        {
            
            bool containsMP4 = finalVidName.Contains(".mp4");
            if (folderSelected && containsMP4)
            {
                screenRec.setVideoName(finalVidName);
                timer1.Start();
                
            }
            else if(!folderSelected && containsMP4)
            {
                MessageBox.Show("You must select an output Folder before recording","Error");
            }
            else if (folderSelected && !containsMP4)
            {
                MessageBox.Show("You must select video name that ends in '.mp4'", "Error");
                finalVidName = "FinalVideo.mp4";
            }
        }

        private void Stop_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            screenRec.Stop();
            Application.Restart();
        }
       
        private void timer1_Tick(object sender, EventArgs e)
        {
            
            screenRec.RecordVideo();
            screenRec.RecordAudio();
            Timelabel.Text = screenRec.getElapsed();
        }

        private void SelectFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowser = new FolderBrowserDialog();
            folderBrowser.Description = "Select an Output Folder";
            if (folderBrowser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                outputPath = @folderBrowser.SelectedPath;
                folderSelected = true;

                Rectangle bounds = Screen.FromControl(this).Bounds;
                screenRec = new ScreenRecorder(bounds,outputPath);
            }
            else
            {
                MessageBox.Show("Please select a folder");
            }
        }

推荐答案

我找到了解决方案,能够判断每个2截图,我们需要下面的功能.

public static List<bool> GetHash(Bitmap bmpSource)
        {
            List<bool> lResult = new List<bool>();
            //create new image with 128x128 pixel
            Bitmap bmpMin = new Bitmap(bmpSource, new System.Drawing.Size(128, 128));
            for (int j = 0; j < bmpMin.Height; j++)
            {
                for (int i = 0; i < bmpMin.Width; i++)
                {
                    //reduce colors to true / false                
                    lResult.Add(bmpMin.GetPixel(i, j).GetBrightness() < 0.1f);
                }
            }
            return lResult;
        }

此函数获取屏幕截图并创建其128x128版本.此外,它将 colored颜色 更改为黑白,以获得真假.

然后,我们需要为每2个屏幕截图调用该函数,如下所示.

                List<bool> iHash1 = GetHash(new Bitmap(tempPath + "//screenshot-" + k + ".png"));
                List<bool> iHash2 = GetHash(new Bitmap(tempPath + "//screenshot-" + (k + 1) + ".png"));
                //determine the number of equal pixel (x of 256)
                long equalElements = iHash1.Zip(iHash2, (i, j) => i == j).Count(eq => eq);
                Debug.Write(equalElements);
                if (equalElements > 16300 )
                {
                    var filePath = tempPath + "//screenshot-" + (k+1) + ".png";
                        File.Delete(filePath);
                    
                }

Csharp相关问答推荐

是否可以使用EF—Core进行临时部分更新?

NumPy s fftn in C#with pythonnet'

C++/C#HostFXR通过std::tuple传递参数

不仅仅是一个简单的自定义按钮

为什么总输出就像12.3没有一分一样?

Azure Function应用(. NET 8)不将信息记录到应用洞察

C#EF Core 8.0表现与预期不符

创建临时Collection 最有效的方法是什么?堆栈分配和集合表达式之间的区别?

如何在C#中使用Postman中的本地IP向本地主机上运行的本地API发出请求

如何在C#中将方法/线程启动传递给基本构造函数

net中从位图获取坐标和绘制折线

在implementationFactory中避免循环依赖

如何将%{v_扩展}转换为%{v_扩展}>>

.NET Google Workspace API获取错误CS0266

我应该为C#12中的主构造函数参数创建私有属性吗?

如何使用.NET 8.0中新的CompositeFormat类?

当`JToken?`为空时?

.NET EF Core Automapper项目到筛选不起作用

在使用xUnit和Mock执行单元测试时,控制器ViewResult返回空的Model集合

使用ImmutableList时,DynamicData未按预期工作