Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.IO;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Windows.Forms;
- using Emgu.CV;
- using Emgu.CV.Structure;
- using Emgu.CV.CvEnum;
- using System.Diagnostics;
- using System.Threading;
- namespace WindowsFormsApp2
- {
- public partial class Form1 : Form
- {
- // -----------------------
- // Dichiarazione variabili
- // -----------------------
- private static int trackBar1_last_value;
- public static Mat video_output = Mat.Zeros(video_edit.rows, video_edit.cols, DepthType.Cv8U, 3);
- public static Mat[] roi_mask = new Mat[3];
- public static bool running = false;
- public static bool[] roi_selected = { false, false, false };
- public static bool image_clicked = false;
- public static bool detection_view = false;
- public static bool eof = false;
- public static int fps = 30;
- public static int mouseX, mouseY;
- public static int light_threshold = 1;
- public static int max_fps = 100;
- public static int roi_selection = -1;
- public static int tired_threshold;
- public static int[] fish_x = { -1, -1, -1 };
- public static float tired_threshold_float;
- public static double inter_frame_time = (double)1 / (double)fps;
- public static double width_coeff, height_coeff;
- public static double detection_balance;
- public static double[] tired_timer = { 0, 0, 0 };
- public static Point roi_corner_1, roi_corner_2;
- public static Point tired_point_top, tired_point_bot;
- public static Rectangle[] roi_area = new Rectangle[3];
- MCvScalar[] rect_color = new MCvScalar[3] { new MCvScalar(255, 0, 0), new MCvScalar(0, 255, 0), new MCvScalar(0, 0, 255) };
- OpenFileDialog input_file_browser = new OpenFileDialog();
- FolderBrowserDialog save_folder_browser = new FolderBrowserDialog();
- DialogResult browse_input_file_result = DialogResult.None;
- DialogResult browse_save_folder_result = DialogResult.None;
- // ---------------------
- // Inizializzazione Form
- // ---------------------
- public Form1()
- {
- InitializeComponent();
- }
- // ---------------------------------------------
- // Caricamento Form e inizializzazione variabili
- // ---------------------------------------------
- private void Form1_Load(object sender, EventArgs e)
- {
- // Avvio il metodo di detection in un nuovo thread
- Thread main_loop_thread = new Thread(video_edit.fish_detection);
- main_loop_thread.IsBackground = true;
- main_loop_thread.Start();
- // Istanzio gli eventi mouseclick legati alla selezione delle ROI
- imageBox1.MouseMove += new MouseEventHandler(imageBox1_MouseMove);
- imageBox1.MouseDown += new MouseEventHandler(imageBox1_MouseDown);
- imageBox1.MouseUp += new MouseEventHandler(imageBox1_MouseUp);
- // Inizializzo le variabile che definiscono la qualità dell'immagine
- video_edit.resize_scale = ((double)trackBar1.Value / (double)10);
- trackBar1_last_value = trackBar1.Value;
- // Inizializzo le variabili che definiscono dimensione e posizione della Linea dei Pesci Stanchi (LPS)
- tired_threshold_float = (float)trackBar3.Value / (float)1000;
- tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
- tired_point_top = new Point(tired_threshold, 0);
- tired_point_bot = new Point(tired_threshold, video_edit.rows);
- label6.Text = (trackBar3.Value / 10).ToString() + "%";
- // Avvio il timer che comunica con il software di controllo circolatore
- timer2.Enabled = true;
- }
- // -------------------------------------------
- // Evento di movimento del mouse sull'immagine
- // -------------------------------------------
- private void imageBox1_MouseMove(object sender, MouseEventArgs e)
- {
- // Salvo la posizione del mouse durante la selezione della ROI
- if (roi_selection >= 0)
- {
- mouseX = (int)(width_coeff * e.X);
- mouseY = (int)(height_coeff * e.Y);
- }
- }
- // ------------
- // Modifica FPS
- // ------------
- private void numericUpDown1_ValueChanged(object sender, EventArgs e)
- {
- // Modifico le variabili legate agli FPS quando varia il controllo relativo
- fps = (int)numericUpDown1.Value;
- inter_frame_time = (double)1 / (double)fps;
- }
- // --------------
- // Pulsante Start
- // --------------
- private void button1_Click(object sender, EventArgs e)
- {
- int i;
- // Switch tra Start e Stop
- if (button1.Text == "Start")
- {
- button1.Text = "Stop";
- // Avvio il ciclo di processing presente nel thread di fish_detection
- running = true;
- // Disabilito i controlli che non devono essere toccati durante il ciclo di processing
- trackBar1.Enabled = false;
- button2.Enabled = false;
- button3.Enabled = false;
- button4.Enabled = false;
- button10.Enabled = false;
- button11.Enabled = false;
- button12.Enabled = false;
- button13.Enabled = false;
- numericUpDown3.Enabled = false;
- }
- else
- {
- button1.Text = "Start";
- // Fermo il ciclo di processing
- running = false;
- // Abilito i controlli che modificano i parametri di cattura
- trackBar1.Enabled = true;
- button2.Enabled = true;
- button3.Enabled = true;
- button4.Enabled = true;
- if (roi_selected[0])
- button10.Enabled = true;
- if (roi_selected[1])
- button11.Enabled = true;
- if (roi_selected[2])
- button12.Enabled = true;
- button13.Enabled = true;
- numericUpDown3.Enabled = true;
- // Aggiorno posizione e dimensione della LPS
- tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
- tired_point_top = new Point(tired_threshold, 0);
- tired_point_bot = new Point(tired_threshold, video_edit.rows);
- refresh_video_size_form();
- // Disegno ROI e LPS sul frame corrente
- video_edit.draw_rois(/* ROI */true, /* LPS */true);
- }
- // Ridefinisco le maschere delle ROI in cui vengono individuati i singoli pesci
- for (i = 0; i < 3; i++)
- {
- roi_mask[i] = Mat.Zeros(video_edit.rows, video_edit.cols, DepthType.Cv8U, 1);
- CvInvoke.Rectangle(roi_mask[i], roi_area[i], new MCvScalar(255), -1);
- }
- }
- // -------------------
- // Selezione prima ROI
- // -------------------
- private void button2_Click(object sender, EventArgs e)
- {
- // Switch tra selezione e conferma
- if (button2.Text == "Area 1")
- {
- // Aggiorno variabili che definiscono la ROI in selezione
- roi_selected[0] = false;
- roi_selection = 0;
- // Disabilito controlli inappropriati
- button1.Enabled = false;
- button3.Enabled = false;
- button4.Enabled = false;
- trackBar1.Enabled = false;
- // ----------------------------------
- button2.Text = "Confirm";
- refresh_video_size_form();
- // Avvio il metodo di impostazione della ROI in un nuovo thread
- Thread roi_thread = new Thread(video_edit.set_roi);
- roi_thread.Start();
- }
- else
- {
- // Aggiorno variabili che definiscono la ROI in selezione
- roi_selected[0] = true;
- roi_selection = -1;
- image_clicked = false;
- // Abilito controlli
- button1.Enabled = true;
- button3.Enabled = true;
- button4.Enabled = true;
- button10.Enabled = true;
- trackBar1.Enabled = true;
- // -----------------
- button2.Text = "Area 1";
- }
- }
- // ---------------------
- // Selezione seconda ROI
- // ---------------------
- // Funziona come la prima
- private void button3_Click(object sender, EventArgs e)
- {
- if (button3.Text == "Area 2")
- {
- roi_selected[1] = false;
- roi_selection = 1;
- button1.Enabled = false;
- button2.Enabled = false;
- button4.Enabled = false;
- trackBar1.Enabled = false;
- button3.Text = "Confirm";
- refresh_video_size_form();
- Thread roi_thread = new Thread(video_edit.set_roi);
- roi_thread.Start();
- }
- else
- {
- roi_selected[1] = true;
- roi_selection = -1;
- image_clicked = false;
- button1.Enabled = true;
- button2.Enabled = true;
- button4.Enabled = true;
- button11.Enabled = true;
- trackBar1.Enabled = true;
- button3.Text = "Area 2";
- }
- }
- // -------------------
- // Selezione terza ROI
- // -------------------
- // Funziona come la prima
- private void button4_Click(object sender, EventArgs e)
- {
- if (button4.Text == "Area 3")
- {
- roi_selected[2] = false;
- roi_selection = 2;
- button1.Enabled = false;
- button2.Enabled = false;
- button3.Enabled = false;
- trackBar1.Enabled = false;
- button4.Text = "Confirm";
- refresh_video_size_form();
- Thread roi_thread = new Thread(video_edit.set_roi);
- roi_thread.Start();
- }
- else
- {
- roi_selected[2] = true;
- roi_selection = -1;
- image_clicked = false;
- button1.Enabled = true;
- button2.Enabled = true;
- button3.Enabled = true;
- button12.Enabled = true;
- trackBar1.Enabled = true;
- button4.Text = "Area 3";
- }
- }
- // ------------------------------------------
- // Evento MouseDown sull'immagine della vasca
- // ------------------------------------------
- private void imageBox1_MouseDown(object sender, MouseEventArgs e)
- {
- image_clicked = true;
- // Definisco il primo angolo della ROI
- roi_corner_1 = new Point(((int)(width_coeff * (double)e.X)), ((int)(height_coeff * (double)e.Y)));
- }
- // ---------------------------------------------
- // Trackbar che definisce la posizione della LPS
- // ---------------------------------------------
- private void trackBar3_Scroll(object sender, EventArgs e)
- {
- // Aggiorno le variabili che definiscono la LPS
- tired_threshold_float = (float)trackBar3.Value / (float)1000;
- tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
- tired_point_top = new Point(tired_threshold, 0);
- tired_point_bot = new Point(tired_threshold, video_edit.rows);
- label6.Text = (trackBar3.Value / 10).ToString() + "%";
- refresh_video_size_form();
- // Disegno ROI e LPS sul frame corrente
- if(!running)
- video_edit.draw_rois(true, true);
- }
- // -----------------------------------
- // Bottone di salvataggio dati su file
- // -----------------------------------
- private void button5_Click(object sender, EventArgs e)
- {
- int i, list_size;
- list_size = video_edit.data_list.Count;
- string data_string, full_path;
- // Recupero la cartella di salvataggio dalla variabile di selezione cartella
- string folder = save_folder_browser.SelectedPath;
- // Controllo la validità del percorso, se si salva nella cartella principale di un disco la barra "\" è già presente
- if(folder.Length == 3)
- full_path = folder + textBox1.Text;
- else
- full_path = folder + "\\" + textBox1.Text;
- // Apro il file di salvataggio
- StreamWriter file_stream = File.CreateText(full_path);
- file_stream.WriteLine("Index\tTime\tThr\tPos 1\tPos 2\tPos 3\tTime 1\tTime 2\tTime 3");
- // Salvo i dati contenuti in data_list, variabile riempita in fish_detection
- for (i = 0; i < list_size; i++)
- {
- data_string = video_edit.data_list[i].index.ToString() + "\t" +
- video_edit.data_list[i].time.ToString() + "\t" +
- video_edit.data_list[i].thresh.ToString() + "\t" +
- video_edit.data_list[i].pos_1.ToString("0.000") + "\t" +
- video_edit.data_list[i].pos_2.ToString("0.000") + "\t" +
- video_edit.data_list[i].pos_3.ToString("0.000") + "\t" +
- video_edit.data_list[i].time_1.ToString("0.000") + "\t" +
- video_edit.data_list[i].time_2.ToString("0.000") + "\t" +
- video_edit.data_list[i].time_3.ToString("0.000");
- file_stream.WriteLine(data_string);
- }
- file_stream.Close();
- MessageBox.Show("File succesfully saved in " + full_path, "Save complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- // ----------------------------------------
- // Bottone di selezione nuovo file di input
- // ----------------------------------------
- private void button6_Click(object sender, EventArgs e)
- {
- timer1.Stop();
- Thread.Sleep(100);
- // Apro il browser dialog per selezionare il file
- browse_input_file_result = input_file_browser.ShowDialog();
- // Controllo che il file sia stato selezionato
- if(browse_input_file_result == DialogResult.OK)
- {
- // Chiamo il metodo che cambia il file di input
- video_edit.change_input_file(input_file_browser.FileName);
- // Aggiorno le dimensioni salvate
- refresh_video_size_form();
- // Aggiorno LPS
- tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
- tired_point_top = new Point(tired_threshold, 0);
- tired_point_bot = new Point(tired_threshold, video_edit.rows);
- // Elimino le ROI precedenti
- button10.PerformClick();
- button11.PerformClick();
- button12.PerformClick();
- // Azzero il tempo passato oltre la linea per ogni pesce
- tired_timer[0] = 0;
- tired_timer[1] = 0;
- tired_timer[2] = 0;
- // Disegno LPS sul frame corrente
- video_edit.draw_rois(false, true);
- // Abilito controlli di selezione ROI
- button2.Enabled = true;
- button3.Enabled = true;
- button4.Enabled = true;
- // Abilito trackbar qualità
- trackBar1.Enabled = true;
- // Gestisco un riavvio dovuto alla discesa a 0 FPS per detection troppo lenta
- if (max_fps == 0)
- {
- max_fps = 1;
- numericUpDown1.Maximum = max_fps;
- numericUpDown1.Value = numericUpDown1.Maximum;
- }
- timer1.Start();
- label6.Text = (trackBar3.Value / 10).ToString() + "%";
- }
- }
- // ---------------------------------------
- // Bottone di selezione nuovo stream video
- // ---------------------------------------
- private void button9_Click(object sender, EventArgs e)
- {
- // Apro stream di prova per vedere se la videocamera funziona
- VideoCapture input_stream = new VideoCapture((int)numericUpDown2.Value - 1);
- timer1.Stop();
- Thread.Sleep(100);
- // Controllo che lo stream di prova sia aperto
- if (input_stream.IsOpened)
- {
- // Chiudo stream di prova
- input_stream.Dispose();
- // Chiamo il metodo che cambia stream di input
- video_edit.change_input_stream((int)numericUpDown2.Value - 1);
- // Aggiorno le dimensioni salvate
- refresh_video_size_form();
- // Aggiorno LPS
- tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
- tired_point_top = new Point(tired_threshold, 0);
- tired_point_bot = new Point(tired_threshold, video_edit.rows);
- // Elimino ROI
- button10.PerformClick();
- button11.PerformClick();
- button12.PerformClick();
- // Azzero tempi passati oltre la linea per ogni pesce
- tired_timer[0] = 0;
- tired_timer[1] = 0;
- tired_timer[2] = 0;
- // Disegno LPS
- video_edit.draw_rois(false, true);
- // Abilito controlli di selezione ROi
- button2.Enabled = true;
- button3.Enabled = true;
- button4.Enabled = true;
- // Abilito trackbar qualità
- trackBar1.Enabled = true;
- // Gestisco un riavvio dovuto alla discesa a 0 FPS per detection troppo lenta
- if (max_fps == 0)
- {
- max_fps = 1;
- numericUpDown1.Maximum = max_fps;
- numericUpDown1.Value = numericUpDown1.Maximum;
- }
- timer1.Start();
- label6.Text = (trackBar3.Value / 10).ToString() + "%";
- }
- }
- // ----------------------------------------------
- // Bottone di selezione cartella salvataggio dati
- // ----------------------------------------------
- private void button7_Click(object sender, EventArgs e)
- {
- // Scelgo la cartella
- browse_save_folder_result = save_folder_browser.ShowDialog();
- // Controllo che il nome del file sia valido
- bool name_valid = !string.IsNullOrEmpty(textBox1.Text) && textBox1.Text.IndexOfAny(Path.GetInvalidFileNameChars()) < 0;
- if ((browse_save_folder_result == DialogResult.OK) && name_valid)
- {
- // Abilito il bottone di salvataggio se il percorso è valido
- button5.Enabled = true;
- }
- else
- {
- // Disabilito il salvataggio se il percorso non è valido
- button5.Enabled = false;
- }
- }
- // ---------------------------------------------------
- // Bottone di controllo numero videocamere disponibili
- // ---------------------------------------------------
- private void button8_Click(object sender, EventArgs e)
- {
- int i = 0;
- VideoCapture test_stream = new VideoCapture(0);
- // Provo ad aprire le videocamere una per una
- while (test_stream.IsOpened)
- {
- test_stream.Dispose();
- test_stream = new VideoCapture(i++);
- }
- test_stream.Dispose();
- // Rendo disponibili le videocamere rilevate
- if (i == 0)
- {
- MessageBox.Show("No cameras available");
- label2.Text = "Max: 0";
- numericUpDown2.Enabled = false;
- button9.Enabled = false;
- }
- else
- {
- numericUpDown2.Enabled = true;
- numericUpDown2.Maximum = i;
- button9.Enabled = true;
- label2.Text = "Max: " + i.ToString();
- }
- }
- // -----------------------------
- // CheckBox input da videocamera
- // -----------------------------
- private void checkBox4_CheckedChanged(object sender, EventArgs e)
- {
- // Rendo mutualmente esclusive le checkbox di videocamera e file
- if ((checkBox4.CheckState == CheckState.Unchecked) && (checkBox3.CheckState == CheckState.Unchecked))
- {
- checkBox3.CheckState = CheckState.Checked;
- button6.Enabled = true;
- button8.Enabled = false;
- }
- if ((checkBox4.CheckState == CheckState.Checked) && (checkBox3.CheckState == CheckState.Checked))
- {
- checkBox3.CheckState = CheckState.Unchecked;
- button6.Enabled = false;
- button8.Enabled = true;
- }
- // Elimino ROI
- button10.PerformClick();
- button11.PerformClick();
- button12.PerformClick();
- // Azzero tempi
- tired_timer[0] = 0;
- tired_timer[1] = 0;
- tired_timer[2] = 0;
- // Disabilito selezione ROI
- button2.Enabled = false;
- button3.Enabled = false;
- button4.Enabled = false;
- button9.Enabled = false;
- numericUpDown2.Enabled = false;
- }
- // ----------------------
- // CheckBox input da file
- // ----------------------
- private void checkBox3_CheckedChanged(object sender, EventArgs e)
- {
- // Rendo mutualmente esclusive le chechbox di videocamera e file
- if((checkBox3.CheckState == CheckState.Unchecked) && (checkBox4.CheckState == CheckState.Unchecked))
- {
- checkBox4.CheckState = CheckState.Checked;
- button6.Enabled = false;
- button8.Enabled = true;
- }
- if ((checkBox3.CheckState == CheckState.Checked) && (checkBox4.CheckState == CheckState.Checked))
- {
- checkBox4.CheckState = CheckState.Unchecked;
- button6.Enabled = true;
- button8.Enabled = false;
- }
- // Elimino ROI
- button10.PerformClick();
- button11.PerformClick();
- button12.PerformClick();
- // Azzero tempi
- tired_timer[0] = 0;
- tired_timer[1] = 0;
- tired_timer[2] = 0;
- // Disabilito selezione ROI
- button2.Enabled = false;
- button3.Enabled = false;
- button4.Enabled = false;
- button9.Enabled = false;
- numericUpDown2.Enabled = false;
- }
- // ------------------------------------------------
- // Funzione di aggiornamento variabili dimensionali
- // ------------------------------------------------
- public void refresh_video_size_form()
- {
- // Modifico il ratio di ridimensionamento secondo la trackbar di qualità
- video_edit.resize_scale = ((double)trackBar1.Value / (double)10);
- // Aggiorno le variabili dimensionali presenti in video_edit
- video_edit.refresh_video_size();
- width_coeff = (double)video_edit.cols / (double)imageBox1.Width;
- height_coeff = (double)video_edit.rows / (double)imageBox1.Height;
- }
- // ---------------------------------------
- // Campo numerico di selezione videocamera
- // ---------------------------------------
- private void numericUpDown2_ValueChanged(object sender, EventArgs e)
- {
- // Disabilito la selezione delle ROI
- button2.Enabled = false;
- button3.Enabled = false;
- button4.Enabled = false;
- }
- // -----------------------------
- // Trackbar di selezione qualità
- // -----------------------------
- private void trackBar1_Scroll_1(object sender, EventArgs e)
- {
- int i;
- // Definisco rapporto tra l'ultimo valore e il valore attuale per ridimensionare l'immagine
- float scale = (float)trackBar1.Value / (float)trackBar1_last_value;
- // Aggiorno le variabili dimensionali
- refresh_video_size_form();
- // Aggiorno l'immagine, ora ridimensionata
- video_edit.refresh_image();
- // Ridefinisco le ROI e le disegno
- for(i = 0; i < 3; i++)
- {
- if (roi_selected[i])
- {
- 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)));
- CvInvoke.Rectangle(video_output, roi_area[i], rect_color[i], ((3 * video_edit.resize_scale) < 1) ? 1 : (int)(3 * video_edit.resize_scale));
- }
- }
- // Aggiorno LPS
- tired_threshold = (int)(((double)trackBar3.Value / (double)1000) * video_edit.cols);
- tired_point_top = new Point(tired_threshold, 0);
- tired_point_bot = new Point(tired_threshold, video_edit.rows);
- // Disegno LPS
- 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));
- // Aggiorno immagine in imageBox1
- imageBox1.Image = video_output;
- imageBox1.Refresh();
- label14.Text = "Quality: " + (trackBar1.Value * 10).ToString() + "% (affects FPS)";
- // Aggiorno la variabile di ultimo valore per la prossima modifica
- trackBar1_last_value = trackBar1.Value;
- }
- // -----------------------------------
- // Textbox di selezione nome file dati
- // -----------------------------------
- private void textBox1_TextChanged(object sender, EventArgs e)
- {
- // Controllo che il nome sia valido
- bool name_valid = !string.IsNullOrEmpty(textBox1.Text) && textBox1.Text.IndexOfAny(Path.GetInvalidFileNameChars()) < 0;
- if (!name_valid)
- {
- // Se non è valido disabilito il bottone di salvataggio
- MessageBox.Show("Insert valid file name");
- button5.Enabled = false;
- }
- else
- {
- // Se esiste ed è stata selezionata una cartella di destinazione abilito il pulsante di salvataggio
- if(browse_save_folder_result == DialogResult.OK)
- {
- button5.Enabled = true;
- }
- }
- }
- // -----------------------------
- // Bottone di eliminazione ROI 1
- // -----------------------------
- private void button10_Click(object sender, EventArgs e)
- {
- // Elimino la ROI e la flaggo come deselezionata
- roi_area[0] = new Rectangle();
- roi_selected[0] = false;
- // Disabilito il bottone "Start" se nessuna ROI è selezionata
- if(!roi_selected[0] && !roi_selected[1] && !roi_selected[2])
- {
- button1.Enabled = false;
- }
- // Ridisegno le ROI
- video_edit.draw_rois(true, true);
- button10.Enabled = false;
- }
- // -----------------------------
- // Bottone di eliminazione ROI 2
- // -----------------------------
- // Funziona come il primo
- private void button11_Click(object sender, EventArgs e)
- {
- roi_area[1] = new Rectangle();
- roi_selected[1] = false;
- if (!roi_selected[0] && !roi_selected[1] && !roi_selected[2])
- {
- button1.Enabled = false;
- }
- video_edit.draw_rois(true, true);
- button11.Enabled = false;
- }
- // -----------------------------
- // Bottone di eliminazione ROI 3
- // -----------------------------
- // Funziona come il primo
- private void button12_Click(object sender, EventArgs e)
- {
- roi_area[2] = new Rectangle();
- roi_selected[2] = false;
- if (!roi_selected[0] && !roi_selected[1] && !roi_selected[2])
- {
- button1.Enabled = false;
- }
- video_edit.draw_rois(true, true);
- button12.Enabled = false;
- }
- // ---------------------------------------------------------------
- // Timer di comunicazione con il software di controllo circolatore
- // ---------------------------------------------------------------
- private void timer2_Tick(object sender, EventArgs e)
- {
- // Apro il file di comunicazione
- StreamWriter pipe_stream = new StreamWriter("pipe");
- // Scrico il segnale di spegnimento se almeno uno dei pesci è stanco da troppo tempo
- if ((tired_timer[0] > (int)numericUpDown3.Value) || (tired_timer[1] > (int)numericUpDown3.Value) || (tired_timer[2] > (int)numericUpDown3.Value))
- {
- pipe_stream.WriteLine("1");
- }
- else
- {
- pipe_stream.WriteLine("0");
- }
- pipe_stream.Close();
- }
- // ---------------------------------
- // Bottone di svuotamento lista dati
- // ---------------------------------
- private void button13_Click(object sender, EventArgs e)
- {
- // Messagebox di conferma
- DialogResult result = MessageBox.Show("Are you sure?", "Clear Data", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
- // Chiamo il metodo di svuotamento lista se l'operazione viene confermata
- if(result == DialogResult.Yes)
- video_edit.clear_data();
- }
- // --------------------------
- // Checkbox di detection view
- // --------------------------
- private void checkBox1_CheckedChanged(object sender, EventArgs e)
- {
- detection_view = checkBox1.Checked;
- }
- // ------------------------------------------------------
- // Evento di rilascio di un tasto del mouse sull'immagine
- // ------------------------------------------------------
- private void imageBox1_MouseUp(object sender, MouseEventArgs e)
- {
- // Se sto selezionando una ROI aggiorno la posizione del secondo angolo e la flaggo come selezionata
- if (roi_selection >= 0)
- {
- roi_corner_2 = new Point(((int)(width_coeff * (double)e.X)), ((int)(height_coeff * (double)e.Y)));
- roi_selected[roi_selection] = true;
- }
- }
- // --------------------------------
- // Timer di aggiornamento controlli
- // --------------------------------
- private void timer1_Tick(object sender, EventArgs e)
- {
- // Aggiorno immagine se l'input non è vuoto
- if (!video_output.IsEmpty)
- {
- imageBox1.Image = video_output;
- imageBox1.Refresh();
- }
- // Gestisco la fine del file
- if(eof)
- {
- button1.PerformClick();
- input_file_browser.Dispose();
- input_file_browser = new OpenFileDialog();
- browse_input_file_result = DialogResult.None;
- eof = false;
- }
- // Aggiorno le label dei tempi
- label8.Text = tired_timer[0].ToString();
- label9.Text = tired_timer[1].ToString();
- label10.Text = tired_timer[2].ToString();
- // Coloro le label dei tempi a seconda del tempo massimo
- if(tired_timer[0] > (int)numericUpDown3.Value)
- label8.ForeColor = Color.Red;
- else
- label8.ForeColor = Color.Black;
- if (tired_timer[1] > (int)numericUpDown3.Value)
- label9.ForeColor = Color.Red;
- else
- label9.ForeColor = Color.Black;
- if (tired_timer[2] > (int)numericUpDown3.Value)
- label10.ForeColor = Color.Red;
- else
- label10.ForeColor = Color.Black;
- // Aggiorno gli FPS
- numericUpDown1.Maximum = max_fps;
- if(checkBox2.Checked)
- {
- numericUpDown1.Value = numericUpDown1.Maximum;
- }
- }
- }
- // ------------------------------------------------------------------
- // Classe contenente l'acquisizione e la manipolazione di frame e ROI
- // ------------------------------------------------------------------
- public class video_edit
- {
- // -----------------------
- // Dichiarazione variabili
- // -----------------------
- private static VideoCapture camera = new VideoCapture();
- public static List<data> data_list = new List<data>();
- private static MCvScalar[] rect_color = new MCvScalar[3] { new MCvScalar(255, 0, 0), new MCvScalar(0, 255, 0), new MCvScalar(0, 0, 255) };
- private static string input_mode = "stream";
- public static int rows;
- public static int cols;
- public static int index = 0;
- private static Mat input_frame = new Mat();
- private static Mat black_frame = new Mat();
- private static double camera_fps = 1;
- public static double resize_scale = 0.1;
- private static bool timer_reset = false;
- // ---------------------------------------------------------------
- // Struttura che immagazzina un singolo record dei dati analizzati
- // ---------------------------------------------------------------
- public struct data
- {
- public int index;
- public long time;
- public float thresh;
- public float pos_1, pos_2, pos_3;
- public double time_1, time_2, time_3;
- public data(int i, long t, float thr, float p1, float p2, float p3, double t1, double t2, double t3)
- {
- index = i;
- time = t;
- thresh = thr;
- pos_1 = p1;
- pos_2 = p2;
- pos_3 = p3;
- time_1 = t1;
- time_2 = t2;
- time_3 = t3;
- }
- }
- // -------------------------------------------
- // Metodo di aggiornamento dimensione immagine
- // -------------------------------------------
- public static void refresh_image()
- {
- Mat temp_resize = new Mat();
- // Leggo un nuovo frame dalla sorgente
- camera.Read(temp_resize);
- // Ridimensiono il frame
- CvInvoke.Resize(temp_resize, Form1.video_output, new Size(cols, rows));
- Form1.video_output.CopyTo(input_frame);
- }
- // --------------------------------
- // Metodo di tracciamento ROI e LPS
- // --------------------------------
- public static void draw_rois(bool rois, bool thresh)
- {
- int i;
- Mat temp_frame = new Mat();
- // Ridimensiono l'immagine secondo la qualità impostata
- CvInvoke.Resize(input_frame, temp_frame, new Size(cols, rows));
- // Se il primo argomento è true disegno le ROI
- if (rois)
- {
- for (i = 0; i < 3; i++)
- {
- if (Form1.roi_selected[i])
- {
- CvInvoke.Rectangle(temp_frame, Form1.roi_area[i], rect_color[i], ((3 * resize_scale) < 1) ? 1 : (int)(3 * resize_scale));
- }
- }
- }
- // Se il secondo argomento è true disegno la LPS
- if (thresh)
- {
- CvInvoke.Line(temp_frame, Form1.tired_point_top, Form1.tired_point_bot, rect_color[2], ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
- }
- temp_frame.CopyTo(Form1.video_output);
- }
- // ----------------------------------------------
- // Metodo di aggiornamento variabili dimensionali
- // ----------------------------------------------
- public static void refresh_video_size()
- {
- rows = (int)((double)camera.GetCaptureProperty(CapProp.FrameHeight) * resize_scale);
- cols = (int)((double)camera.GetCaptureProperty(CapProp.FrameWidth) * resize_scale);
- }
- // ----------------------------------
- // Metodo di aggiornamento file video
- // ----------------------------------
- public static void change_input_file(string path)
- {
- Mat temp_frame = new Mat();
- Mat resz_frame = new Mat();
- // Elimino l'input precedente e apro il nuovo file
- camera.Dispose();
- camera = new VideoCapture(path);
- if (camera.IsOpened)
- {
- // Aggiorno le variabili dimensionali
- refresh_video_size();
- // Registro gli FPS a cui è stato registrato il video
- camera_fps = camera.GetCaptureProperty(CapProp.Fps);
- // Catturo un nuovo frame
- while (!camera.Grab()) { };
- camera.Retrieve(temp_frame);
- // Ridimensiono il frame
- CvInvoke.Resize(temp_frame, resz_frame, new Size(cols, rows));
- // Aggiorno il frame corrente
- resz_frame.CopyTo(input_frame);
- resz_frame.CopyTo(Form1.video_output);
- }
- input_mode = "file";
- }
- // ------------------------------------
- // Metodo di aggiornamento stream video
- // ------------------------------------
- public static void change_input_stream(int camera_index)
- {
- Mat temp_frame = new Mat();
- Mat resz_frame = new Mat();
- // Elimino l'input precedente e apro la nuova videocamera
- camera.Dispose();
- camera = new VideoCapture(camera_index);
- // Aggiorno le variabili dimensionali
- refresh_video_size();
- // Catturo un nuovo frame
- while (!camera.Grab()) { };
- camera.Retrieve(temp_frame);
- // Ridimensiono il frame
- CvInvoke.Resize(temp_frame, resz_frame, new Size(0, 0), resize_scale, resize_scale);
- // Aggiorno il frame corrente
- resz_frame.CopyTo(input_frame);
- resz_frame.CopyTo(Form1.video_output);
- input_mode = "stream";
- }
- // --------------------------------
- // Metodo di svuotamento lista dati
- // --------------------------------
- public static void clear_data()
- {
- index = 0;
- timer_reset = true;
- data_list.Clear();
- }
- // ----------------------------------------
- // Ciclo di acquisizione e processing frame
- // ----------------------------------------
- public static void fish_detection()
- {
- int i;
- double[] fish_timer = { 0, 0, 0 };
- long elapsed;
- data current_data;
- Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(2, 2), new Point(-1, -1));
- Mat input = new Mat();
- Mat detected = new Mat();
- Mat resized = new Mat();
- Mat blurred_input = new Mat();
- Mat[] partial_output = new Mat[3] { new Mat(), new Mat(), new Mat() };
- Mat output = new Mat();
- Mat temp_frame = new Mat();
- Mat fg_KNN = new Mat();
- Mat fg_KNN_bw = new Mat();
- BackgroundSubtractorKNN bgsKNN = new BackgroundSubtractorKNN(50, 100, true);
- MCvScalar red = new MCvScalar(0, 0, 255);
- MCvScalar green = new MCvScalar(0, 255, 0);
- MCvScalar blue = new MCvScalar(255, 0, 0);
- MCvScalar color = new MCvScalar(255);
- Moments moments;
- Point[] center = new Point[3] { new Point(0, 0), new Point(0, 0), new Point(0, 0) };
- Stopwatch stopwatch = new Stopwatch();
- Stopwatch total_time = new Stopwatch();
- DateTime[] t_fish = { DateTime.Now, DateTime.Now, DateTime.Now };
- bool[] first_cross = { true, true, true };
- double inter_frame_t, total_time_file = 0;
- DateTime t_last_frame = DateTime.Now;
- DateTime t_now = DateTime.Now;
- TimeSpan t_delta = t_now.Subtract(t_last_frame);
- while (true)
- {
- // Il ciclo di processing è controllato dal bottone "Start/Stop"
- if (Form1.running)
- {
- // Inizio a registrare il tempo passato in esecuzione per salvarlo nel file dati
- total_time.Start();
- // Gestisco problema di esecuzione troppo lenta
- while (Form1.fps == 0) { };
- inter_frame_t = Form1.inter_frame_time;
- // Aspetto il tempo necessario per il frame successivo
- while (t_delta.TotalSeconds <= inter_frame_t)
- {
- Thread.Sleep(10);
- t_now = DateTime.Now;
- t_delta = t_now.Subtract(t_last_frame);
- // Scarto i frame intermedi se sto leggendo da videocamera
- if (input_mode == "stream")
- {
- camera.Read(input_frame);
- }
- }
- // Acquisisco il frame se sto leggendo da file
- if (input_mode == "file")
- {
- camera.Read(input_frame);
- }
- // Fermo il ciclo di processing se il frame acquisito non è valido
- if (input_frame.IsEmpty)
- {
- Form1.running = false;
- Form1.eof = true;
- }
- else
- {
- t_delta = TimeSpan.Zero;
- t_last_frame = t_now;
- // Registro il tempo di esecuzione del ciclo di processing per regolare gli FPS
- stopwatch.Restart();
- // Porto il frame alla qualità desiderata
- CvInvoke.Resize(input_frame, resized, new Size(cols, rows));
- // Genero un frame nero di dimensione corretta su cui lavorare
- black_frame = Mat.Zeros(rows, cols, DepthType.Cv8U, 3);
- resized.CopyTo(detected);
- // Ripeto per le tre corsie
- for (i = 0; i < 3; i++)
- {
- // Copio la corsia corrente sul frame nero usando una maschera definita dalla ROI
- black_frame.CopyTo(input);
- resized.CopyTo(input, Form1.roi_mask[i]);
- // Riduco rumore sfocando l'immagine
- CvInvoke.GaussianBlur(input, blurred_input, new Size(21, 21), 0, 0, BorderType.Default);
- // Applico la background subtraction al frame colorato per usare anche il colore dei pesci come discriminante
- bgsKNN.Apply(blurred_input, fg_KNN);
- // Passo il frame a bw per calcolarne i momenti
- CvInvoke.Threshold(fg_KNN, fg_KNN_bw, Form1.light_threshold, 255, ThresholdType.Binary);
- fg_KNN_bw.CopyTo(partial_output[i]);
- // Eseguo un'operazione di opening sull'immagine per ridurre il rumore
- CvInvoke.Erode(partial_output[i], temp_frame, element, new Point(-1, -1), 1, BorderType.Constant, new MCvScalar(255, 255, 255));
- CvInvoke.Dilate(temp_frame, partial_output[i], element, new Point(-1, -1), 1, BorderType.Constant, new MCvScalar(255, 255, 255));
- // Rimuovo il rumore esterno generato da Dilate
- CvInvoke.Rectangle(partial_output[i], new Rectangle(0, 0, partial_output[i].Width, partial_output[i].Height), new MCvScalar(0, 0, 0), 10);
- // Calcolo i momenti
- moments = CvInvoke.Moments(partial_output[i], true);
- if (Form1.roi_selected[i])
- {
- // Calcolo il centro di massa del pesce rilevato
- center[i] = new Point((int)(moments.M10 / moments.M00), (int)(moments.M01 / moments.M00));
- // Gestisco i momenti in cui il software perde di vista il pesce
- if (center[i].X < -1)
- {
- center[i].X = -2;
- }
- Form1.fish_x[i] = center[i].X;
- // Controllo se il pesce è stanco
- if (center[i].X < Form1.tired_threshold)
- {
- color = red;
- if (first_cross[i])
- {
- t_fish[i] = DateTime.Now;
- first_cross[i] = false;
- }
- // Assegno i tempi a seconda del metodo di input
- if (input_mode == "stream")
- {
- fish_timer[i] = DateTime.Now.Subtract(t_fish[i]).TotalSeconds;
- }
- else if (input_mode == "file")
- {
- fish_timer[i] += 1 / camera_fps;
- }
- Form1.tired_timer[i] = fish_timer[i];
- }
- else
- {
- // Riporto tutto a zero se il pesce torna oltre LPS
- color = green;
- first_cross[i] = true;
- fish_timer[i] = 0;
- Form1.tired_timer[i] = 0;
- }
- }
- else
- {
- // ROI non selezionata
- center[i] = new Point(-1, -1);
- }
- // Disegno un cerchio sulla posizione rilevata
- CvInvoke.Circle(detected, center[i], ((5 * resize_scale) < 1) ? 1 : (int)(5 * resize_scale), color, ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
- }
- // Scelgo cosa mostrare a seconda che sia selezionata o no la vista detection
- if (Form1.detection_view)
- {
- CvInvoke.Add(partial_output[0], partial_output[1], temp_frame);
- CvInvoke.Add(partial_output[2], temp_frame, output);
- }
- else
- {
- detected.CopyTo(output);
- }
- // Disegno LPS sul frame in uscita
- CvInvoke.Line(output, Form1.tired_point_top, Form1.tired_point_bot, red, ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
- // Disegno le ROI se il ciclo si sta fermando
- if (!Form1.running)
- {
- for (i = 0; i < 3; i++)
- {
- if (Form1.roi_selected[i])
- {
- CvInvoke.Rectangle(output, Form1.roi_area[i], rect_color[i], ((3 * resize_scale) < 1) ? 1 : (int)(3 * resize_scale));
- }
- }
- }
- output.CopyTo(Form1.video_output);
- stopwatch.Stop();
- elapsed = stopwatch.ElapsedMilliseconds;
- // setto gli fps massimi relativi al tempo di processing del frame corrente (margine 2x)
- if(elapsed >= 1)
- {
- if ((int)(1000 / (2 * (elapsed))) > 0)
- {
- Form1.max_fps = (int)(1000 / (2 * (elapsed)));
- }
- else
- {
- Form1.max_fps = 0;
- MessageBox.Show("Processing took too long. Try stopping, reloading file or stream and lowering quality");
- }
- }
- else
- {
- Form1.max_fps = 500;
- }
- total_time_file += 1000 / camera_fps;
- if (timer_reset)
- {
- total_time.Reset();
- timer_reset = false;
- }
- // Salvo tutti i dati utili
- 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]);
- data_list.Add(current_data);
- }
- }
- else
- {
- // Fermo la registrazione del tempo se il ciclo non è in esecuzione
- total_time.Stop();
- }
- }
- }
- // -----------------------
- // Metodo di selezione ROI
- // -----------------------
- public static void set_roi()
- {
- Mat temp_frame = new Mat();
- int i;
- int roi = Form1.roi_selection;
- // Ridimensiono il frame corrente alla qualità corretta
- CvInvoke.Resize(input_frame, temp_frame, new Size(cols, rows));
- // Finchè non rilascio il tasto del mouse sull'immagine eseguo questo ciclo
- while (!Form1.roi_selected[roi])
- {
- if (Form1.image_clicked)
- {
- // Ridimensiono il frame corrente alla qualità corretta
- CvInvoke.Resize(input_frame, temp_frame, new Size(cols, rows));
- // L'oggetto Rectangle considera il primo angolo come il superiore sinistro,
- // quindi se la ROI è stata disegnata diversamente sull'immagine devo
- // trovare quale punto utilizzare per definire il rettangolo.
- if ((Form1.roi_corner_1.X < Form1.mouseX) && (Form1.roi_corner_1.Y < Form1.mouseY))
- {
- 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);
- }
- else if ((Form1.roi_corner_1.X >= Form1.mouseX) && (Form1.roi_corner_1.Y < Form1.mouseY))
- {
- 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);
- }
- else if ((Form1.roi_corner_1.X >= Form1.mouseX) && (Form1.roi_corner_1.Y >= Form1.mouseY))
- {
- Form1.roi_area[roi] = new Rectangle(Form1.mouseX, Form1.mouseY, Form1.roi_corner_1.X - Form1.mouseX, Form1.roi_corner_1.Y - Form1.mouseY);
- }
- else if ((Form1.roi_corner_1.X < Form1.mouseX) && (Form1.roi_corner_1.Y >= Form1.mouseY))
- {
- 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);
- }
- }
- // Disegno le ROI
- for (i = 0; i < 3; i++)
- {
- CvInvoke.Rectangle(temp_frame, Form1.roi_area[i], rect_color[i], ((3 * resize_scale) < 1) ? 1 : (int)(3 * resize_scale));
- }
- // Disegno la LPS
- CvInvoke.Line(temp_frame, Form1.tired_point_top, Form1.tired_point_bot, rect_color[2], ((2 * resize_scale) < 1) ? 1 : (int)(2 * resize_scale));
- temp_frame.CopyTo(Form1.video_output);
- }
- temp_frame.CopyTo(Form1.video_output);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement