Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Drawing;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using OpenCvSharp;
- using OpenCvSharp.Extensions;
- using Point = OpenCvSharp.Point; // Ensuring OpenCvSharp Point is used
- using Size = OpenCvSharp.Size; // Ensuring OpenCvSharp Size is used
- namespace VideoSegmentAnalyzer
- {
- public partial class Form1 : Form
- {
- private VideoCapture _videoCapture;
- private Timer _timer;
- private int _totalFrames;
- private int _currentFrame;
- private Rectangle _roi; // To store the rectangle
- private System.Drawing.Point _startPoint; // To store the start point of the rectangle
- private bool _drawing; // To indicate if we are currently drawing
- private bool _tracking; // To indicate if we are currently tracking
- private Mat _firstFrame; // To store the first frame for testing
- public Form1()
- {
- InitializeComponent();
- InitializeComponents();
- InitializeVideoCapture();
- }
- private void InitializeComponents()
- {
- this.pictureBoxFrame = new PictureBox();
- this.pictureBoxAnalyzed = new PictureBox();
- this.progressBarAnalysis = new ProgressBar();
- this.labelStatus = new Label();
- this.buttonStart = new Button();
- this.buttonTest = new Button();
- // pictureBoxFrame setup
- this.pictureBoxFrame.Location = new System.Drawing.Point(12, 12);
- this.pictureBoxFrame.Size = new System.Drawing.Size(320, 240);
- this.pictureBoxFrame.SizeMode = PictureBoxSizeMode.StretchImage; // Ensure the video fits the PictureBox
- this.pictureBoxFrame.MouseDown += PictureBoxFrame_MouseDown;
- this.pictureBoxFrame.MouseMove += PictureBoxFrame_MouseMove;
- this.pictureBoxFrame.MouseUp += PictureBoxFrame_MouseUp;
- this.pictureBoxFrame.Paint += PictureBoxFrame_Paint;
- // pictureBoxAnalyzed setup
- this.pictureBoxAnalyzed.Location = new System.Drawing.Point(350, 12);
- this.pictureBoxAnalyzed.Size = new System.Drawing.Size(320, 240);
- this.pictureBoxAnalyzed.SizeMode = PictureBoxSizeMode.StretchImage; // Ensure the analyzed frame fits the PictureBox
- // progressBarAnalysis setup
- this.progressBarAnalysis.Location = new System.Drawing.Point(12, 270);
- this.progressBarAnalysis.Size = new System.Drawing.Size(658, 23);
- // labelStatus setup
- this.labelStatus.Location = new System.Drawing.Point(12, 300);
- this.labelStatus.Size = new System.Drawing.Size(658, 23);
- // buttonStart setup
- this.buttonStart.Location = new System.Drawing.Point(12, 330);
- this.buttonStart.Size = new System.Drawing.Size(100, 30);
- this.buttonStart.Text = "Start Analysis";
- this.buttonStart.Click += new EventHandler(this.ButtonStart_Click);
- // buttonTest setup
- this.buttonTest.Location = new System.Drawing.Point(120, 330);
- this.buttonTest.Size = new System.Drawing.Size(100, 30);
- this.buttonTest.Text = "Test First Frame";
- this.buttonTest.Click += new EventHandler(this.ButtonTest_Click);
- // Adding controls to the form
- this.Controls.Add(this.pictureBoxFrame);
- this.Controls.Add(this.pictureBoxAnalyzed);
- this.Controls.Add(this.progressBarAnalysis);
- this.Controls.Add(this.labelStatus);
- this.Controls.Add(this.buttonStart);
- this.Controls.Add(this.buttonTest);
- // Form setup
- this.Text = "Video Segment Analyzer";
- this.ClientSize = new System.Drawing.Size(682, 373);
- this.FormClosing += new FormClosingEventHandler(this.MainForm_FormClosing);
- }
- private void PictureBoxFrame_MouseDown(object sender, MouseEventArgs e)
- {
- if (!_tracking)
- {
- _startPoint = e.Location;
- _drawing = true;
- }
- }
- private void PictureBoxFrame_MouseMove(object sender, MouseEventArgs e)
- {
- if (_drawing)
- {
- System.Drawing.Point endPoint = e.Location;
- _roi = new Rectangle(Math.Min(_startPoint.X, endPoint.X),
- Math.Min(_startPoint.Y, endPoint.Y),
- Math.Abs(_startPoint.X - endPoint.X),
- Math.Abs(_startPoint.Y - endPoint.Y));
- pictureBoxFrame.Invalidate(); // Trigger repaint
- }
- }
- private void PictureBoxFrame_MouseUp(object sender, MouseEventArgs e)
- {
- _drawing = false;
- _tracking = true;
- }
- private void PictureBoxFrame_Paint(object sender, PaintEventArgs e)
- {
- if (_roi != null && _roi.Width > 0 && _roi.Height > 0)
- {
- e.Graphics.DrawRectangle(Pens.Red, _roi);
- }
- }
- private void InitializeVideoCapture()
- {
- _videoCapture = new VideoCapture(@"D:\Csharp Projects\VideoSegmentAnalyzer\Video Files to Analyze\Video001.mp4");
- _totalFrames = _videoCapture.FrameCount;
- // Display the first frame for drawing the ROI
- _firstFrame = new Mat();
- if (_videoCapture.Read(_firstFrame))
- {
- pictureBoxFrame.Image = BitmapConverter.ToBitmap(_firstFrame);
- }
- _timer = new Timer();
- _timer.Interval = 30; // Adjust as needed
- _timer.Tick += ProcessFrame;
- }
- private void ButtonStart_Click(object sender, EventArgs e)
- {
- if (_roi.Width == 0 || _roi.Height == 0)
- {
- MessageBox.Show("Please draw a rectangle to define the ROI.");
- return;
- }
- _currentFrame = 0;
- progressBarAnalysis.Value = 0;
- labelStatus.Text = "Starting analysis...";
- _timer.Start();
- }
- private void ButtonTest_Click(object sender, EventArgs e)
- {
- if (_firstFrame != null)
- {
- ProcessSingleFrame(_firstFrame, 0);
- }
- }
- private async void ProcessSingleFrame(Mat frame, int frameNumber)
- {
- // Process and analyze the frame
- bool blinkDetected = false;
- string lastSegment = string.Empty;
- var (analyzedFrame, segmentDetected) = await Task.Run(() => AnalyzeFrame(frame, frameNumber, ref blinkDetected, ref lastSegment));
- if (analyzedFrame != null)
- {
- pictureBoxAnalyzed.Image = BitmapConverter.ToBitmap(analyzedFrame);
- labelStatus.Text = $"Segment detected in frame {frameNumber}.";
- }
- else
- {
- pictureBoxAnalyzed.Image = null; // Clear the PictureBox if no segments are detected
- labelStatus.Text = $"No segment detected in frame {frameNumber}.";
- }
- }
- private async void ProcessFrame(object sender, EventArgs e)
- {
- using (var frame = new Mat())
- {
- if (_videoCapture.Read(frame))
- {
- // Update the ROI if tracking is enabled
- if (_tracking && _firstFrame != null)
- {
- _roi = UpdateROI(_firstFrame, frame, _roi);
- }
- // Ensure ROI is within frame bounds
- _roi = EnsureROIWithinBounds(frame, _roi);
- // Display each frame in pictureBoxFrame
- pictureBoxFrame.Image = BitmapConverter.ToBitmap(frame);
- // Initialize blink detection and last segment variables
- bool blinkDetected = false;
- string lastSegment = string.Empty;
- // Process and analyze the frame
- var (analyzedFrame, segmentDetected) = await Task.Run(() => AnalyzeFrame(frame, _currentFrame, ref blinkDetected, ref lastSegment));
- if (analyzedFrame != null)
- {
- pictureBoxAnalyzed.Image = BitmapConverter.ToBitmap(analyzedFrame);
- labelStatus.Text = $"Segment detected in frame {_currentFrame}.";
- }
- else
- {
- pictureBoxAnalyzed.Image = null; // Clear the PictureBox if no segments are detected
- labelStatus.Text = $"Processing frame {_currentFrame}/{_totalFrames}.";
- }
- // Update progress
- _currentFrame++;
- progressBarAnalysis.Value = (int)((double)_currentFrame / _totalFrames * 100);
- labelStatus.Text = segmentDetected ? $"Segment detected in frame {_currentFrame}." : $"Processing frame {_currentFrame}/{_totalFrames}";
- if (_currentFrame >= _totalFrames)
- {
- _timer.Stop();
- labelStatus.Text = "Analysis complete.";
- }
- // Store the current frame as the previous frame for the next iteration
- _firstFrame = frame.Clone();
- }
- else
- {
- _timer.Stop();
- labelStatus.Text = "Error reading video file.";
- }
- }
- }
- private (Mat, bool) AnalyzeFrame(Mat frame, int frameNumber, ref bool blinkDetected, ref string lastSegment)
- {
- // Ensure we have a valid ROI
- if (_roi.Width == 0 || _roi.Height == 0)
- return (null, false);
- // Convert ROI to OpenCV Rect and crop the frame
- Rect rect = new Rect(_roi.X, _roi.Y, _roi.Width, _roi.Height);
- Mat roiFrame = new Mat(frame, rect);
- // Convert ROI frame to grayscale
- Mat grayFrame = new Mat();
- Cv2.CvtColor(roiFrame, grayFrame, ColorConversionCodes.BGR2GRAY);
- // Apply GaussianBlur
- Mat blurredFrame = new Mat();
- Cv2.GaussianBlur(grayFrame, blurredFrame, new Size(5, 5), 0);
- // Apply Canny edge detection
- Mat canny = new Mat();
- Cv2.Canny(blurredFrame, canny, 50, 150);
- // Apply morphological transformation
- Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));
- Mat closed = new Mat();
- Cv2.MorphologyEx(canny, closed, MorphTypes.Close, kernel);
- // Find contours
- Point[][] contours;
- HierarchyIndex[] hierarchy;
- Cv2.FindContours(closed, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
- bool segmentDetected = false;
- foreach (var contour in contours)
- {
- double peri = Cv2.ArcLength(contour, true);
- var approx = Cv2.ApproxPolyDP(contour, 0.02 * peri, true);
- double area = Cv2.ContourArea(approx);
- if (approx.Length == 4 && area > 1000)
- {
- Rect boundingRect = Cv2.BoundingRect(approx);
- Cv2.Rectangle(frame, boundingRect, new Scalar(36, 255, 12), 3);
- segmentDetected = true;
- // Save the frame
- string filePath = $@"D:\DetectedFrames\frame_{frameNumber}.png";
- frame.SaveImage(filePath);
- }
- }
- return segmentDetected ? (frame, true) : (null, false);
- }
- private Rectangle UpdateROI(Mat previousFrame, Mat currentFrame, Rectangle roi)
- {
- // Convert frames to grayscale
- Mat prevGray = new Mat();
- Mat currGray = new Mat();
- Cv2.CvtColor(previousFrame, prevGray, ColorConversionCodes.BGR2GRAY);
- Cv2.CvtColor(currentFrame, currGray, ColorConversionCodes.BGR2GRAY);
- // Define the points to track
- Point2f[] prevPts = {
- new Point2f(roi.Left, roi.Top),
- new Point2f(roi.Right, roi.Top),
- new Point2f(roi.Left, roi.Bottom),
- new Point2f(roi.Right, roi.Bottom)
- };
- Point2f[] currPts = new Point2f[prevPts.Length];
- // Track points using KLT tracker
- byte[] status;
- float[] err;
- Cv2.CalcOpticalFlowPyrLK(prevGray, currGray, prevPts, ref currPts, out status, out err);
- // Calculate the movement
- if (status[0] == 1 && status[1] == 1 && status[2] == 1 && status[3] == 1)
- {
- float dx = (currPts[0].X + currPts[1].X + currPts[2].X + currPts[3].X) / 4 - (prevPts[0].X + prevPts[1].X + prevPts[2].X + prevPts[3].X) / 4;
- float dy = (currPts[0].Y + currPts[1].Y + currPts[2].Y + currPts[3].Y) / 4 - (prevPts[0].Y + prevPts[1].Y + prevPts[2].Y + prevPts[3].Y) / 4;
- // Update the ROI position
- return new Rectangle((int)(roi.X + dx), (int)(roi.Y + dy), roi.Width, roi.Height);
- }
- return roi;
- }
- private Rectangle EnsureROIWithinBounds(Mat frame, Rectangle roi)
- {
- // Ensure the ROI does not go out of the frame bounds
- int x = Math.Max(roi.X, 0);
- int y = Math.Max(roi.Y, 0);
- int width = Math.Min(roi.Width, frame.Cols - x);
- int height = Math.Min(roi.Height, frame.Rows - y);
- return new Rectangle(x, y, width, height);
- }
- private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
- {
- _timer?.Stop();
- _videoCapture?.Release();
- }
- private PictureBox pictureBoxFrame;
- private PictureBox pictureBoxAnalyzed;
- private ProgressBar progressBarAnalysis;
- private Label labelStatus;
- private Button buttonStart;
- private Button buttonTest;
- private void Form1_Load(object sender, EventArgs e)
- {
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment