TesteCaminhao/TesteImagemCaminhao/WheelsDetectionService.cs
2025-03-17 11:13:59 -03:00

217 lines
8.0 KiB
C#

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using TesteImagemCaminhao;
namespace VehicleDetectionAPI
{
public class WheelsDetectionService : IWheelsDetectionService
{
private readonly HttpClient _httpClient;
private readonly string _apiUrl;
private readonly string _apiKey;
public WheelsDetectionService(IConfiguration configuration)
{
_httpClient = new HttpClient();
_apiUrl = configuration["ComputerVision:ApiUrl"];
_apiKey = configuration["ComputerVision:ApiKey"];
}
public async Task<int> DetectWheelsCount(string imagePath)
{
try
{
// Método 1: Usar detecção de objetos para identificar rodas diretamente
// (método mais preciso se tivermos um modelo treinado para isso)
int wheelsCount = await DetectWheelsUsingObjectDetection(imagePath);
// Se o método anterior não detectar rodas, usar método alternativo
if (wheelsCount == 0)
{
// Método 2: Estimar com base em detecção de contornos e recursos geométricos
wheelsCount = DetectWheelsUsingContours(imagePath);
}
return wheelsCount;
}
catch (Exception ex)
{
Console.WriteLine($"Erro na detecção de rodas: {ex.Message}");
return EstimateDefaultWheelsCount(imagePath); // Fallback para estimativa padrão
}
}
public async Task<int> DetectWheelsCountOld(string imagePath)
{
try
{
// Método 1: Usar detecção de objetos para identificar rodas diretamente
// (método mais preciso se tivermos um modelo treinado para isso)
int wheelsCount = await DetectWheelsUsingObjectDetection(imagePath);
// Se o método anterior não detectar rodas, usar método alternativo
if (wheelsCount == 0)
{
// Método 2: Estimar com base em detecção de contornos e recursos geométricos
wheelsCount = DetectWheelsUsingContours(imagePath);
}
return wheelsCount;
}
catch (Exception ex)
{
Console.WriteLine($"Erro na detecção de rodas: {ex.Message}");
return EstimateDefaultWheelsCount(imagePath); // Fallback para estimativa padrão
}
}
private async Task<int> DetectWheelsUsingObjectDetection(string imagePath)
{
// Esta função envia a imagem para um serviço de detecção de objetos
// como Azure Custom Vision, Yolo ou um modelo ML personalizado
// Exemplo de integração com o Azure Custom Vision:
try
{
using var fileStream = new FileStream(imagePath, FileMode.Open);
using var content = new StreamContent(fileStream);
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
// Adicionar a chave de API ao cabeçalho
_httpClient.DefaultRequestHeaders.Add("Prediction-Key", _apiKey);
// Enviar a imagem para o serviço
var response = await _httpClient.PostAsync(_apiUrl, content);
response.EnsureSuccessStatusCode();
// Analisar a resposta
var result = await response.Content.ReadAsStringAsync();
var detectionResult = JsonConvert.DeserializeObject<DetectionResult>(result);
// Contar apenas objetos detectados como "roda" com confiança > 0.5
int wheelsCount = detectionResult.Predictions
.Count(p => p.TagName.ToLower() == "roda" && p.Probability > 0.5);
return wheelsCount;
}
catch
{
// Se falhar, retornar 0 para que o método alternativo seja usado
return 0;
}
}
private int DetectWheelsUsingContours(string imagePath)
{
// Implementação simplificada usando processamento de imagem básico
// Em um ambiente real, usaríamos uma biblioteca de visão computacional como OpenCV
// Esta é uma implementação simulada
// Em produção, usaríamos algoritmos para:
// 1. Converter para escala de cinza
// 2. Aplicar detecção de bordas (Canny)
// 3. Encontrar contornos circulares (HoughCircles)
// 4. Filtrar por tamanho e posição para identificar rodas
// Como exemplo, retornamos um valor baseado no tipo de veículo detectado
using (var bitmap = new Bitmap(imagePath))
{
// Análise básica da imagem para simular processamento
// Em um sistema real, este seria um algoritmo complexo
// Se a imagem for larga (proporção > 2:1), provavelmente é um caminhão
if (bitmap.Width > bitmap.Height * 2)
{
return 6; // Estimar rodas para um caminhão
}
// Se for mais alta que larga, pode ser uma moto
else if (bitmap.Height > bitmap.Width)
{
return 2; // Estimar rodas para uma moto
}
else
{
return 4; // Estimar rodas para um carro
}
}
}
private int EstimateDefaultWheelsCount(string imagePath)
{
// Análise simples da imagem para fazer uma estimativa padrão
using (var bitmap = new Bitmap(imagePath))
{
// Detectar cor predominante para estimar o tipo de veículo
Color predominantColor = GetPredominantColor(bitmap);
// Tamanho da imagem
var size = bitmap.Width * bitmap.Height;
// Estimativa baseada na cor e tamanho
if (size < 100000) // Imagem pequena
return 2; // Possivelmente uma moto
else if (size > 500000) // Imagem grande
return 6; // Possivelmente um caminhão
else
return 4; // Padrão para carros
}
}
private Color GetPredominantColor(Bitmap bitmap)
{
// Método simplificado para obter cor predominante
int r = 0, g = 0, b = 0;
int total = 0;
// Amostragem de pixels
for (int x = 0; x < bitmap.Width; x += 10)
{
for (int y = 0; y < bitmap.Height; y += 10)
{
var pixel = bitmap.GetPixel(x, y);
r += pixel.R;
g += pixel.G;
b += pixel.B;
total++;
}
}
// Calcular média
return Color.FromArgb(r / total, g / total, b / total);
}
}
// Classe para deserializar a resposta da API de detecção de objetos
public class DetectionResult
{
public string Id { get; set; }
public string Project { get; set; }
public string Iteration { get; set; }
public DateTime Created { get; set; }
public Prediction[] Predictions { get; set; }
}
public class Prediction
{
public float Probability { get; set; }
public string TagId { get; set; }
public string TagName { get; set; }
public BoundingBox BoundingBox { get; set; }
}
public class BoundingBox
{
public float Left { get; set; }
public float Top { get; set; }
public float Width { get; set; }
public float Height { get; set; }
}
}