Chocolade19721309

Untitled

Jun 8th, 2024
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.46 KB | None | 0 0
  1. using System;
  2. using System.Drawing;
  3. using System.Threading.Tasks;
  4. using System.Windows.Forms;
  5. using OpenCvSharp;
  6. using OpenCvSharp.Extensions;
  7. using Point = OpenCvSharp.Point; // Ensuring OpenCvSharp Point is used
  8. using Size = OpenCvSharp.Size; // Ensuring OpenCvSharp Size is used
  9.  
  10. namespace VideoSegmentAnalyzer
  11. {
  12. public partial class Form1 : Form
  13. {
  14. private VideoCapture _videoCapture;
  15. private Timer _timer;
  16. private int _totalFrames;
  17. private int _currentFrame;
  18.  
  19. private Rectangle _roi; // To store the rectangle
  20. private System.Drawing.Point _startPoint; // To store the start point of the rectangle
  21. private bool _drawing; // To indicate if we are currently drawing
  22. private bool _tracking; // To indicate if we are currently tracking
  23. private Mat _firstFrame; // To store the first frame for testing
  24.  
  25. public Form1()
  26. {
  27. InitializeComponent();
  28. InitializeComponents();
  29. InitializeVideoCapture();
  30. }
  31.  
  32. private void InitializeComponents()
  33. {
  34. this.pictureBoxFrame = new PictureBox();
  35. this.pictureBoxAnalyzed = new PictureBox();
  36. this.progressBarAnalysis = new ProgressBar();
  37. this.labelStatus = new Label();
  38. this.buttonStart = new Button();
  39. this.buttonTest = new Button();
  40.  
  41. // pictureBoxFrame setup
  42. this.pictureBoxFrame.Location = new System.Drawing.Point(12, 12);
  43. this.pictureBoxFrame.Size = new System.Drawing.Size(320, 240);
  44. this.pictureBoxFrame.SizeMode = PictureBoxSizeMode.StretchImage; // Ensure the video fits the PictureBox
  45. this.pictureBoxFrame.MouseDown += PictureBoxFrame_MouseDown;
  46. this.pictureBoxFrame.MouseMove += PictureBoxFrame_MouseMove;
  47. this.pictureBoxFrame.MouseUp += PictureBoxFrame_MouseUp;
  48. this.pictureBoxFrame.Paint += PictureBoxFrame_Paint;
  49.  
  50. // pictureBoxAnalyzed setup
  51. this.pictureBoxAnalyzed.Location = new System.Drawing.Point(350, 12);
  52. this.pictureBoxAnalyzed.Size = new System.Drawing.Size(320, 240);
  53. this.pictureBoxAnalyzed.SizeMode = PictureBoxSizeMode.StretchImage; // Ensure the analyzed frame fits the PictureBox
  54.  
  55. // progressBarAnalysis setup
  56. this.progressBarAnalysis.Location = new System.Drawing.Point(12, 270);
  57. this.progressBarAnalysis.Size = new System.Drawing.Size(658, 23);
  58.  
  59. // labelStatus setup
  60. this.labelStatus.Location = new System.Drawing.Point(12, 300);
  61. this.labelStatus.Size = new System.Drawing.Size(658, 23);
  62.  
  63. // buttonStart setup
  64. this.buttonStart.Location = new System.Drawing.Point(12, 330);
  65. this.buttonStart.Size = new System.Drawing.Size(100, 30);
  66. this.buttonStart.Text = "Start Analysis";
  67. this.buttonStart.Click += new EventHandler(this.ButtonStart_Click);
  68.  
  69. // buttonTest setup
  70. this.buttonTest.Location = new System.Drawing.Point(120, 330);
  71. this.buttonTest.Size = new System.Drawing.Size(100, 30);
  72. this.buttonTest.Text = "Test First Frame";
  73. this.buttonTest.Click += new EventHandler(this.ButtonTest_Click);
  74.  
  75. // Adding controls to the form
  76. this.Controls.Add(this.pictureBoxFrame);
  77. this.Controls.Add(this.pictureBoxAnalyzed);
  78. this.Controls.Add(this.progressBarAnalysis);
  79. this.Controls.Add(this.labelStatus);
  80. this.Controls.Add(this.buttonStart);
  81. this.Controls.Add(this.buttonTest);
  82.  
  83. // Form setup
  84. this.Text = "Video Segment Analyzer";
  85. this.ClientSize = new System.Drawing.Size(682, 373);
  86. this.FormClosing += new FormClosingEventHandler(this.MainForm_FormClosing);
  87. }
  88.  
  89. private void PictureBoxFrame_MouseDown(object sender, MouseEventArgs e)
  90. {
  91. if (!_tracking)
  92. {
  93. _startPoint = e.Location;
  94. _drawing = true;
  95. }
  96. }
  97.  
  98. private void PictureBoxFrame_MouseMove(object sender, MouseEventArgs e)
  99. {
  100. if (_drawing)
  101. {
  102. System.Drawing.Point endPoint = e.Location;
  103. _roi = new Rectangle(Math.Min(_startPoint.X, endPoint.X),
  104. Math.Min(_startPoint.Y, endPoint.Y),
  105. Math.Abs(_startPoint.X - endPoint.X),
  106. Math.Abs(_startPoint.Y - endPoint.Y));
  107. pictureBoxFrame.Invalidate(); // Trigger repaint
  108. }
  109. }
  110.  
  111. private void PictureBoxFrame_MouseUp(object sender, MouseEventArgs e)
  112. {
  113. _drawing = false;
  114. _tracking = true;
  115. }
  116.  
  117. private void PictureBoxFrame_Paint(object sender, PaintEventArgs e)
  118. {
  119. if (_roi != null && _roi.Width > 0 && _roi.Height > 0)
  120. {
  121. e.Graphics.DrawRectangle(Pens.Red, _roi);
  122. }
  123. }
  124.  
  125. private void InitializeVideoCapture()
  126. {
  127. _videoCapture = new VideoCapture(@"D:\Csharp Projects\VideoSegmentAnalyzer\Video Files to Analyze\Video001.mp4");
  128. _totalFrames = _videoCapture.FrameCount;
  129.  
  130. // Display the first frame for drawing the ROI
  131. _firstFrame = new Mat();
  132. if (_videoCapture.Read(_firstFrame))
  133. {
  134. pictureBoxFrame.Image = BitmapConverter.ToBitmap(_firstFrame);
  135. }
  136.  
  137. _timer = new Timer();
  138. _timer.Interval = 30; // Adjust as needed
  139. _timer.Tick += ProcessFrame;
  140. }
  141.  
  142. private void ButtonStart_Click(object sender, EventArgs e)
  143. {
  144. if (_roi.Width == 0 || _roi.Height == 0)
  145. {
  146. MessageBox.Show("Please draw a rectangle to define the ROI.");
  147. return;
  148. }
  149.  
  150. _currentFrame = 0;
  151. progressBarAnalysis.Value = 0;
  152. labelStatus.Text = "Starting analysis...";
  153. _timer.Start();
  154. }
  155.  
  156. private void ButtonTest_Click(object sender, EventArgs e)
  157. {
  158. if (_firstFrame != null)
  159. {
  160. ProcessSingleFrame(_firstFrame, 0);
  161. }
  162. }
  163.  
  164. private async void ProcessSingleFrame(Mat frame, int frameNumber)
  165. {
  166. // Process and analyze the frame
  167. bool blinkDetected = false;
  168. string lastSegment = string.Empty;
  169. var (analyzedFrame, segmentDetected) = await Task.Run(() => AnalyzeFrame(frame, frameNumber, ref blinkDetected, ref lastSegment));
  170. if (analyzedFrame != null)
  171. {
  172. pictureBoxAnalyzed.Image = BitmapConverter.ToBitmap(analyzedFrame);
  173. labelStatus.Text = $"Segment detected in frame {frameNumber}.";
  174. }
  175. else
  176. {
  177. pictureBoxAnalyzed.Image = null; // Clear the PictureBox if no segments are detected
  178. labelStatus.Text = $"No segment detected in frame {frameNumber}.";
  179. }
  180. }
  181.  
  182. private async void ProcessFrame(object sender, EventArgs e)
  183. {
  184. using (var frame = new Mat())
  185. {
  186. if (_videoCapture.Read(frame))
  187. {
  188. // Update the ROI if tracking is enabled
  189. if (_tracking && _firstFrame != null)
  190. {
  191. _roi = UpdateROI(_firstFrame, frame, _roi);
  192. }
  193.  
  194. // Ensure ROI is within frame bounds
  195. _roi = EnsureROIWithinBounds(frame, _roi);
  196.  
  197. // Display each frame in pictureBoxFrame
  198. pictureBoxFrame.Image = BitmapConverter.ToBitmap(frame);
  199.  
  200. // Initialize blink detection and last segment variables
  201. bool blinkDetected = false;
  202. string lastSegment = string.Empty;
  203.  
  204. // Process and analyze the frame
  205. var (analyzedFrame, segmentDetected) = await Task.Run(() => AnalyzeFrame(frame, _currentFrame, ref blinkDetected, ref lastSegment));
  206. if (analyzedFrame != null)
  207. {
  208. pictureBoxAnalyzed.Image = BitmapConverter.ToBitmap(analyzedFrame);
  209. labelStatus.Text = $"Segment detected in frame {_currentFrame}.";
  210. }
  211. else
  212. {
  213. pictureBoxAnalyzed.Image = null; // Clear the PictureBox if no segments are detected
  214. labelStatus.Text = $"Processing frame {_currentFrame}/{_totalFrames}.";
  215. }
  216.  
  217. // Update progress
  218. _currentFrame++;
  219. progressBarAnalysis.Value = (int)((double)_currentFrame / _totalFrames * 100);
  220. labelStatus.Text = segmentDetected ? $"Segment detected in frame {_currentFrame}." : $"Processing frame {_currentFrame}/{_totalFrames}";
  221.  
  222. if (_currentFrame >= _totalFrames)
  223. {
  224. _timer.Stop();
  225. labelStatus.Text = "Analysis complete.";
  226. }
  227.  
  228. // Store the current frame as the previous frame for the next iteration
  229. _firstFrame = frame.Clone();
  230. }
  231. else
  232. {
  233. _timer.Stop();
  234. labelStatus.Text = "Error reading video file.";
  235. }
  236. }
  237. }
  238.  
  239. private (Mat, bool) AnalyzeFrame(Mat frame, int frameNumber, ref bool blinkDetected, ref string lastSegment)
  240. {
  241. // Ensure we have a valid ROI
  242. if (_roi.Width == 0 || _roi.Height == 0)
  243. return (null, false);
  244.  
  245. // Convert ROI to OpenCV Rect and crop the frame
  246. Rect rect = new Rect(_roi.X, _roi.Y, _roi.Width, _roi.Height);
  247. Mat roiFrame = new Mat(frame, rect);
  248.  
  249. // Convert ROI frame to grayscale
  250. Mat grayFrame = new Mat();
  251. Cv2.CvtColor(roiFrame, grayFrame, ColorConversionCodes.BGR2GRAY);
  252.  
  253. // Apply GaussianBlur
  254. Mat blurredFrame = new Mat();
  255. Cv2.GaussianBlur(grayFrame, blurredFrame, new Size(5, 5), 0);
  256.  
  257. // Apply Canny edge detection
  258. Mat canny = new Mat();
  259. Cv2.Canny(blurredFrame, canny, 50, 150);
  260.  
  261. // Apply morphological transformation
  262. Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));
  263. Mat closed = new Mat();
  264. Cv2.MorphologyEx(canny, closed, MorphTypes.Close, kernel);
  265.  
  266. // Find contours
  267. Point[][] contours;
  268. HierarchyIndex[] hierarchy;
  269. Cv2.FindContours(closed, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
  270.  
  271. bool segmentDetected = false;
  272.  
  273. foreach (var contour in contours)
  274. {
  275. double peri = Cv2.ArcLength(contour, true);
  276. var approx = Cv2.ApproxPolyDP(contour, 0.02 * peri, true);
  277. double area = Cv2.ContourArea(approx);
  278.  
  279. if (approx.Length == 4 && area > 1000)
  280. {
  281. Rect boundingRect = Cv2.BoundingRect(approx);
  282. Cv2.Rectangle(frame, boundingRect, new Scalar(36, 255, 12), 3);
  283. segmentDetected = true;
  284.  
  285. // Save the frame
  286. string filePath = $@"D:\DetectedFrames\frame_{frameNumber}.png";
  287. frame.SaveImage(filePath);
  288. }
  289. }
  290.  
  291. return segmentDetected ? (frame, true) : (null, false);
  292. }
  293.  
  294. private Rectangle UpdateROI(Mat previousFrame, Mat currentFrame, Rectangle roi)
  295. {
  296. // Convert frames to grayscale
  297. Mat prevGray = new Mat();
  298. Mat currGray = new Mat();
  299. Cv2.CvtColor(previousFrame, prevGray, ColorConversionCodes.BGR2GRAY);
  300. Cv2.CvtColor(currentFrame, currGray, ColorConversionCodes.BGR2GRAY);
  301.  
  302. // Define the points to track
  303. Point2f[] prevPts = {
  304. new Point2f(roi.Left, roi.Top),
  305. new Point2f(roi.Right, roi.Top),
  306. new Point2f(roi.Left, roi.Bottom),
  307. new Point2f(roi.Right, roi.Bottom)
  308. };
  309.  
  310. Point2f[] currPts = new Point2f[prevPts.Length];
  311.  
  312. // Track points using KLT tracker
  313. byte[] status;
  314. float[] err;
  315. Cv2.CalcOpticalFlowPyrLK(prevGray, currGray, prevPts, ref currPts, out status, out err);
  316.  
  317. // Calculate the movement
  318. if (status[0] == 1 && status[1] == 1 && status[2] == 1 && status[3] == 1)
  319. {
  320. 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;
  321. 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;
  322.  
  323. // Update the ROI position
  324. return new Rectangle((int)(roi.X + dx), (int)(roi.Y + dy), roi.Width, roi.Height);
  325. }
  326.  
  327. return roi;
  328. }
  329.  
  330. private Rectangle EnsureROIWithinBounds(Mat frame, Rectangle roi)
  331. {
  332. // Ensure the ROI does not go out of the frame bounds
  333. int x = Math.Max(roi.X, 0);
  334. int y = Math.Max(roi.Y, 0);
  335. int width = Math.Min(roi.Width, frame.Cols - x);
  336. int height = Math.Min(roi.Height, frame.Rows - y);
  337.  
  338. return new Rectangle(x, y, width, height);
  339. }
  340.  
  341. private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
  342. {
  343. _timer?.Stop();
  344. _videoCapture?.Release();
  345. }
  346.  
  347. private PictureBox pictureBoxFrame;
  348. private PictureBox pictureBoxAnalyzed;
  349. private ProgressBar progressBarAnalysis;
  350. private Label labelStatus;
  351. private Button buttonStart;
  352. private Button buttonTest;
  353.  
  354. private void Form1_Load(object sender, EventArgs e)
  355. {
  356.  
  357. }
  358. }
  359. }
Advertisement
Add Comment
Please, Sign In to add comment