295 lines
10 KiB
C#
295 lines
10 KiB
C#
using AgroBase.Services;
|
|
using Microsoft.Web.WebView2.WinForms;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace AgroBase.Models
|
|
{
|
|
public class CameraCaminhoModel
|
|
{
|
|
public Bitmap bitmapSegmentado;
|
|
|
|
public string ID { get; set; }
|
|
public string Nome { get; set; }
|
|
public int Posicao { get; set; }
|
|
public bool Iniciada { get; set; } = false;
|
|
public CameraService camera { get; set; }
|
|
public WebView2 browserRgb { get; set; }
|
|
public Panel panelRgb { get; set; }
|
|
public WebView2 browserHeatmap { get; set; }
|
|
public Panel panelHeatmap { get; set; }
|
|
public ComboBox combo { get; set; }
|
|
public string ArquivoLeitura { get; set; }
|
|
public int MaxLeituras { get; set; }
|
|
public string VideoPorta { get; set; }
|
|
public string VideoRgbUrl { get; set; }
|
|
public string VideoHeatmapUrl { get; set; }
|
|
public string DeviceID { get; set; }
|
|
public string MqttTopico { get; set; } = "street_detector";
|
|
|
|
public Dictionary<string, Color> ClassMap = new Dictionary<string, Color>()
|
|
{
|
|
{ "background", Color.Black },
|
|
{ "rua", Color.DarkRed },
|
|
{ "cana", Color.DarkGreen },
|
|
{ "ceu", Color.Gold },
|
|
};
|
|
|
|
public CameraDeepLabV3PlusModel Leitura { get; set; } = new CameraDeepLabV3PlusModel();
|
|
public List<Point> PontosExtremos { get; set; } = new List<Point>();
|
|
public double Angulo { get; set; }
|
|
public double AnguloEsquerdo { get; set; }
|
|
public double AnguloDireito { get; set; }
|
|
|
|
public DateTime UltimaMensagemRecebida { get; set; } = DateTime.MinValue;
|
|
public DateTime UltimaMensagemProcessada { get; set; } = DateTime.MinValue;
|
|
|
|
public SonarCamModel Sonar { get; set; } = new SonarCamModel();
|
|
|
|
|
|
|
|
|
|
|
|
public void DesligarCamera()
|
|
{
|
|
try
|
|
{
|
|
Iniciada = false;
|
|
Variaveis.MqttServiceLocal.Topicos.Remove(camera._mqttTopico);
|
|
if (panelRgb != null)
|
|
{
|
|
panelRgb.Controls.Remove(browserRgb);
|
|
}
|
|
browserRgb = null;
|
|
Task.Run(async () => await Variaveis.MqttServiceLocal.UnsubscribeAsync(camera._mqttTopico));
|
|
|
|
lock (camera.processLock)
|
|
{
|
|
if (camera.pythonProcess != null)
|
|
{
|
|
camera.pythonProcess.Kill();
|
|
camera.pythonProcess = null;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.Message);
|
|
}
|
|
}
|
|
|
|
public static List<Point> DefinirPontosExtremos(List<Point> PontosCamera)
|
|
{
|
|
if (!PontosCamera.Any())
|
|
{
|
|
return new List<Point>();
|
|
}
|
|
List<Point> Pontos = new List<Point>()
|
|
{
|
|
new Point(9999, -1), // Ponto 0 - Mais a esquerda e abaixo
|
|
new Point(9999, -1), // Ponto 1 - Mais a esquerda e abaixo, e esquerda > Ponto0.X
|
|
new Point(9999, 9999), // Ponto 2 - Mais a esquerda e acima
|
|
new Point(-1, 9999), // Ponto 3 - Mais a direita e acima
|
|
new Point(-1, -1), // Ponto 4 - Mais a direita e abaixo, e direita < Ponto5.X
|
|
new Point(-1, -1), // Ponto 5 - Mais a direita e abaixo
|
|
};
|
|
|
|
foreach (var Ponto in PontosCamera)
|
|
{
|
|
// Ponto 0 - Mais a esquerda e abaixo
|
|
if (Ponto.X < Pontos[0].X)
|
|
{
|
|
Pontos[0] = new Point() { X = Ponto.X, Y = Ponto.Y };
|
|
}
|
|
// Ponto 5 - Mais a direita e abaixo
|
|
if (Ponto.X > Pontos[5].X)
|
|
{
|
|
Pontos[5] = new Point() { X = Ponto.X, Y = Ponto.Y };
|
|
}
|
|
}
|
|
var Ponto0 = PontosCamera.Where(Ponto => Ponto.X == Pontos[0].X).OrderByDescending(Ponto => Ponto.Y).First();
|
|
Pontos[0] = Ponto0;
|
|
var Ponto5 = PontosCamera.Where(Ponto => Ponto.X == Pontos[5].X).OrderByDescending(Ponto => Ponto.Y).First();
|
|
Pontos[5] = Ponto5;
|
|
|
|
foreach (var Ponto in PontosCamera)
|
|
{
|
|
// Ponto 1 - Mais a esquerda e abaixo, e esquerda > Ponto0.X
|
|
if (Ponto.X < Pontos[1].X && Ponto.X > Ponto0.X)
|
|
{
|
|
Pontos[1] = new Point() { X = Ponto.X, Y = Ponto.Y };
|
|
}
|
|
// Ponto 4 Mais a direita e abaixo, e direita < Ponto5.X
|
|
if (Ponto.X > Pontos[4].X && Ponto.X < Ponto5.X)
|
|
{
|
|
Pontos[4] = new Point() { X = Ponto.X, Y = Ponto.Y };
|
|
}
|
|
}
|
|
var Ponto1 = PontosCamera.Where(Ponto => Ponto.X == Pontos[1].X).OrderByDescending(Ponto => Ponto.Y).First();
|
|
Pontos[1] = Ponto1;
|
|
var Ponto4 = PontosCamera.Where(Ponto => Ponto.X == Pontos[4].X).OrderByDescending(Ponto => Ponto.Y).First();
|
|
Pontos[4] = Ponto4;
|
|
|
|
int Y_min = PontosCamera.OrderBy(Ponto => Ponto.Y).First().Y;
|
|
foreach (var Ponto in PontosCamera.Where(x => x.Y == Y_min))
|
|
{
|
|
// Ponto 2 - Mais a esquerda e acima
|
|
if (Ponto.X < Pontos[2].X)
|
|
{
|
|
Pontos[2] = new Point() { X = Ponto.X, Y = Ponto.Y };
|
|
}
|
|
// Ponto 3 - Mais a direita e acima
|
|
if (Ponto.X > Pontos[3].X)
|
|
{
|
|
Pontos[3] = new Point() { X = Ponto.X, Y = Ponto.Y };
|
|
}
|
|
}
|
|
|
|
return Pontos;
|
|
}
|
|
|
|
// 🔹 Gera um mapa de calor corretamente escalado
|
|
public Bitmap GenerateHeatmapBitmap()
|
|
{
|
|
double MaxDepth = 10000;
|
|
var depth_data = Leitura.depth_data;
|
|
|
|
if (depth_data == null || depth_data.Count == 0)
|
|
{
|
|
return null;
|
|
//throw new InvalidOperationException("Dados de profundidade inválidos.");
|
|
}
|
|
|
|
int height = depth_data.Count;
|
|
int width = depth_data[0].Count;
|
|
|
|
Bitmap heatmap = new Bitmap(width, height);
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int depth = depth_data[y][x];
|
|
|
|
// 🔹 Normaliza a profundidade entre 0 (vermelho, perto) e 10.000 mm (azul, longe)
|
|
int normalized = (int)FuncoesMatematicas.Clamp(255 - ((depth * 255) / MaxDepth), 0, 255);
|
|
|
|
Color color = ApplyJetColormap(normalized);
|
|
heatmap.SetPixel(x, y, color);
|
|
}
|
|
}
|
|
|
|
return heatmap;
|
|
}
|
|
|
|
// 🔹 Função para converter um valor normalizado (0-255) para um colormap "Jet" correto
|
|
private Color ApplyJetColormap(int value)
|
|
{
|
|
double normalized = value / 255.0;
|
|
|
|
int r = (int)(FuncoesMatematicas.Clamp(255 * Math.Max(0, Math.Min(1, 1.5 - Math.Abs(normalized * 2 - 1.5))), 0, 255));
|
|
int g = (int)(FuncoesMatematicas.Clamp(255 * Math.Max(0, Math.Min(1, 1.5 - Math.Abs(normalized * 2 - 1.0))), 0, 255));
|
|
int b = (int)(FuncoesMatematicas.Clamp(255 * Math.Max(0, Math.Min(1, 1.5 - Math.Abs(normalized * 2 - 0.5))), 0, 255));
|
|
|
|
return Color.FromArgb(r, g, b);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public class GridMap
|
|
{
|
|
public int x_max { get; set; }
|
|
public int y_max { get; set; }
|
|
public Subdivisoes subdivisoes_cima { get; set; }
|
|
public Subdivisoes subdivisoes_chao { get; set; }
|
|
}
|
|
|
|
public class Subdivisoes
|
|
{
|
|
public int num_linhas { get; set; }
|
|
public int num_colunas { get; set; }
|
|
public List<Celula> celulas { get; set; }
|
|
}
|
|
|
|
public class Celula
|
|
{
|
|
public int linha { get; set; }
|
|
public int coluna { get; set; }
|
|
public int x { get; set; }
|
|
public int y { get; set; }
|
|
public int largura { get; set; }
|
|
public int altura { get; set; }
|
|
public double profundidade_calibragem { get; set; }
|
|
public double profundidade_media { get; set; }
|
|
public double dif_profundidade
|
|
{
|
|
get
|
|
{
|
|
return profundidade_media - profundidade_calibragem;
|
|
}
|
|
}
|
|
public Color cor
|
|
{
|
|
get
|
|
{
|
|
double margem = 200;
|
|
|
|
if (dif_profundidade < margem)
|
|
{
|
|
return Color.Red;
|
|
}
|
|
else if (dif_profundidade > margem)
|
|
{
|
|
return Color.Gold;
|
|
}
|
|
|
|
return Color.Transparent;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class GridDrawer
|
|
{
|
|
public static GridMap LoadJson(string json)
|
|
{
|
|
return JsonConvert.DeserializeObject<GridMap>(json);
|
|
}
|
|
|
|
public static Bitmap DrawGridOnBitmap(GridMap gridMap, Bitmap image)
|
|
{
|
|
Bitmap output = new Bitmap(image);
|
|
using (Graphics g = Graphics.FromImage(output))
|
|
{
|
|
foreach (var celula in gridMap.subdivisoes_chao.celulas)
|
|
{
|
|
using (Brush brush = new SolidBrush(Color.FromArgb(100, celula.cor))) // 100 = opacidade
|
|
{
|
|
g.FillRectangle(brush, celula.x, celula.y, celula.largura, celula.altura);
|
|
}
|
|
g.DrawRectangle(Pens.White, celula.x, celula.y, celula.largura, celula.altura);
|
|
}
|
|
|
|
foreach (var celula in gridMap.subdivisoes_cima.celulas)
|
|
{
|
|
using (Brush brush = new SolidBrush(Color.FromArgb(100, celula.cor)))
|
|
{
|
|
g.FillRectangle(brush, celula.x, celula.y, celula.largura, celula.altura);
|
|
}
|
|
g.DrawRectangle(Pens.White, celula.x, celula.y, celula.largura, celula.altura);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|