Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Threading.Tasks;
- using System.Web;
- using System.Windows.Forms;
- using OpenCvSharp;
- using OpenCvSharp.Extensions;
- using Tesseract;
- using Bitmap = System.Drawing.Bitmap;
- using Rectangle = System.Drawing.Rectangle;
- namespace VideoSegmentAnalyzer
- {
- public partial class Form1 : Form
- {
- private VideoCapture _videoCapture;
- private Timer _timer;
- private int _totalFrames;
- private int _currentFrame;
- private Rectangle _roiPicturebox; // To store the rectangle
- private System.Drawing.Point _rectangleStartPoint; // 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
- private List<System.Drawing.Point> _dotPoints = new List<System.Drawing.Point>();
- private bool _displayInBinary;
- private Mat frame;
- public Form1()
- {
- InitializeComponent();
- InitializeComponents();
- InitializeVideoCapture();
- }
- private void InitializeVideoCapture()
- {
- _videoCapture = new VideoCapture(@"D:\Csharp Projects\VideoSegmentAnalyzer\Videos\Video001.mp4");
- _totalFrames = _videoCapture.FrameCount;
- // Configure the trackBarFrames
- trackBarFrames.Minimum = 0;
- trackBarFrames.Maximum = _totalFrames - 1;
- trackBarFrames.TickFrequency = 1;
- trackBarFrames.Value = 0;
- trackBarFrames.Scroll += TrackBarFrames_Scroll;
- // Display the first frame for drawing the ROI
- _firstFrame = new Mat();
- if (_videoCapture.Read(_firstFrame))
- {
- Bitmap bitmap = BitmapConverter.ToBitmap(_firstFrame);
- UpdateControl(bitmap.Width, bitmap.Height);
- pictureBoxFrames.Image = bitmap;
- labelFrames.Text = $"Displaying frame 1/{_totalFrames}"; // Show 1 as the first frame
- }
- _timer = new Timer();
- _timer.Interval = 30; // Adjust as needed
- _timer.Tick += ProcessFrame;
- }
- private void TrackBarFrames_Scroll(object sender, EventArgs e)
- {
- _currentFrame = trackBarFrames.Value;
- _videoCapture.Set(VideoCaptureProperties.PosFrames, _currentFrame);
- Mat frame = new Mat();
- if (_videoCapture.Read(frame))
- {
- pictureBoxFrames.Image = BitmapConverter.ToBitmap(frame);
- labelFrames.Text = $"Displaying frame {_currentFrame + 1}/{_totalFrames}"; // Add 1 to display the frame number starting from 1
- }
- }
- private void ButtonStart_Click(object sender, EventArgs e)
- {
- if (_roiPicturebox.Width == 0 || _roiPicturebox.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 (_roiPicturebox.Width == 0 || _roiPicturebox.Height == 0)
- {
- MessageBox.Show("Please draw a rectangle to define the ROI.");
- return;
- }
- int frameNumber = trackBarFrames.Value;
- _videoCapture.Set(VideoCaptureProperties.PosFrames, frameNumber);
- Mat frame = new Mat();
- if (_videoCapture.Read(frame))
- {
- ProcessSingleFrame(frame, frameNumber);
- }
- else
- {
- MessageBox.Show("Failed to read the frame at the current trackbar position.");
- }
- }
- private async void ProcessSingleFrame(Mat frame, int frameNumber)
- {
- // Process and analyze the frame
- (Mat analyzedFrame, bool segmentDetected, bool blinkDetected) = await Task.Run(() => AnalyzeFrame(frame, frameNumber));
- if (analyzedFrame != null)
- {
- pictureBoxPoints.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 (Mat frame = new Mat())
- {
- if (_videoCapture.Read(frame))
- {
- // Update the ROI if tracking is enabled
- if (_tracking && _firstFrame != null)
- {
- _roiPicturebox = UpdateROI(_firstFrame, frame, _roiPicturebox);
- }
- // Ensure ROI is within frame bounds
- _roiPicturebox = EnsureROIWithinBounds(frame, _roiPicturebox);
- // Display each frame in pictureBoxFrame
- pictureBoxFrames.Image = BitmapConverter.ToBitmap(frame);
- // Process and analyze the frame
- (Mat analyzedFrame, bool segmentDetected, bool blinkDetected) = await Task.Run(() => AnalyzeFrame(frame, _currentFrame));
- if (analyzedFrame != null)
- {
- pictureBoxPoints.Image = BitmapConverter.ToBitmap(analyzedFrame);
- labelStatus.Text = $"Segment detected in frame {_currentFrame}.";
- }
- else
- {
- pictureBoxPoints.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 frameMat, bool segmentDetected, bool blinkDetected) AnalyzeFrame(Mat frame, int frameNumber)
- {
- this.frame = frame;
- bool blinkDetected = false;
- // Ensure we have a valid ROI
- if (_roiPicturebox.Width == 0 || _roiPicturebox.Height == 0)
- return (null, false, blinkDetected);
- double xFactor = (double)frame.Width / pictureBoxFrames.Width;
- double yFactor = (double)frame.Height / pictureBoxFrames.Height;
- // Convert ROI to OpenCV Rect and crop the frame
- OpenCvSharp.Rect rect = new OpenCvSharp.Rect(
- (int)(_roiPicturebox.X * xFactor),
- (int)(_roiPicturebox.Y * yFactor),
- (int)(_roiPicturebox.Width * xFactor),
- (int)(_roiPicturebox.Height * yFactor)
- );
- Mat roiFrame = new Mat(frame, rect);
- // Convert ROI frame to grayscale for analysis
- Mat analysisFrame = new Mat();
- Cv2.CvtColor(roiFrame, analysisFrame, ColorConversionCodes.BGR2GRAY);
- // Convert Mat to Bitmap for binary threshold analysis
- Mat binaryFrame = new Mat();
- Cv2.Threshold(analysisFrame, binaryFrame, 180, 255, ThresholdTypes.Binary);
- // Display the ROI frame based on the selected display mode
- if (!_displayInBinary)
- {
- // Display the ROI frame in black & white (binary)
- pictureBoxPoints.Image = BitmapConverter.ToBitmap(binaryFrame);
- }
- else
- {
- // Display the ROI frame in color
- pictureBoxPoints.Image = BitmapConverter.ToBitmap(roiFrame);
- }
- // Find contours
- OpenCvSharp.Point[][] contours;
- HierarchyIndex[] hierarchy;
- Cv2.FindContours(binaryFrame, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
- // Detect if the display is blank (blink)
- if (contours.Length == 0)
- {
- blinkDetected = true;
- }
- return (null, false, blinkDetected);
- }
- 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
- OpenCvSharp.Point2f[] prevPts = {
- new OpenCvSharp.Point2f(roi.Left, roi.Top),
- new OpenCvSharp.Point2f(roi.Right, roi.Top),
- new OpenCvSharp.Point2f(roi.Left, roi.Bottom),
- new OpenCvSharp.Point2f(roi.Right, roi.Bottom)
- };
- OpenCvSharp.Point2f[] currPts = new OpenCvSharp.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);
- }
- #region UI Components and Initialization
- private void InitializeComponents()
- {
- radioButtonColorThreshold.Checked = true;
- }
- private void UpdateControl(int videoWidth, int videoHeight)
- {
- int height = 640;
- int width = height * videoWidth / videoHeight;
- int gap = 20;
- }
- #endregion
- #region PictureBoxPoints Events
- private void PictureBoxPoints_MouseDown(object sender, MouseEventArgs e)
- {
- if (e.Button == MouseButtons.Left && pictureBoxPoints.Image != null)
- {
- if (frame != null)
- {
- // Calculate the image coordinates based on the mouse position
- double xFactor = (double)frame.Width / pictureBoxFrames.Width;
- double yFactor = (double)frame.Height / pictureBoxFrames.Height;
- // Adjust for Zoom mode: Get the actual displayed image size
- int displayedImageWidth = pictureBoxPoints.ClientSize.Width;
- int displayedImageHeight = pictureBoxPoints.ClientSize.Height;
- int imageX = (int)(e.Location.X * xFactor);
- int imageY = (int)(e.Location.Y * yFactor);
- // Now 'imageX' and 'imageY' contain the corresponding image coordinates
- // You can use these values for further processing
- _dotPoints.Add(new System.Drawing.Point(imageX, imageY));
- pictureBoxPoints.Invalidate();
- }
- }
- }
- private void PictureBoxPoints_Paint(object sender, PaintEventArgs e)
- {
- foreach (System.Drawing.Point point in _dotPoints)
- {
- int ellipseWidth = 10;
- int ellipseHeight = 10;
- int ellipseX = point.X - ellipseWidth / 2;
- int ellipseY = point.Y - ellipseHeight / 2;
- e.Graphics.FillEllipse(Brushes.Red, new Rectangle(ellipseX, ellipseY, ellipseWidth, ellipseHeight));
- }
- }
- private void PictureBoxAnalyzed_Paint(object sender, PaintEventArgs e)
- {
- }
- #endregion
- private void RadioButtonThreshold_CheckedChanged(object sender, EventArgs e)
- {
- if (radioButtonGrayThreshold.Checked)
- {
- _displayInBinary = false;
- }
- else if (radioButtonColorThreshold.Checked)
- {
- _displayInBinary = true;
- }
- // Optionally reprocess the current frame to reflect the change immediately
- if (_videoCapture != null && _currentFrame < _totalFrames)
- {
- Mat frame = new Mat();
- _videoCapture.Set(VideoCaptureProperties.PosFrames, _currentFrame);
- if (_videoCapture.Read(frame))
- {
- ProcessSingleFrame(frame, _currentFrame);
- }
- }
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- }
- private void pictureBoxFrames_MouseDown(object sender, MouseEventArgs e)
- {
- _tracking = false;
- if (!_tracking)
- {
- _rectangleStartPoint = e.Location;
- _roiPicturebox = Rectangle.Empty; // Clear the existing rectangle
- pictureBoxFrames.Invalidate(); // Trigger repaint to clear the previous rectangle
- _drawing = true;
- }
- }
- private void pictureBoxFrames_MouseMove(object sender, MouseEventArgs e)
- {
- if (_drawing && pictureBoxFrames.Image != null)
- {
- System.Drawing.Point endPoint = e.Location;
- _roiPicturebox = new Rectangle(Math.Min(_rectangleStartPoint.X, endPoint.X),
- Math.Min(_rectangleStartPoint.Y, endPoint.Y),
- Math.Abs(_rectangleStartPoint.X - endPoint.X),
- Math.Abs(_rectangleStartPoint.Y - endPoint.Y));
- pictureBoxFrames.Invalidate(); // Trigger repaint
- }
- }
- private void pictureBoxFrames_MouseUp(object sender, MouseEventArgs e)
- {
- _drawing = false;
- _tracking = true;
- }
- private void pictureBoxFrames_Paint(object sender, PaintEventArgs e)
- {
- if (_roiPicturebox != Rectangle.Empty)
- {
- e.Graphics.DrawRectangle(Pens.Red, _roiPicturebox);
- }
- }
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment