Chocolade19721309

Untitled

Jun 13th, 2024
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.25 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Threading.Tasks;
  5. using System.Web;
  6. using System.Windows.Forms;
  7. using OpenCvSharp;
  8. using OpenCvSharp.Extensions;
  9. using Tesseract;
  10. using Bitmap = System.Drawing.Bitmap;
  11. using Rectangle = System.Drawing.Rectangle;
  12.  
  13. namespace VideoSegmentAnalyzer
  14. {
  15. public partial class Form1 : Form
  16. {
  17. private VideoCapture _videoCapture;
  18. private Timer _timer;
  19. private int _totalFrames;
  20. private int _currentFrame;
  21. private Rectangle _roiPicturebox; // To store the rectangle
  22. private System.Drawing.Point _rectangleStartPoint; // To store the start point of the rectangle
  23. private bool _drawing; // To indicate if we are currently drawing
  24. private bool _tracking; // To indicate if we are currently tracking
  25. private Mat _firstFrame; // To store the first frame for testing
  26. private List<System.Drawing.Point> _dotPoints = new List<System.Drawing.Point>();
  27. private bool _displayInBinary;
  28. private Mat frame;
  29.  
  30.  
  31. public Form1()
  32. {
  33. InitializeComponent();
  34.  
  35. InitializeComponents();
  36. InitializeVideoCapture();
  37. }
  38.  
  39. private void InitializeVideoCapture()
  40. {
  41. _videoCapture = new VideoCapture(@"D:\Csharp Projects\VideoSegmentAnalyzer\Videos\Video001.mp4");
  42. _totalFrames = _videoCapture.FrameCount;
  43.  
  44. // Configure the trackBarFrames
  45. trackBarFrames.Minimum = 0;
  46. trackBarFrames.Maximum = _totalFrames - 1;
  47. trackBarFrames.TickFrequency = 1;
  48. trackBarFrames.Value = 0;
  49. trackBarFrames.Scroll += TrackBarFrames_Scroll;
  50.  
  51. // Display the first frame for drawing the ROI
  52. _firstFrame = new Mat();
  53. if (_videoCapture.Read(_firstFrame))
  54. {
  55. Bitmap bitmap = BitmapConverter.ToBitmap(_firstFrame);
  56. UpdateControl(bitmap.Width, bitmap.Height);
  57. pictureBoxFrames.Image = bitmap;
  58. labelFrames.Text = $"Displaying frame 1/{_totalFrames}"; // Show 1 as the first frame
  59. }
  60.  
  61. _timer = new Timer();
  62. _timer.Interval = 30; // Adjust as needed
  63. _timer.Tick += ProcessFrame;
  64. }
  65.  
  66. private void TrackBarFrames_Scroll(object sender, EventArgs e)
  67. {
  68. _currentFrame = trackBarFrames.Value;
  69. _videoCapture.Set(VideoCaptureProperties.PosFrames, _currentFrame);
  70.  
  71. Mat frame = new Mat();
  72. if (_videoCapture.Read(frame))
  73. {
  74. pictureBoxFrames.Image = BitmapConverter.ToBitmap(frame);
  75. labelFrames.Text = $"Displaying frame {_currentFrame + 1}/{_totalFrames}"; // Add 1 to display the frame number starting from 1
  76. }
  77. }
  78.  
  79. private void ButtonStart_Click(object sender, EventArgs e)
  80. {
  81. if (_roiPicturebox.Width == 0 || _roiPicturebox.Height == 0)
  82. {
  83. MessageBox.Show("Please draw a rectangle to define the ROI.");
  84. return;
  85. }
  86.  
  87. _currentFrame = 0;
  88. progressBarAnalysis.Value = 0;
  89. labelStatus.Text = "Starting analysis...";
  90. _timer.Start();
  91. }
  92.  
  93. private void ButtonTest_Click(object sender, EventArgs e)
  94. {
  95. if (_roiPicturebox.Width == 0 || _roiPicturebox.Height == 0)
  96. {
  97. MessageBox.Show("Please draw a rectangle to define the ROI.");
  98. return;
  99. }
  100.  
  101. int frameNumber = trackBarFrames.Value;
  102. _videoCapture.Set(VideoCaptureProperties.PosFrames, frameNumber);
  103.  
  104. Mat frame = new Mat();
  105. if (_videoCapture.Read(frame))
  106. {
  107. ProcessSingleFrame(frame, frameNumber);
  108. }
  109. else
  110. {
  111. MessageBox.Show("Failed to read the frame at the current trackbar position.");
  112. }
  113. }
  114.  
  115. private async void ProcessSingleFrame(Mat frame, int frameNumber)
  116. {
  117. // Process and analyze the frame
  118. (Mat analyzedFrame, bool segmentDetected, bool blinkDetected) = await Task.Run(() => AnalyzeFrame(frame, frameNumber));
  119. if (analyzedFrame != null)
  120. {
  121. pictureBoxPoints.Image = BitmapConverter.ToBitmap(analyzedFrame);
  122. labelStatus.Text = $"Segment detected in frame {frameNumber}.";
  123. }
  124. else
  125. {
  126. //pictureBoxAnalyzed.Image = null; // Clear the PictureBox if no segments are detected
  127. labelStatus.Text = $"No segment detected in frame {frameNumber}.";
  128. }
  129. }
  130.  
  131. private async void ProcessFrame(object sender, EventArgs e)
  132. {
  133. using (Mat frame = new Mat())
  134. {
  135. if (_videoCapture.Read(frame))
  136. {
  137. // Update the ROI if tracking is enabled
  138. if (_tracking && _firstFrame != null)
  139. {
  140. _roiPicturebox = UpdateROI(_firstFrame, frame, _roiPicturebox);
  141. }
  142.  
  143. // Ensure ROI is within frame bounds
  144. _roiPicturebox = EnsureROIWithinBounds(frame, _roiPicturebox);
  145.  
  146. // Display each frame in pictureBoxFrame
  147. pictureBoxFrames.Image = BitmapConverter.ToBitmap(frame);
  148.  
  149. // Process and analyze the frame
  150. (Mat analyzedFrame, bool segmentDetected, bool blinkDetected) = await Task.Run(() => AnalyzeFrame(frame, _currentFrame));
  151. if (analyzedFrame != null)
  152. {
  153. pictureBoxPoints.Image = BitmapConverter.ToBitmap(analyzedFrame);
  154. labelStatus.Text = $"Segment detected in frame {_currentFrame}.";
  155. }
  156. else
  157. {
  158. pictureBoxPoints.Image = null; // Clear the PictureBox if no segments are detected
  159. labelStatus.Text = $"Processing frame {_currentFrame}/{_totalFrames}.";
  160. }
  161.  
  162. // Update progress
  163. _currentFrame++;
  164. progressBarAnalysis.Value = (int)((double)_currentFrame / _totalFrames * 100);
  165. labelStatus.Text = segmentDetected ? $"Segment detected in frame {_currentFrame}." : $"Processing frame {_currentFrame}/{_totalFrames}";
  166.  
  167. if (_currentFrame >= _totalFrames)
  168. {
  169. _timer.Stop();
  170. labelStatus.Text = "Analysis complete.";
  171. }
  172.  
  173. // Store the current frame as the previous frame for the next iteration
  174. _firstFrame = frame.Clone();
  175. }
  176. else
  177. {
  178. _timer.Stop();
  179. labelStatus.Text = "Error reading video file.";
  180. }
  181. }
  182. }
  183.  
  184. private (Mat frameMat, bool segmentDetected, bool blinkDetected) AnalyzeFrame(Mat frame, int frameNumber)
  185. {
  186. this.frame = frame;
  187.  
  188. bool blinkDetected = false;
  189.  
  190. // Ensure we have a valid ROI
  191. if (_roiPicturebox.Width == 0 || _roiPicturebox.Height == 0)
  192. return (null, false, blinkDetected);
  193.  
  194. double xFactor = (double)frame.Width / pictureBoxFrames.Width;
  195. double yFactor = (double)frame.Height / pictureBoxFrames.Height;
  196.  
  197. // Convert ROI to OpenCV Rect and crop the frame
  198. OpenCvSharp.Rect rect = new OpenCvSharp.Rect(
  199. (int)(_roiPicturebox.X * xFactor),
  200. (int)(_roiPicturebox.Y * yFactor),
  201. (int)(_roiPicturebox.Width * xFactor),
  202. (int)(_roiPicturebox.Height * yFactor)
  203. );
  204. Mat roiFrame = new Mat(frame, rect);
  205.  
  206. // Convert ROI frame to grayscale for analysis
  207. Mat analysisFrame = new Mat();
  208. Cv2.CvtColor(roiFrame, analysisFrame, ColorConversionCodes.BGR2GRAY);
  209.  
  210. // Convert Mat to Bitmap for binary threshold analysis
  211. Mat binaryFrame = new Mat();
  212. Cv2.Threshold(analysisFrame, binaryFrame, 180, 255, ThresholdTypes.Binary);
  213.  
  214. // Display the ROI frame based on the selected display mode
  215. if (!_displayInBinary)
  216. {
  217. // Display the ROI frame in black & white (binary)
  218. pictureBoxPoints.Image = BitmapConverter.ToBitmap(binaryFrame);
  219. }
  220. else
  221. {
  222. // Display the ROI frame in color
  223. pictureBoxPoints.Image = BitmapConverter.ToBitmap(roiFrame);
  224. }
  225.  
  226. // Find contours
  227. OpenCvSharp.Point[][] contours;
  228. HierarchyIndex[] hierarchy;
  229. Cv2.FindContours(binaryFrame, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
  230.  
  231. // Detect if the display is blank (blink)
  232. if (contours.Length == 0)
  233. {
  234. blinkDetected = true;
  235. }
  236.  
  237. return (null, false, blinkDetected);
  238. }
  239.  
  240. private Rectangle UpdateROI(Mat previousFrame, Mat currentFrame, Rectangle roi)
  241. {
  242. // Convert frames to grayscale
  243. Mat prevGray = new Mat();
  244. Mat currGray = new Mat();
  245. Cv2.CvtColor(previousFrame, prevGray, ColorConversionCodes.BGR2GRAY);
  246. Cv2.CvtColor(currentFrame, currGray, ColorConversionCodes.BGR2GRAY);
  247.  
  248. // Define the points to track
  249. OpenCvSharp.Point2f[] prevPts = {
  250. new OpenCvSharp.Point2f(roi.Left, roi.Top),
  251. new OpenCvSharp.Point2f(roi.Right, roi.Top),
  252. new OpenCvSharp.Point2f(roi.Left, roi.Bottom),
  253. new OpenCvSharp.Point2f(roi.Right, roi.Bottom)
  254. };
  255.  
  256. OpenCvSharp.Point2f[] currPts = new OpenCvSharp.Point2f[prevPts.Length];
  257.  
  258. // Track points using KLT tracker
  259. byte[] status;
  260. float[] err;
  261. Cv2.CalcOpticalFlowPyrLK(prevGray, currGray, prevPts, ref currPts, out status, out err);
  262.  
  263. // Calculate the movement
  264. if (status[0] == 1 && status[1] == 1 && status[2] == 1 && status[3] == 1)
  265. {
  266. 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;
  267. 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;
  268.  
  269. // Update the ROI position
  270. return new Rectangle((int)(roi.X + dx), (int)(roi.Y + dy), roi.Width, roi.Height);
  271. }
  272.  
  273. return roi;
  274. }
  275.  
  276. private Rectangle EnsureROIWithinBounds(Mat frame, Rectangle roi)
  277. {
  278. // Ensure the ROI does not go out of the frame bounds
  279. int x = Math.Max(roi.X, 0);
  280. int y = Math.Max(roi.Y, 0);
  281. int width = Math.Min(roi.Width, frame.Cols - x);
  282. int height = Math.Min(roi.Height, frame.Rows - y);
  283.  
  284. return new Rectangle(x, y, width, height);
  285. }
  286.  
  287. #region UI Components and Initialization
  288.  
  289. private void InitializeComponents()
  290. {
  291. radioButtonColorThreshold.Checked = true;
  292. }
  293.  
  294. private void UpdateControl(int videoWidth, int videoHeight)
  295. {
  296. int height = 640;
  297. int width = height * videoWidth / videoHeight;
  298. int gap = 20;
  299. }
  300. #endregion
  301.  
  302. #region PictureBoxPoints Events
  303. private void PictureBoxPoints_MouseDown(object sender, MouseEventArgs e)
  304. {
  305. if (e.Button == MouseButtons.Left && pictureBoxPoints.Image != null)
  306. {
  307. if (frame != null)
  308. {
  309. // Calculate the image coordinates based on the mouse position
  310. double xFactor = (double)frame.Width / pictureBoxFrames.Width;
  311. double yFactor = (double)frame.Height / pictureBoxFrames.Height;
  312.  
  313. // Adjust for Zoom mode: Get the actual displayed image size
  314. int displayedImageWidth = pictureBoxPoints.ClientSize.Width;
  315. int displayedImageHeight = pictureBoxPoints.ClientSize.Height;
  316.  
  317. int imageX = (int)(e.Location.X * xFactor);
  318. int imageY = (int)(e.Location.Y * yFactor);
  319.  
  320. // Now 'imageX' and 'imageY' contain the corresponding image coordinates
  321. // You can use these values for further processing
  322.  
  323. _dotPoints.Add(new System.Drawing.Point(imageX, imageY));
  324. pictureBoxPoints.Invalidate();
  325. }
  326. }
  327. }
  328.  
  329. private void PictureBoxPoints_Paint(object sender, PaintEventArgs e)
  330. {
  331. foreach (System.Drawing.Point point in _dotPoints)
  332. {
  333. int ellipseWidth = 10;
  334. int ellipseHeight = 10;
  335. int ellipseX = point.X - ellipseWidth / 2;
  336. int ellipseY = point.Y - ellipseHeight / 2;
  337.  
  338. e.Graphics.FillEllipse(Brushes.Red, new Rectangle(ellipseX, ellipseY, ellipseWidth, ellipseHeight));
  339. }
  340. }
  341.  
  342. private void PictureBoxAnalyzed_Paint(object sender, PaintEventArgs e)
  343. {
  344.  
  345. }
  346. #endregion
  347.  
  348. private void RadioButtonThreshold_CheckedChanged(object sender, EventArgs e)
  349. {
  350. if (radioButtonGrayThreshold.Checked)
  351. {
  352. _displayInBinary = false;
  353. }
  354. else if (radioButtonColorThreshold.Checked)
  355. {
  356. _displayInBinary = true;
  357. }
  358.  
  359. // Optionally reprocess the current frame to reflect the change immediately
  360. if (_videoCapture != null && _currentFrame < _totalFrames)
  361. {
  362. Mat frame = new Mat();
  363. _videoCapture.Set(VideoCaptureProperties.PosFrames, _currentFrame);
  364. if (_videoCapture.Read(frame))
  365. {
  366. ProcessSingleFrame(frame, _currentFrame);
  367. }
  368. }
  369. }
  370.  
  371. private void Form1_Load(object sender, EventArgs e)
  372. {
  373.  
  374. }
  375.  
  376. private void pictureBoxFrames_MouseDown(object sender, MouseEventArgs e)
  377. {
  378. _tracking = false;
  379.  
  380. if (!_tracking)
  381. {
  382. _rectangleStartPoint = e.Location;
  383. _roiPicturebox = Rectangle.Empty; // Clear the existing rectangle
  384. pictureBoxFrames.Invalidate(); // Trigger repaint to clear the previous rectangle
  385. _drawing = true;
  386. }
  387. }
  388.  
  389. private void pictureBoxFrames_MouseMove(object sender, MouseEventArgs e)
  390. {
  391. if (_drawing && pictureBoxFrames.Image != null)
  392. {
  393. System.Drawing.Point endPoint = e.Location;
  394. _roiPicturebox = new Rectangle(Math.Min(_rectangleStartPoint.X, endPoint.X),
  395. Math.Min(_rectangleStartPoint.Y, endPoint.Y),
  396. Math.Abs(_rectangleStartPoint.X - endPoint.X),
  397. Math.Abs(_rectangleStartPoint.Y - endPoint.Y));
  398. pictureBoxFrames.Invalidate(); // Trigger repaint
  399. }
  400. }
  401.  
  402. private void pictureBoxFrames_MouseUp(object sender, MouseEventArgs e)
  403. {
  404. _drawing = false;
  405. _tracking = true;
  406. }
  407.  
  408. private void pictureBoxFrames_Paint(object sender, PaintEventArgs e)
  409. {
  410. if (_roiPicturebox != Rectangle.Empty)
  411. {
  412. e.Graphics.DrawRectangle(Pens.Red, _roiPicturebox);
  413. }
  414. }
  415.  
  416. private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  417. {
  418.  
  419. }
  420. }
  421. }
Advertisement
Add Comment
Please, Sign In to add comment