Advertisement
Guest User

Untitled

a guest
Dec 15th, 2019
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 55.01 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Windows.Forms;
  6. using Emgu.CV;
  7. using Emgu.CV.Structure;
  8. using Emgu.CV.CvEnum;
  9. using System.Diagnostics;
  10. using System.Threading;
  11.  
  12.  
  13. namespace WindowsFormsApp2
  14. {
  15.     public partial class Form1 : Form
  16.     {
  17.         // -----------------------
  18.         // Dichiarazione variabili
  19.         // -----------------------
  20.  
  21.         private static int trackBar1_last_value;
  22.        
  23.         public static Mat video_output = Mat.Zeros(video_edit.rows, video_edit.cols, DepthType.Cv8U, 3);
  24.         public static Mat[] roi_mask = new Mat[3];
  25.  
  26.         public static bool running = false;
  27.         public static bool[] roi_selected = { false, false, false };
  28.         public static bool image_clicked = false;
  29.         public static bool detection_view = false;
  30.         public static bool eof = false;
  31.  
  32.         public static int fps = 30;
  33.         public static int mouseX, mouseY;
  34.         public static int light_threshold = 1;
  35.         public static int max_fps = 100;
  36.         public static int roi_selection = -1;
  37.         public static int tired_threshold;
  38.         public static int[] fish_x = { -1, -1, -1 };
  39.  
  40.         public static float tired_threshold_float;
  41.  
  42.         public static double inter_frame_time = (double)1 / (double)fps;
  43.         public static double width_coeff, height_coeff;
  44.         public static double detection_balance;
  45.         public static double[] tired_timer = { 0, 0, 0 };
  46.  
  47.         public static Point roi_corner_1, roi_corner_2;
  48.         public static Point tired_point_top, tired_point_bot;
  49.        
  50.         public static Rectangle[] roi_area = new Rectangle[3];
  51.  
  52.         MCvScalar[] rect_color = new MCvScalar[3] { new MCvScalar(255, 0, 0), new MCvScalar(0, 255, 0), new MCvScalar(0, 0, 255) };
  53.        
  54.         OpenFileDialog input_file_browser = new OpenFileDialog();
  55.         FolderBrowserDialog save_folder_browser = new FolderBrowserDialog();
  56.  
  57.         DialogResult browse_input_file_result = DialogResult.None;
  58.         DialogResult browse_save_folder_result = DialogResult.None;
  59.  
  60.         // ---------------------
  61.         // Inizializzazione Form
  62.         // ---------------------
  63.         public Form1()
  64.         {
  65.             InitializeComponent();
  66.         }
  67.  
  68.         // ---------------------------------------------
  69.         // Caricamento Form e inizializzazione variabili
  70.         // ---------------------------------------------
  71.         private void Form1_Load(object sender, EventArgs e)
  72.         {
  73.            
  74.             // Avvio il metodo di detection in un nuovo thread
  75.             Thread main_loop_thread = new Thread(video_edit.fish_detection);
  76.             main_loop_thread.IsBackground = true;
  77.             main_loop_thread.Start();
  78.  
  79.             // Istanzio gli eventi mouseclick legati alla selezione delle ROI
  80.             imageBox1.MouseMove += new MouseEventHandler(imageBox1_MouseMove);
  81.             imageBox1.MouseDown += new MouseEventHandler(imageBox1_MouseDown);
  82.             imageBox1.MouseUp += new MouseEventHandler(imageBox1_MouseUp);
  83.  
  84.             // Inizializzo le variabile che definiscono la qualità dell'immagine
  85.             video_edit.resize_scale = ((double)trackBar1.Value / (double)10);
  86.             trackBar1_last_value = trackBar1.Value;
  87.  
  88.             // Inizializzo le variabili che definiscono dimensione e posizione della Linea dei Pesci Stanchi (LPS)
  89.             tired_threshold_float = (float)trackBar3.Value / (float)1000;
  90.             tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
  91.             tired_point_top = new Point(tired_threshold, 0);
  92.             tired_point_bot = new Point(tired_threshold, video_edit.rows);
  93.             label6.Text = (trackBar3.Value / 10).ToString() + "%";
  94.  
  95.             // Avvio il timer che comunica con il software di controllo circolatore
  96.             timer2.Enabled = true;  
  97.            
  98.         }
  99.  
  100.         // -------------------------------------------
  101.         // Evento di movimento del mouse sull'immagine
  102.         // -------------------------------------------
  103.         private void imageBox1_MouseMove(object sender, MouseEventArgs e)
  104.         {
  105.             // Salvo la posizione del mouse durante la selezione della ROI
  106.             if (roi_selection >= 0)
  107.             {
  108.                 mouseX = (int)(width_coeff * e.X);
  109.                 mouseY = (int)(height_coeff * e.Y);
  110.             }
  111.         }
  112.  
  113.         // ------------
  114.         // Modifica FPS
  115.         // ------------
  116.         private void numericUpDown1_ValueChanged(object sender, EventArgs e)
  117.         {
  118.             // Modifico le variabili legate agli FPS quando varia il controllo relativo
  119.             fps = (int)numericUpDown1.Value;
  120.             inter_frame_time = (double)1 / (double)fps;
  121.         }
  122.  
  123.         // --------------
  124.         // Pulsante Start
  125.         // --------------
  126.         private void button1_Click(object sender, EventArgs e)
  127.         {
  128.             int i;
  129.  
  130.             // Switch tra Start e Stop
  131.             if (button1.Text == "Start")
  132.             {
  133.                 button1.Text = "Stop";
  134.  
  135.                 // Avvio il ciclo di processing presente nel thread di fish_detection
  136.                 running = true;
  137.  
  138.                 // Disabilito i controlli che non devono essere toccati durante il ciclo di processing
  139.                 trackBar1.Enabled = false;
  140.  
  141.                 button2.Enabled = false;
  142.                 button3.Enabled = false;
  143.                 button4.Enabled = false;
  144.  
  145.                 button10.Enabled = false;
  146.                 button11.Enabled = false;
  147.                 button12.Enabled = false;
  148.  
  149.                 button13.Enabled = false;
  150.  
  151.                 numericUpDown3.Enabled = false;
  152.             }
  153.             else
  154.             {
  155.                 button1.Text = "Start";
  156.  
  157.                 // Fermo il ciclo di processing
  158.                 running = false;
  159.  
  160.                 // Abilito i controlli che modificano i parametri di cattura
  161.                 trackBar1.Enabled = true;
  162.  
  163.                 button2.Enabled = true;
  164.                 button3.Enabled = true;
  165.                 button4.Enabled = true;
  166.  
  167.                 if (roi_selected[0])
  168.                     button10.Enabled = true;
  169.                 if (roi_selected[1])
  170.                     button11.Enabled = true;
  171.                 if (roi_selected[2])
  172.                     button12.Enabled = true;
  173.  
  174.                 button13.Enabled = true;
  175.  
  176.                 numericUpDown3.Enabled = true;
  177.  
  178.  
  179.                 // Aggiorno posizione e dimensione della LPS
  180.                 tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
  181.                 tired_point_top = new Point(tired_threshold, 0);
  182.                 tired_point_bot = new Point(tired_threshold, video_edit.rows);
  183.  
  184.                 refresh_video_size_form();
  185.  
  186.                 // Disegno ROI e LPS sul frame corrente
  187.                 video_edit.draw_rois(/* ROI */true, /* LPS */true);
  188.             }
  189.  
  190.             // Ridefinisco le maschere delle ROI in cui vengono individuati i singoli pesci
  191.             for (i = 0; i < 3; i++)
  192.             {
  193.                 roi_mask[i] = Mat.Zeros(video_edit.rows, video_edit.cols, DepthType.Cv8U, 1);
  194.                 CvInvoke.Rectangle(roi_mask[i], roi_area[i], new MCvScalar(255), -1);
  195.             }
  196.         }
  197.  
  198.         // -------------------
  199.         // Selezione prima ROI
  200.         // -------------------
  201.         private void button2_Click(object sender, EventArgs e)
  202.         {
  203.             // Switch tra selezione e conferma
  204.             if (button2.Text == "Area 1")
  205.             {
  206.                 // Aggiorno variabili che definiscono la ROI in selezione
  207.                 roi_selected[0] = false;
  208.                 roi_selection = 0;
  209.  
  210.                 // Disabilito controlli inappropriati
  211.                 button1.Enabled = false;
  212.                 button3.Enabled = false;
  213.                 button4.Enabled = false;
  214.  
  215.                 trackBar1.Enabled = false;
  216.                 // ----------------------------------
  217.  
  218.                 button2.Text = "Confirm";
  219.  
  220.                 refresh_video_size_form();
  221.  
  222.                 // Avvio il metodo di impostazione della ROI in un nuovo thread
  223.                 Thread roi_thread = new Thread(video_edit.set_roi);
  224.                 roi_thread.Start();
  225.             }
  226.             else
  227.             {
  228.                 // Aggiorno variabili che definiscono la ROI in selezione
  229.                 roi_selected[0] = true;
  230.                 roi_selection = -1;
  231.                 image_clicked = false;
  232.  
  233.                 // Abilito controlli
  234.                 button1.Enabled = true;
  235.                 button3.Enabled = true;
  236.                 button4.Enabled = true;
  237.  
  238.                 button10.Enabled = true;
  239.                 trackBar1.Enabled = true;
  240.                 // -----------------
  241.  
  242.                 button2.Text = "Area 1";
  243.             }
  244.         }
  245.  
  246.         // ---------------------
  247.         // Selezione seconda ROI
  248.         // ---------------------
  249.  
  250.         // Funziona come la prima
  251.         private void button3_Click(object sender, EventArgs e)
  252.         {
  253.             if (button3.Text == "Area 2")
  254.             {
  255.                 roi_selected[1] = false;
  256.                 roi_selection = 1;
  257.  
  258.                 button1.Enabled = false;
  259.                 button2.Enabled = false;
  260.                 button4.Enabled = false;
  261.  
  262.                 trackBar1.Enabled = false;
  263.  
  264.                 button3.Text = "Confirm";
  265.  
  266.                 refresh_video_size_form();
  267.  
  268.                 Thread roi_thread = new Thread(video_edit.set_roi);
  269.                 roi_thread.Start();
  270.             }
  271.             else
  272.             {
  273.                 roi_selected[1] = true;
  274.                 roi_selection = -1;
  275.                 image_clicked = false;
  276.  
  277.                 button1.Enabled = true;
  278.                 button2.Enabled = true;
  279.                 button4.Enabled = true;
  280.  
  281.                 button11.Enabled = true;
  282.                 trackBar1.Enabled = true;
  283.  
  284.                 button3.Text = "Area 2";
  285.             }
  286.         }
  287.  
  288.         // -------------------
  289.         // Selezione terza ROI
  290.         // -------------------
  291.  
  292.         // Funziona come la prima
  293.         private void button4_Click(object sender, EventArgs e)
  294.         {
  295.             if (button4.Text == "Area 3")
  296.             {
  297.                 roi_selected[2] = false;
  298.                 roi_selection = 2;
  299.  
  300.                 button1.Enabled = false;
  301.                 button2.Enabled = false;
  302.                 button3.Enabled = false;
  303.  
  304.                 trackBar1.Enabled = false;
  305.  
  306.                 button4.Text = "Confirm";
  307.  
  308.                 refresh_video_size_form();
  309.  
  310.                 Thread roi_thread = new Thread(video_edit.set_roi);
  311.                 roi_thread.Start();
  312.             }
  313.             else
  314.             {
  315.                 roi_selected[2] = true;
  316.                 roi_selection = -1;
  317.                 image_clicked = false;
  318.  
  319.                 button1.Enabled = true;
  320.                 button2.Enabled = true;
  321.                 button3.Enabled = true;
  322.  
  323.                 button12.Enabled = true;
  324.                 trackBar1.Enabled = true;
  325.  
  326.                 button4.Text = "Area 3";
  327.             }
  328.         }
  329.  
  330.         // ------------------------------------------
  331.         // Evento MouseDown sull'immagine della vasca
  332.         // ------------------------------------------
  333.         private void imageBox1_MouseDown(object sender, MouseEventArgs e)
  334.         {
  335.             image_clicked = true;
  336.  
  337.             // Definisco il primo angolo della ROI
  338.             roi_corner_1 = new Point(((int)(width_coeff * (double)e.X)), ((int)(height_coeff * (double)e.Y)));
  339.         }
  340.  
  341.         // ---------------------------------------------
  342.         // Trackbar che definisce la posizione della LPS
  343.         // ---------------------------------------------
  344.         private void trackBar3_Scroll(object sender, EventArgs e)
  345.         {
  346.             // Aggiorno le variabili che definiscono la LPS
  347.             tired_threshold_float = (float)trackBar3.Value / (float)1000;
  348.             tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
  349.             tired_point_top = new Point(tired_threshold, 0);
  350.             tired_point_bot = new Point(tired_threshold, video_edit.rows);
  351.  
  352.             label6.Text = (trackBar3.Value / 10).ToString() + "%";
  353.  
  354.             refresh_video_size_form();
  355.  
  356.             // Disegno ROI e LPS sul frame corrente
  357.             if(!running)
  358.                 video_edit.draw_rois(true, true);
  359.         }
  360.  
  361.         // -----------------------------------
  362.         // Bottone di salvataggio dati su file
  363.         // -----------------------------------
  364.         private void button5_Click(object sender, EventArgs e)
  365.         {
  366.             int i, list_size;
  367.             list_size = video_edit.data_list.Count;
  368.             string data_string, full_path;
  369.  
  370.             // Recupero la cartella di salvataggio dalla variabile di selezione cartella
  371.             string folder = save_folder_browser.SelectedPath;
  372.  
  373.             // Controllo la validità del percorso, se si salva nella cartella principale di un disco la barra "\" è già presente
  374.             if(folder.Length == 3)
  375.                 full_path = folder + textBox1.Text;
  376.             else
  377.                 full_path = folder + "\\" + textBox1.Text;
  378.  
  379.  
  380.             // Apro il file di salvataggio
  381.             StreamWriter file_stream = File.CreateText(full_path);
  382.  
  383.             file_stream.WriteLine("Index\tTime\tThr\tPos 1\tPos 2\tPos 3\tTime 1\tTime 2\tTime 3");
  384.  
  385.             // Salvo i dati contenuti in data_list, variabile riempita in fish_detection
  386.             for (i = 0; i < list_size; i++)
  387.             {
  388.                 data_string = video_edit.data_list[i].index.ToString() + "\t" +
  389.                                 video_edit.data_list[i].time.ToString() + "\t" +
  390.                                 video_edit.data_list[i].thresh.ToString() + "\t" +
  391.                                 video_edit.data_list[i].pos_1.ToString("0.000") + "\t" +
  392.                                 video_edit.data_list[i].pos_2.ToString("0.000") + "\t" +
  393.                                 video_edit.data_list[i].pos_3.ToString("0.000") + "\t" +
  394.                                 video_edit.data_list[i].time_1.ToString("0.000") + "\t" +
  395.                                 video_edit.data_list[i].time_2.ToString("0.000") + "\t" +
  396.                                 video_edit.data_list[i].time_3.ToString("0.000");
  397.  
  398.  
  399.                 file_stream.WriteLine(data_string);
  400.             }
  401.  
  402.             file_stream.Close();
  403.  
  404.             MessageBox.Show("File succesfully saved in " + full_path, "Save complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
  405.         }
  406.  
  407.         // ----------------------------------------
  408.         // Bottone di selezione nuovo file di input
  409.         // ----------------------------------------
  410.         private void button6_Click(object sender, EventArgs e)
  411.         {
  412.             timer1.Stop();
  413.             Thread.Sleep(100);
  414.  
  415.             // Apro il browser dialog per selezionare il file
  416.             browse_input_file_result = input_file_browser.ShowDialog();
  417.  
  418.             // Controllo che il file sia stato selezionato
  419.             if(browse_input_file_result == DialogResult.OK)
  420.             {
  421.                 // Chiamo il metodo che cambia il file di input
  422.                 video_edit.change_input_file(input_file_browser.FileName);
  423.                 // Aggiorno le dimensioni salvate
  424.                 refresh_video_size_form();
  425.  
  426.                 // Aggiorno LPS
  427.                 tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
  428.                 tired_point_top = new Point(tired_threshold, 0);
  429.                 tired_point_bot = new Point(tired_threshold, video_edit.rows);
  430.  
  431.                 // Elimino le ROI precedenti
  432.                 button10.PerformClick();
  433.                 button11.PerformClick();
  434.                 button12.PerformClick();
  435.  
  436.                 // Azzero il tempo passato oltre la linea per ogni pesce
  437.                 tired_timer[0] = 0;
  438.                 tired_timer[1] = 0;
  439.                 tired_timer[2] = 0;
  440.  
  441.                 // Disegno LPS sul frame corrente
  442.                 video_edit.draw_rois(false, true);
  443.  
  444.                 // Abilito controlli di selezione ROI
  445.                 button2.Enabled = true;
  446.                 button3.Enabled = true;
  447.                 button4.Enabled = true;
  448.  
  449.                 // Abilito trackbar qualità
  450.                 trackBar1.Enabled = true;
  451.  
  452.                 // Gestisco un riavvio dovuto alla discesa a 0 FPS per detection troppo lenta
  453.                 if (max_fps == 0)
  454.                 {
  455.                     max_fps = 1;
  456.                     numericUpDown1.Maximum = max_fps;
  457.                     numericUpDown1.Value = numericUpDown1.Maximum;
  458.                 }
  459.  
  460.                 timer1.Start();
  461.  
  462.                 label6.Text = (trackBar3.Value / 10).ToString() + "%";
  463.             }
  464.         }
  465.  
  466.         // ---------------------------------------
  467.         // Bottone di selezione nuovo stream video
  468.         // ---------------------------------------
  469.         private void button9_Click(object sender, EventArgs e)
  470.         {
  471.             // Apro stream di prova per vedere se la videocamera funziona
  472.             VideoCapture input_stream = new VideoCapture((int)numericUpDown2.Value - 1);
  473.  
  474.             timer1.Stop();
  475.             Thread.Sleep(100);
  476.             // Controllo che lo stream di prova sia aperto
  477.             if (input_stream.IsOpened)
  478.             {
  479.                 // Chiudo stream di prova
  480.                 input_stream.Dispose();
  481.  
  482.                 // Chiamo il metodo che cambia stream di input
  483.                 video_edit.change_input_stream((int)numericUpDown2.Value - 1);
  484.                 // Aggiorno le dimensioni salvate
  485.                 refresh_video_size_form();
  486.  
  487.                 // Aggiorno LPS
  488.                 tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
  489.                 tired_point_top = new Point(tired_threshold, 0);
  490.                 tired_point_bot = new Point(tired_threshold, video_edit.rows);
  491.  
  492.                 // Elimino ROI
  493.                 button10.PerformClick();
  494.                 button11.PerformClick();
  495.                 button12.PerformClick();
  496.  
  497.                 // Azzero tempi passati oltre la linea per ogni pesce
  498.                 tired_timer[0] = 0;
  499.                 tired_timer[1] = 0;
  500.                 tired_timer[2] = 0;
  501.  
  502.                 // Disegno LPS
  503.                 video_edit.draw_rois(false, true);
  504.  
  505.                 // Abilito controlli di selezione ROi
  506.                 button2.Enabled = true;
  507.                 button3.Enabled = true;
  508.                 button4.Enabled = true;
  509.  
  510.                 // Abilito trackbar qualità
  511.                 trackBar1.Enabled = true;
  512.  
  513.                 // Gestisco un riavvio dovuto alla discesa a 0 FPS per detection troppo lenta
  514.                 if (max_fps == 0)
  515.                 {
  516.                     max_fps = 1;
  517.                     numericUpDown1.Maximum = max_fps;
  518.                     numericUpDown1.Value = numericUpDown1.Maximum;
  519.                 }
  520.  
  521.                 timer1.Start();
  522.  
  523.                 label6.Text = (trackBar3.Value / 10).ToString() + "%";
  524.             }
  525.         }
  526.  
  527.         // ----------------------------------------------
  528.         // Bottone di selezione cartella salvataggio dati
  529.         // ----------------------------------------------
  530.         private void button7_Click(object sender, EventArgs e)
  531.         {
  532.             // Scelgo la cartella
  533.             browse_save_folder_result = save_folder_browser.ShowDialog();
  534.  
  535.             // Controllo che il nome del file sia valido
  536.             bool name_valid = !string.IsNullOrEmpty(textBox1.Text) && textBox1.Text.IndexOfAny(Path.GetInvalidFileNameChars()) < 0;
  537.  
  538.             if ((browse_save_folder_result == DialogResult.OK) && name_valid)
  539.             {
  540.                 // Abilito il bottone di salvataggio se il percorso è valido
  541.                 button5.Enabled = true;
  542.             }
  543.             else
  544.             {
  545.                 // Disabilito il salvataggio se il percorso non è valido
  546.                 button5.Enabled = false;
  547.             }
  548.         }
  549.  
  550.         // ---------------------------------------------------
  551.         // Bottone di controllo numero videocamere disponibili
  552.         // ---------------------------------------------------
  553.         private void button8_Click(object sender, EventArgs e)
  554.         {
  555.             int i = 0;
  556.             VideoCapture test_stream = new VideoCapture(0);
  557.  
  558.             // Provo ad aprire le videocamere una per una
  559.             while (test_stream.IsOpened)
  560.             {
  561.                 test_stream.Dispose();
  562.                 test_stream = new VideoCapture(i++);
  563.             }
  564.  
  565.             test_stream.Dispose();
  566.  
  567.             // Rendo disponibili le videocamere rilevate
  568.             if (i == 0)
  569.             {
  570.                 MessageBox.Show("No cameras available");
  571.                 label2.Text = "Max: 0";
  572.                 numericUpDown2.Enabled = false;
  573.                 button9.Enabled = false;
  574.             }
  575.             else
  576.             {
  577.                 numericUpDown2.Enabled = true;
  578.                 numericUpDown2.Maximum = i;
  579.                 button9.Enabled = true;
  580.                 label2.Text = "Max: " + i.ToString();
  581.             }
  582.         }
  583.  
  584.         // -----------------------------
  585.         // CheckBox input da videocamera
  586.         // -----------------------------
  587.         private void checkBox4_CheckedChanged(object sender, EventArgs e)
  588.         {
  589.             // Rendo mutualmente esclusive le checkbox di videocamera e file
  590.             if ((checkBox4.CheckState == CheckState.Unchecked) && (checkBox3.CheckState == CheckState.Unchecked))
  591.             {
  592.                 checkBox3.CheckState = CheckState.Checked;
  593.                 button6.Enabled = true;
  594.                 button8.Enabled = false;
  595.             }
  596.             if ((checkBox4.CheckState == CheckState.Checked) && (checkBox3.CheckState == CheckState.Checked))
  597.             {
  598.                 checkBox3.CheckState = CheckState.Unchecked;
  599.                 button6.Enabled = false;
  600.                 button8.Enabled = true;
  601.             }
  602.  
  603.             // Elimino ROI
  604.             button10.PerformClick();
  605.             button11.PerformClick();
  606.             button12.PerformClick();
  607.  
  608.             // Azzero tempi
  609.             tired_timer[0] = 0;
  610.             tired_timer[1] = 0;
  611.             tired_timer[2] = 0;
  612.  
  613.             // Disabilito selezione ROI
  614.             button2.Enabled = false;
  615.             button3.Enabled = false;
  616.             button4.Enabled = false;
  617.  
  618.             button9.Enabled = false;
  619.             numericUpDown2.Enabled = false;
  620.         }
  621.  
  622.         // ----------------------
  623.         // CheckBox input da file
  624.         // ----------------------
  625.         private void checkBox3_CheckedChanged(object sender, EventArgs e)
  626.         {
  627.             // Rendo mutualmente esclusive le chechbox di videocamera e file
  628.             if((checkBox3.CheckState == CheckState.Unchecked) && (checkBox4.CheckState == CheckState.Unchecked))
  629.             {
  630.                 checkBox4.CheckState = CheckState.Checked;
  631.                 button6.Enabled = false;
  632.                 button8.Enabled = true;
  633.             }
  634.             if ((checkBox3.CheckState == CheckState.Checked) && (checkBox4.CheckState == CheckState.Checked))
  635.             {
  636.                 checkBox4.CheckState = CheckState.Unchecked;
  637.                 button6.Enabled = true;
  638.                 button8.Enabled = false;
  639.             }
  640.  
  641.             // Elimino ROI
  642.             button10.PerformClick();
  643.             button11.PerformClick();
  644.             button12.PerformClick();
  645.  
  646.             // Azzero tempi
  647.             tired_timer[0] = 0;
  648.             tired_timer[1] = 0;
  649.             tired_timer[2] = 0;
  650.  
  651.             // Disabilito selezione ROI
  652.             button2.Enabled = false;
  653.             button3.Enabled = false;
  654.             button4.Enabled = false;
  655.  
  656.             button9.Enabled = false;
  657.             numericUpDown2.Enabled = false;
  658.         }
  659.  
  660.         // ------------------------------------------------
  661.         // Funzione di aggiornamento variabili dimensionali
  662.         // ------------------------------------------------
  663.         public void refresh_video_size_form()
  664.         {
  665.             // Modifico il ratio di ridimensionamento secondo la trackbar di qualità
  666.             video_edit.resize_scale = ((double)trackBar1.Value / (double)10);
  667.             // Aggiorno le variabili dimensionali presenti in video_edit
  668.             video_edit.refresh_video_size();
  669.  
  670.             width_coeff = (double)video_edit.cols / (double)imageBox1.Width;
  671.             height_coeff = (double)video_edit.rows / (double)imageBox1.Height;
  672.         }
  673.  
  674.         // ---------------------------------------
  675.         // Campo numerico di selezione videocamera
  676.         // ---------------------------------------
  677.         private void numericUpDown2_ValueChanged(object sender, EventArgs e)
  678.         {
  679.             // Disabilito la selezione delle ROI
  680.             button2.Enabled = false;
  681.             button3.Enabled = false;
  682.             button4.Enabled = false;
  683.         }
  684.        
  685.         // -----------------------------
  686.         // Trackbar di selezione qualità
  687.         // -----------------------------
  688.         private void trackBar1_Scroll_1(object sender, EventArgs e)
  689.         {
  690.             int i;
  691.             // Definisco rapporto tra l'ultimo valore e il valore attuale per ridimensionare l'immagine
  692.             float scale = (float)trackBar1.Value / (float)trackBar1_last_value;
  693.  
  694.             // Aggiorno le variabili dimensionali
  695.             refresh_video_size_form();
  696.  
  697.             // Aggiorno l'immagine, ora ridimensionata
  698.             video_edit.refresh_image();
  699.  
  700.             // Ridefinisco le ROI e le disegno
  701.             for(i = 0; i < 3; i++)
  702.             {
  703.                 if (roi_selected[i])
  704.                 {
  705.                     roi_area[i] = new Rectangle(new Point((int)(roi_area[i].X * scale), (int)(roi_area[i].Y * scale)), new Size((int)(roi_area[i].Width * scale), (int)(roi_area[i].Height * scale)));
  706.                     CvInvoke.Rectangle(video_output, roi_area[i], rect_color[i], ((3 * video_edit.resize_scale) < 1) ? 1 : (int)(3 * video_edit.resize_scale));
  707.                 }
  708.             }
  709.  
  710.             // Aggiorno LPS
  711.             tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
  712.             tired_point_top = new Point(tired_threshold, 0);
  713.             tired_point_bot = new Point(tired_threshold, video_edit.rows);
  714.  
  715.             // Disegno LPS
  716.             CvInvoke.Line(video_output, tired_point_top, tired_point_bot, rect_color[2], ((2 * video_edit.resize_scale) < 1) ? 1 : (int)(2 * video_edit.resize_scale));
  717.  
  718.             // Aggiorno immagine in imageBox1
  719.             imageBox1.Image = video_output;
  720.             imageBox1.Refresh();
  721.  
  722.             label14.Text = "Quality: " + (trackBar1.Value * 10).ToString() + "% (affects FPS)";
  723.  
  724.             // Aggiorno la variabile di ultimo valore per la prossima modifica
  725.             trackBar1_last_value = trackBar1.Value;
  726.  
  727.         }
  728.  
  729.         // -----------------------------------
  730.         // Textbox di selezione nome file dati
  731.         // -----------------------------------
  732.         private void textBox1_TextChanged(object sender, EventArgs e)
  733.         {
  734.             // Controllo che il nome sia valido
  735.             bool name_valid = !string.IsNullOrEmpty(textBox1.Text) && textBox1.Text.IndexOfAny(Path.GetInvalidFileNameChars()) < 0;
  736.  
  737.             if (!name_valid)
  738.             {
  739.                 // Se non è valido disabilito il bottone di salvataggio
  740.                 MessageBox.Show("Insert valid file name");
  741.                 button5.Enabled = false;
  742.             }
  743.             else
  744.             {
  745.                 // Se esiste ed è stata selezionata una cartella di destinazione abilito il pulsante di salvataggio
  746.                 if(browse_save_folder_result == DialogResult.OK)
  747.                 {
  748.                     button5.Enabled = true;
  749.                 }
  750.             }
  751.         }
  752.  
  753.         // -----------------------------
  754.         // Bottone di eliminazione ROI 1
  755.         // -----------------------------
  756.         private void button10_Click(object sender, EventArgs e)
  757.         {
  758.             // Elimino la ROI e la flaggo come deselezionata
  759.             roi_area[0] = new Rectangle();
  760.             roi_selected[0] = false;
  761.  
  762.             // Disabilito il bottone "Start" se nessuna ROI è selezionata
  763.             if(!roi_selected[0] && !roi_selected[1] && !roi_selected[2])
  764.             {
  765.                 button1.Enabled = false;
  766.             }        
  767.  
  768.             // Ridisegno le ROI
  769.             video_edit.draw_rois(true, true);
  770.  
  771.             button10.Enabled = false;
  772.         }
  773.  
  774.         // -----------------------------
  775.         // Bottone di eliminazione ROI 2
  776.         // -----------------------------
  777.  
  778.         // Funziona come il primo
  779.         private void button11_Click(object sender, EventArgs e)
  780.         {
  781.             roi_area[1] = new Rectangle();
  782.             roi_selected[1] = false;
  783.  
  784.             if (!roi_selected[0] && !roi_selected[1] && !roi_selected[2])
  785.             {
  786.                 button1.Enabled = false;
  787.             }
  788.  
  789.             video_edit.draw_rois(true, true);
  790.  
  791.             button11.Enabled = false;
  792.         }
  793.  
  794.         // -----------------------------
  795.         // Bottone di eliminazione ROI 3
  796.         // -----------------------------
  797.  
  798.         // Funziona come il primo
  799.         private void button12_Click(object sender, EventArgs e)
  800.         {
  801.             roi_area[2] = new Rectangle();
  802.             roi_selected[2] = false;
  803.  
  804.             if (!roi_selected[0] && !roi_selected[1] && !roi_selected[2])
  805.             {
  806.                 button1.Enabled = false;
  807.             }
  808.  
  809.             video_edit.draw_rois(true, true);
  810.  
  811.             button12.Enabled = false;
  812.         }
  813.  
  814.         // ---------------------------------------------------------------
  815.         // Timer di comunicazione con il software di controllo circolatore
  816.         // ---------------------------------------------------------------
  817.         private void timer2_Tick(object sender, EventArgs e)
  818.         {
  819.             // Apro il file di comunicazione
  820.             StreamWriter pipe_stream = new StreamWriter("pipe");
  821.  
  822.             // Scrico il segnale di spegnimento se almeno uno dei pesci è stanco da troppo tempo
  823.             if ((tired_timer[0] > (int)numericUpDown3.Value) || (tired_timer[1] > (int)numericUpDown3.Value) || (tired_timer[2] > (int)numericUpDown3.Value))
  824.             {
  825.                 pipe_stream.WriteLine("1");
  826.             }
  827.             else
  828.             {
  829.                 pipe_stream.WriteLine("0");
  830.             }
  831.  
  832.             pipe_stream.Close();
  833.         }
  834.  
  835.         // ---------------------------------
  836.         // Bottone di svuotamento lista dati
  837.         // ---------------------------------
  838.         private void button13_Click(object sender, EventArgs e)
  839.         {
  840.             // Messagebox di conferma
  841.             DialogResult result = MessageBox.Show("Are you sure?", "Clear Data", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
  842.  
  843.             // Chiamo il metodo di svuotamento lista se l'operazione viene confermata
  844.             if(result == DialogResult.Yes)
  845.                 video_edit.clear_data();
  846.         }
  847.  
  848.         // --------------------------
  849.         // Checkbox di detection view
  850.         // --------------------------
  851.         private void checkBox1_CheckedChanged(object sender, EventArgs e)
  852.         {
  853.             detection_view = checkBox1.Checked;
  854.         }
  855.  
  856.         // ------------------------------------------------------
  857.         // Evento di rilascio di un tasto del mouse sull'immagine
  858.         // ------------------------------------------------------
  859.         private void imageBox1_MouseUp(object sender, MouseEventArgs e)
  860.         {
  861.             // Se sto selezionando una ROI aggiorno la posizione del secondo angolo e la flaggo come selezionata
  862.             if (roi_selection >= 0)
  863.             {
  864.                 roi_corner_2 = new Point(((int)(width_coeff * (double)e.X)), ((int)(height_coeff * (double)e.Y)));
  865.                 roi_selected[roi_selection] = true;
  866.             }
  867.         }
  868.  
  869.         // --------------------------------
  870.         // Timer di aggiornamento controlli
  871.         // --------------------------------
  872.         private void timer1_Tick(object sender, EventArgs e)
  873.         {
  874.             // Aggiorno immagine se l'input non è vuoto
  875.             if (!video_output.IsEmpty)
  876.             {
  877.                 imageBox1.Image = video_output;
  878.                 imageBox1.Refresh();
  879.             }
  880.            
  881.             // Gestisco la fine del file
  882.             if(eof)
  883.             {
  884.                 button1.PerformClick();
  885.                 input_file_browser.Dispose();
  886.                 input_file_browser = new OpenFileDialog();
  887.                 browse_input_file_result = DialogResult.None;
  888.                 eof = false;
  889.             }
  890.  
  891.             // Aggiorno le label dei tempi
  892.             label8.Text = tired_timer[0].ToString();
  893.             label9.Text = tired_timer[1].ToString();
  894.             label10.Text = tired_timer[2].ToString();
  895.  
  896.             // Coloro le label dei tempi a seconda del tempo massimo
  897.             if(tired_timer[0] > (int)numericUpDown3.Value)
  898.                 label8.ForeColor = Color.Red;
  899.             else
  900.                 label8.ForeColor = Color.Black;
  901.  
  902.             if (tired_timer[1] > (int)numericUpDown3.Value)
  903.                 label9.ForeColor = Color.Red;
  904.             else
  905.                 label9.ForeColor = Color.Black;
  906.  
  907.             if (tired_timer[2] > (int)numericUpDown3.Value)
  908.                 label10.ForeColor = Color.Red;
  909.             else
  910.                 label10.ForeColor = Color.Black;
  911.  
  912.             // Aggiorno gli FPS
  913.             numericUpDown1.Maximum = max_fps;
  914.             if(checkBox2.Checked)
  915.             {
  916.                 numericUpDown1.Value = numericUpDown1.Maximum;
  917.             }
  918.         }
  919.     }
  920.  
  921.     // ------------------------------------------------------------------
  922.     // Classe contenente l'acquisizione e la manipolazione di frame e ROI
  923.     // ------------------------------------------------------------------
  924.     public class video_edit
  925.     {
  926.         // -----------------------
  927.         // Dichiarazione variabili
  928.         // -----------------------
  929.  
  930.         private static VideoCapture camera = new VideoCapture();
  931.  
  932.         public static List<data> data_list = new List<data>();
  933.  
  934.         private static MCvScalar[] rect_color = new MCvScalar[3] { new MCvScalar(255, 0, 0), new MCvScalar(0, 255, 0), new MCvScalar(0, 0, 255) };
  935.  
  936.         private static string input_mode = "stream";
  937.  
  938.         public static int rows;
  939.         public static int cols;
  940.         public static int index = 0;
  941.  
  942.         private static Mat input_frame = new Mat();
  943.         private static Mat black_frame = new Mat();
  944.  
  945.         private static double camera_fps = 1;
  946.         public static double resize_scale = 0.1;
  947.  
  948.         private static bool timer_reset = false;
  949.  
  950.         // ---------------------------------------------------------------
  951.         // Struttura che immagazzina un singolo record dei dati analizzati
  952.         // ---------------------------------------------------------------
  953.         public struct data
  954.         {
  955.             public int index;
  956.             public long time;
  957.             public float thresh;
  958.             public float pos_1, pos_2, pos_3;
  959.             public double time_1, time_2, time_3;
  960.  
  961.             public data(int i, long t, float thr, float p1, float p2, float p3, double t1, double t2, double t3)
  962.             {
  963.                 index = i;
  964.                 time = t;
  965.                 thresh = thr;
  966.                 pos_1 = p1;
  967.                 pos_2 = p2;
  968.                 pos_3 = p3;
  969.                 time_1 = t1;
  970.                 time_2 = t2;
  971.                 time_3 = t3;
  972.             }
  973.         }
  974.  
  975.         // -------------------------------------------
  976.         // Metodo di aggiornamento dimensione immagine
  977.         // -------------------------------------------
  978.         public static void refresh_image()
  979.         {
  980.             Mat temp_resize = new Mat();
  981.  
  982.             // Leggo un nuovo frame dalla sorgente
  983.             camera.Read(temp_resize);
  984.  
  985.             // Ridimensiono il frame
  986.             CvInvoke.Resize(temp_resize, Form1.video_output, new Size(cols, rows));
  987.             Form1.video_output.CopyTo(input_frame);
  988.         }
  989.  
  990.         // --------------------------------
  991.         // Metodo di tracciamento ROI e LPS
  992.         // --------------------------------
  993.         public static void draw_rois(bool rois, bool thresh)
  994.         {
  995.             int i;
  996.             Mat temp_frame = new Mat();
  997.  
  998.             // Ridimensiono l'immagine secondo la qualità impostata
  999.             CvInvoke.Resize(input_frame, temp_frame, new Size(cols, rows));
  1000.  
  1001.             // Se il primo argomento è true disegno le ROI
  1002.             if (rois)
  1003.             {
  1004.                 for (i = 0; i < 3; i++)
  1005.                 {
  1006.                     if (Form1.roi_selected[i])
  1007.                     {
  1008.                         CvInvoke.Rectangle(temp_frame, Form1.roi_area[i], rect_color[i], ((3 * resize_scale) < 1) ? 1 : (int)(3 * resize_scale));
  1009.                     }
  1010.                 }
  1011.             }
  1012.  
  1013.             // Se il secondo argomento è true disegno la LPS
  1014.             if (thresh)
  1015.             {
  1016.                 CvInvoke.Line(temp_frame, Form1.tired_point_top, Form1.tired_point_bot, rect_color[2], ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
  1017.             }
  1018.  
  1019.             temp_frame.CopyTo(Form1.video_output);
  1020.         }
  1021.  
  1022.         // ----------------------------------------------
  1023.         // Metodo di aggiornamento variabili dimensionali
  1024.         // ----------------------------------------------
  1025.         public static void refresh_video_size()
  1026.         {
  1027.             rows = (int)((double)camera.GetCaptureProperty(CapProp.FrameHeight) * resize_scale);
  1028.             cols = (int)((double)camera.GetCaptureProperty(CapProp.FrameWidth) * resize_scale);
  1029.         }
  1030.        
  1031.         // ----------------------------------
  1032.         // Metodo di aggiornamento file video
  1033.         // ----------------------------------
  1034.         public static void change_input_file(string path)
  1035.         {
  1036.             Mat temp_frame = new Mat();
  1037.             Mat resz_frame = new Mat();
  1038.  
  1039.             // Elimino l'input precedente e apro il nuovo file
  1040.             camera.Dispose();
  1041.             camera = new VideoCapture(path);
  1042.  
  1043.             if (camera.IsOpened)
  1044.             {
  1045.                 // Aggiorno le variabili dimensionali
  1046.                 refresh_video_size();
  1047.  
  1048.                 // Registro gli FPS a cui è stato registrato il video
  1049.                 camera_fps = camera.GetCaptureProperty(CapProp.Fps);
  1050.                
  1051.                 // Catturo un nuovo frame
  1052.                 while (!camera.Grab()) { };
  1053.                 camera.Retrieve(temp_frame);
  1054.  
  1055.                 // Ridimensiono il frame
  1056.                 CvInvoke.Resize(temp_frame, resz_frame, new Size(cols, rows));
  1057.  
  1058.                 // Aggiorno il frame corrente
  1059.                 resz_frame.CopyTo(input_frame);
  1060.                 resz_frame.CopyTo(Form1.video_output);
  1061.             }
  1062.  
  1063.             input_mode = "file";
  1064.         }
  1065.  
  1066.         // ------------------------------------
  1067.         // Metodo di aggiornamento stream video
  1068.         // ------------------------------------
  1069.         public static void change_input_stream(int camera_index)
  1070.         {
  1071.             Mat temp_frame = new Mat();
  1072.             Mat resz_frame = new Mat();
  1073.  
  1074.             // Elimino l'input precedente e apro la nuova videocamera
  1075.             camera.Dispose();
  1076.             camera = new VideoCapture(camera_index);
  1077.  
  1078.             // Aggiorno le variabili dimensionali
  1079.             refresh_video_size();
  1080.  
  1081.             // Catturo un nuovo frame
  1082.             while (!camera.Grab()) { };
  1083.             camera.Retrieve(temp_frame);
  1084.  
  1085.             // Ridimensiono il frame
  1086.             CvInvoke.Resize(temp_frame, resz_frame, new Size(0, 0), resize_scale, resize_scale);
  1087.  
  1088.             // Aggiorno il frame corrente
  1089.             resz_frame.CopyTo(input_frame);
  1090.             resz_frame.CopyTo(Form1.video_output);
  1091.  
  1092.             input_mode = "stream";
  1093.         }
  1094.  
  1095.         // --------------------------------
  1096.         // Metodo di svuotamento lista dati
  1097.         // --------------------------------
  1098.         public static void clear_data()
  1099.         {
  1100.             index = 0;
  1101.             timer_reset = true;
  1102.             data_list.Clear();
  1103.         }
  1104.  
  1105.         // ----------------------------------------
  1106.         // Ciclo di acquisizione e processing frame
  1107.         // ----------------------------------------
  1108.         public static void fish_detection()
  1109.         {
  1110.             int i;
  1111.             double[] fish_timer = { 0, 0, 0 };
  1112.             long elapsed;
  1113.  
  1114.             data current_data;
  1115.  
  1116.             Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(2, 2), new Point(-1, -1));
  1117.  
  1118.             Mat input = new Mat();
  1119.             Mat detected = new Mat();
  1120.             Mat resized = new Mat();
  1121.             Mat blurred_input = new Mat();
  1122.  
  1123.             Mat[] partial_output = new Mat[3] { new Mat(), new Mat(), new Mat() };
  1124.             Mat output = new Mat();
  1125.  
  1126.             Mat temp_frame = new Mat();
  1127.             Mat fg_KNN = new Mat();
  1128.             Mat fg_KNN_bw = new Mat();
  1129.  
  1130.             BackgroundSubtractorKNN bgsKNN = new BackgroundSubtractorKNN(50, 100, true);
  1131.  
  1132.             MCvScalar red = new MCvScalar(0, 0, 255);
  1133.             MCvScalar green = new MCvScalar(0, 255, 0);
  1134.             MCvScalar blue = new MCvScalar(255, 0, 0);
  1135.             MCvScalar color = new MCvScalar(255);
  1136.  
  1137.             Moments moments;
  1138.             Point[] center = new Point[3] { new Point(0, 0), new Point(0, 0), new Point(0, 0) };
  1139.  
  1140.             Stopwatch stopwatch = new Stopwatch();
  1141.             Stopwatch total_time = new Stopwatch();
  1142.  
  1143.             DateTime[] t_fish = { DateTime.Now, DateTime.Now, DateTime.Now };
  1144.             bool[] first_cross = { true, true, true };
  1145.             double inter_frame_t, total_time_file = 0;
  1146.  
  1147.             DateTime t_last_frame = DateTime.Now;
  1148.             DateTime t_now = DateTime.Now;
  1149.             TimeSpan t_delta = t_now.Subtract(t_last_frame);
  1150.  
  1151.             while (true)
  1152.             {
  1153.                 // Il ciclo di processing è controllato dal bottone "Start/Stop"
  1154.                 if (Form1.running)
  1155.                 {
  1156.                     // Inizio a registrare il tempo passato in esecuzione per salvarlo nel file dati
  1157.                     total_time.Start();
  1158.  
  1159.                     // Gestisco problema di esecuzione troppo lenta
  1160.                     while (Form1.fps == 0) { };
  1161.  
  1162.                     inter_frame_t = Form1.inter_frame_time;
  1163.  
  1164.                     // Aspetto il tempo necessario per il frame successivo
  1165.                     while (t_delta.TotalSeconds <= inter_frame_t)
  1166.                     {
  1167.                         Thread.Sleep(10);
  1168.                         t_now = DateTime.Now;
  1169.                         t_delta = t_now.Subtract(t_last_frame);
  1170.  
  1171.                         // Scarto i frame intermedi se sto leggendo da videocamera
  1172.                         if (input_mode == "stream")
  1173.                         {
  1174.                             camera.Read(input_frame);
  1175.                         }
  1176.                     }
  1177.  
  1178.                     // Acquisisco il frame se sto leggendo da file
  1179.                     if (input_mode == "file")
  1180.                     {
  1181.                         camera.Read(input_frame);
  1182.                     }
  1183.  
  1184.                     // Fermo il ciclo di processing se il frame acquisito non è valido
  1185.                     if (input_frame.IsEmpty)
  1186.                     {
  1187.                         Form1.running = false;
  1188.                         Form1.eof = true;
  1189.                     }
  1190.                     else
  1191.                     {
  1192.  
  1193.                         t_delta = TimeSpan.Zero;
  1194.                         t_last_frame = t_now;
  1195.  
  1196.                         // Registro il tempo di esecuzione del ciclo di processing per regolare gli FPS
  1197.                         stopwatch.Restart();
  1198.  
  1199.                         // Porto il frame alla qualità desiderata
  1200.                         CvInvoke.Resize(input_frame, resized, new Size(cols, rows));
  1201.  
  1202.                         // Genero un frame nero di dimensione corretta su cui lavorare
  1203.                         black_frame = Mat.Zeros(rows, cols, DepthType.Cv8U, 3);
  1204.  
  1205.                         resized.CopyTo(detected);
  1206.  
  1207.  
  1208.                         // Ripeto per le tre corsie
  1209.                         for (i = 0; i < 3; i++)
  1210.                         {
  1211.                             // Copio la corsia corrente sul frame nero usando una maschera definita dalla ROI
  1212.                             black_frame.CopyTo(input);
  1213.                             resized.CopyTo(input, Form1.roi_mask[i]);
  1214.  
  1215.                             // Riduco rumore sfocando l'immagine
  1216.                             CvInvoke.GaussianBlur(input, blurred_input, new Size(21, 21), 0, 0, BorderType.Default);
  1217.  
  1218.                             // Applico la background subtraction al frame colorato per usare anche il colore dei pesci come discriminante
  1219.                             bgsKNN.Apply(blurred_input, fg_KNN);
  1220.  
  1221.                             // Passo il frame a bw per calcolarne i momenti
  1222.                             CvInvoke.Threshold(fg_KNN, fg_KNN_bw, Form1.light_threshold, 255, ThresholdType.Binary);
  1223.                             fg_KNN_bw.CopyTo(partial_output[i]);
  1224.  
  1225.                             // Eseguo un'operazione di opening sull'immagine per ridurre il rumore
  1226.                             CvInvoke.Erode(partial_output[i], temp_frame, element, new Point(-1, -1), 1, BorderType.Constant, new MCvScalar(255, 255, 255));
  1227.                             CvInvoke.Dilate(temp_frame, partial_output[i], element, new Point(-1, -1), 1, BorderType.Constant, new MCvScalar(255, 255, 255));
  1228.  
  1229.                             // Rimuovo il rumore esterno generato da Dilate
  1230.                             CvInvoke.Rectangle(partial_output[i], new Rectangle(0, 0, partial_output[i].Width, partial_output[i].Height), new MCvScalar(0, 0, 0), 10);
  1231.  
  1232.                             // Calcolo i momenti
  1233.                             moments = CvInvoke.Moments(partial_output[i], true);
  1234.  
  1235.                             if (Form1.roi_selected[i])
  1236.                             {
  1237.                                 // Calcolo il centro di massa del pesce rilevato
  1238.                                 center[i] = new Point((int)(moments.M10 / moments.M00), (int)(moments.M01 / moments.M00));
  1239.  
  1240.                                 // Gestisco i momenti in cui il software perde di vista il pesce
  1241.                                 if (center[i].X < -1)
  1242.                                 {
  1243.                                     center[i].X = -2;
  1244.                                 }
  1245.  
  1246.                                 Form1.fish_x[i] = center[i].X;
  1247.  
  1248.                                 // Controllo se il pesce è stanco
  1249.                                 if (center[i].X < Form1.tired_threshold)
  1250.                                 {
  1251.                                     color = red;
  1252.                                     if (first_cross[i])
  1253.                                     {
  1254.                                         t_fish[i] = DateTime.Now;
  1255.                                         first_cross[i] = false;
  1256.                                     }
  1257.  
  1258.                                     // Assegno i tempi a seconda del metodo di input
  1259.                                     if (input_mode == "stream")
  1260.                                     {
  1261.                                         fish_timer[i] = DateTime.Now.Subtract(t_fish[i]).TotalSeconds;
  1262.                                     }
  1263.                                     else if (input_mode == "file")
  1264.                                     {
  1265.                                         fish_timer[i] += 1 / camera_fps;
  1266.                                     }
  1267.  
  1268.                                     Form1.tired_timer[i] = fish_timer[i];
  1269.                                 }
  1270.                                 else
  1271.                                 {
  1272.                                     // Riporto tutto a zero se il pesce torna oltre LPS
  1273.                                     color = green;
  1274.                                     first_cross[i] = true;
  1275.                                     fish_timer[i] = 0;
  1276.                                     Form1.tired_timer[i] = 0;
  1277.                                 }
  1278.                             }
  1279.                             else
  1280.                             {
  1281.                                 // ROI non selezionata
  1282.                                 center[i] = new Point(-1, -1);
  1283.                             }
  1284.  
  1285.                             // Disegno un cerchio sulla posizione rilevata
  1286.                             CvInvoke.Circle(detected, center[i], ((5 * resize_scale) < 1) ? 1 : (int)(5 * resize_scale), color, ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
  1287.                         }
  1288.  
  1289.                         // Scelgo cosa mostrare a seconda che sia selezionata o no la vista detection
  1290.                         if (Form1.detection_view)
  1291.                         {
  1292.                             CvInvoke.Add(partial_output[0], partial_output[1], temp_frame);
  1293.                             CvInvoke.Add(partial_output[2], temp_frame, output);
  1294.                         }
  1295.                         else
  1296.                         {
  1297.                             detected.CopyTo(output);
  1298.                         }
  1299.  
  1300.                         // Disegno LPS sul frame in uscita
  1301.                         CvInvoke.Line(output, Form1.tired_point_top, Form1.tired_point_bot, red, ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
  1302.  
  1303.                         // Disegno le ROI se il ciclo si sta fermando
  1304.                         if (!Form1.running)
  1305.                         {
  1306.                             for (i = 0; i < 3; i++)
  1307.                             {
  1308.                                 if (Form1.roi_selected[i])
  1309.                                 {
  1310.                                     CvInvoke.Rectangle(output, Form1.roi_area[i], rect_color[i], ((3 * resize_scale) < 1) ? 1 : (int)(3 * resize_scale));
  1311.                                 }
  1312.                             }
  1313.                         }
  1314.  
  1315.                         output.CopyTo(Form1.video_output);
  1316.                         stopwatch.Stop();
  1317.                         elapsed = stopwatch.ElapsedMilliseconds;
  1318.  
  1319.                         // setto gli fps massimi relativi al tempo di processing del frame corrente (margine 2x)
  1320.                         if(elapsed >= 1)
  1321.                         {
  1322.                             if ((int)(1000 / (2 * (elapsed))) > 0)
  1323.                             {
  1324.                                 Form1.max_fps = (int)(1000 / (2 * (elapsed)));
  1325.                             }
  1326.                             else
  1327.                             {
  1328.                                 Form1.max_fps = 0;
  1329.                                 MessageBox.Show("Processing took too long. Try stopping, reloading file or stream and lowering quality");
  1330.                             }
  1331.                         }
  1332.                         else
  1333.                         {
  1334.                             Form1.max_fps = 500;
  1335.                         }
  1336.  
  1337.                         total_time_file += 1000 / camera_fps;
  1338.  
  1339.                         if (timer_reset)
  1340.                         {
  1341.                             total_time.Reset();
  1342.                             timer_reset = false;
  1343.                         }
  1344.  
  1345.                         // Salvo tutti i dati utili
  1346.                         current_data = new data(index++, (input_mode == "stream") ? total_time.ElapsedMilliseconds : (long)total_time_file, Form1.tired_threshold_float, (center[0].X > 0) ? ((float)center[0].X / (float)cols) : 0, (center[1].X > 0) ? ((float)center[1].X / (float)cols) : 0, (center[2].X > 0) ? ((float)center[2].X / (float)cols) : 0, fish_timer[0], fish_timer[1], fish_timer[2]);
  1347.                         data_list.Add(current_data);
  1348.                     }
  1349.                 }
  1350.                 else
  1351.                 {
  1352.                     // Fermo la registrazione del tempo se il ciclo non è in esecuzione
  1353.                     total_time.Stop();
  1354.                 }
  1355.             }
  1356.         }
  1357.  
  1358.         // -----------------------
  1359.         // Metodo di selezione ROI
  1360.         // -----------------------
  1361.         public static void set_roi()
  1362.         {
  1363.             Mat temp_frame = new Mat();
  1364.  
  1365.             int i;
  1366.             int roi = Form1.roi_selection;
  1367.  
  1368.             // Ridimensiono il frame corrente alla qualità corretta
  1369.             CvInvoke.Resize(input_frame, temp_frame, new Size(cols, rows));
  1370.  
  1371.             // Finchè non rilascio il tasto del mouse sull'immagine eseguo questo ciclo
  1372.             while (!Form1.roi_selected[roi])
  1373.             {
  1374.                 if (Form1.image_clicked)
  1375.                 {
  1376.                     // Ridimensiono il frame corrente alla qualità corretta
  1377.                     CvInvoke.Resize(input_frame, temp_frame, new Size(cols, rows));
  1378.  
  1379.                     // L'oggetto Rectangle considera il primo angolo come il superiore sinistro,
  1380.                     // quindi se la ROI è stata disegnata diversamente sull'immagine devo
  1381.                     // trovare quale punto utilizzare per definire il rettangolo.
  1382.  
  1383.                     if ((Form1.roi_corner_1.X < Form1.mouseX) && (Form1.roi_corner_1.Y < Form1.mouseY))
  1384.                     {
  1385.                         Form1.roi_area[roi] = new Rectangle(Form1.roi_corner_1.X, Form1.roi_corner_1.Y, Form1.mouseX - Form1.roi_corner_1.X, Form1.mouseY - Form1.roi_corner_1.Y);
  1386.                     }
  1387.                     else if ((Form1.roi_corner_1.X >= Form1.mouseX) && (Form1.roi_corner_1.Y < Form1.mouseY))
  1388.                     {
  1389.                         Form1.roi_area[roi] = new Rectangle(Form1.mouseX, Form1.roi_corner_1.Y, Form1.roi_corner_1.X - Form1.mouseX, Form1.mouseY - Form1.roi_corner_1.Y);
  1390.                     }
  1391.                     else if ((Form1.roi_corner_1.X >= Form1.mouseX) && (Form1.roi_corner_1.Y >= Form1.mouseY))
  1392.                     {
  1393.                         Form1.roi_area[roi] = new Rectangle(Form1.mouseX, Form1.mouseY, Form1.roi_corner_1.X - Form1.mouseX, Form1.roi_corner_1.Y - Form1.mouseY);
  1394.                     }
  1395.                     else if ((Form1.roi_corner_1.X < Form1.mouseX) && (Form1.roi_corner_1.Y >= Form1.mouseY))
  1396.                     {
  1397.                         Form1.roi_area[roi] = new Rectangle(Form1.roi_corner_1.X, Form1.mouseY, Form1.mouseX - Form1.roi_corner_1.X, Form1.roi_corner_1.Y - Form1.mouseY);
  1398.                     }
  1399.  
  1400.                 }
  1401.  
  1402.                 // Disegno le ROI
  1403.                 for (i = 0; i < 3; i++)
  1404.                 {
  1405.                     CvInvoke.Rectangle(temp_frame, Form1.roi_area[i], rect_color[i], ((3 * resize_scale) < 1) ? 1 : (int)(3 * resize_scale));
  1406.                 }
  1407.  
  1408.                 // Disegno la LPS
  1409.                 CvInvoke.Line(temp_frame, Form1.tired_point_top, Form1.tired_point_bot, rect_color[2], ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
  1410.  
  1411.                 temp_frame.CopyTo(Form1.video_output);
  1412.             }
  1413.  
  1414.             temp_frame.CopyTo(Form1.video_output);
  1415.  
  1416.         }
  1417.     }
  1418. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement