Cambiado funcionamiento de BuscarCoincidencias para guardar el clip original.

This commit is contained in:
Miguel 2025-02-25 21:36:07 +01:00
parent 3fe845b02f
commit b6b078f8ce
1 changed files with 295 additions and 27 deletions

View File

@ -95,6 +95,33 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
Search_templates = false;
}
[ObservableProperty]
[property: Category("Tag Extraction:")]
bool tomarClip;
// En lugar de almacenar Mat directamente, guardaremos una representación serializable
[ObservableProperty]
[property: Category("Tag Extraction:")]
byte[] capturedRegionData;
[ObservableProperty]
[property: Category("Tag Extraction:")]
[property: ReadOnly(true)]
bool regionCapturada;
// Para uso interno (no serializado)
[JsonIgnore]
private Mat _capturedRegion;
// Propiedades para almacenar las dimensiones de la captura
[ObservableProperty]
[property: Category("Tag Extraction:")]
int capturedWidth;
[ObservableProperty]
[property: Category("Tag Extraction:")]
int capturedHeight;
[ObservableProperty]
[property: Category("Tag Extraction:")]
bool export_ocr;
@ -103,6 +130,200 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
[property: Category("Tag Extraction:")]
string text_export_ocr;
// Esta propiedad manejará la conversión entre Mat y datos serializables
[JsonIgnore]
public Mat CapturedRegion
{
get
{
if (_capturedRegion == null && CapturedRegionData != null && CapturedRegionData.Length > 0)
{
// Recrear Mat desde los datos almacenados
_capturedRegion = BytesToMat(CapturedRegionData, CapturedWidth, CapturedHeight);
}
return _capturedRegion;
}
set
{
if (value != null)
{
// Convertir Mat a bytes para serialización
CapturedRegionData = MatToBytes(value);
CapturedWidth = value.Width;
CapturedHeight = value.Height;
_capturedRegion = value;
}
else
{
CapturedRegionData = null;
CapturedWidth = 0;
CapturedHeight = 0;
_capturedRegion = null;
}
}
}
partial void OnTomarClipChanged(bool oldValue, bool newValue)
{
if (tomarClip)
{
CapturarRegionActual();
TomarClip = false; // Resetear el flag después de la captura
}
}
// Método para capturar la región actual
private void CapturarRegionActual()
{
Application.Current.Dispatcher.Invoke(() =>
{
if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo)
{
if (imagenDeFondo.Source is BitmapSource bitmapSource)
{
// Obtener los DPI de la imagen original
float originalDpiX = (float)bitmapSource.DpiX;
float originalDpiY = (float)bitmapSource.DpiY;
// Estándar DPI en el que el Canvas renderiza la imagen
float canvasDpiX = 96;
float canvasDpiY = 96;
// Calcular el ratio de escala entre el Canvas y la imagen original
float scaleFactorX = originalDpiX / canvasDpiX;
float scaleFactorY = originalDpiY / canvasDpiY;
// Ajustar las coordenadas de recorte en función del ratio de escala
int x = (int)MeterToPixels(Left * scaleFactorX);
int y = (int)MeterToPixels(Top * scaleFactorY);
int width = (int)MeterToPixels(Ancho * scaleFactorX);
int height = (int)MeterToPixels(Alto * scaleFactorY);
// Validar y ajustar el tamaño del recorte para que se mantenga dentro de los límites de la imagen
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x;
if (y + height > bitmapSource.PixelHeight) height = bitmapSource.PixelHeight - y;
// Recortar el área deseada utilizando las coordenadas ajustadas
CroppedBitmap croppedBitmap = new CroppedBitmap(bitmapSource, new Int32Rect(x, y, width, height));
// Capturar la región y almacenarla
if (_capturedRegion != null)
{
_capturedRegion.Dispose(); // Liberar recursos previos
}
// Usar la propiedad que maneja la serialización
CapturedRegion = BitmapSourceToMat(croppedBitmap);
// Actualizar el estado
RegionCapturada = true;
MessageBox.Show("Región capturada correctamente.", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
});
}
// Métodos para convertir entre Mat y bytes
private byte[] MatToBytes(Mat mat)
{
if (mat == null)
return null;
// Asegurar que tenemos un formato consistente para serialización
Mat bgr = new Mat();
if (mat.NumberOfChannels != 3)
{
CvInvoke.CvtColor(mat, bgr, mat.NumberOfChannels == 1 ?
ColorConversion.Gray2Bgr : ColorConversion.Bgra2Bgr);
}
else
{
bgr = mat.Clone();
}
// Convertir a un formato que pueda ser serializado
using (MemoryStream ms = new MemoryStream())
{
// Convertir Mat a Bitmap
Bitmap bitmap = bgr.ToBitmap();
// Guardar como PNG (sin pérdida de calidad)
bitmap.Save(ms, ImageFormat.Png);
// Liberar recursos
bitmap.Dispose();
if (bgr != mat)
bgr.Dispose();
return ms.ToArray();
}
}
private Mat BytesToMat(byte[] bytes, int width, int height)
{
if (bytes == null || bytes.Length == 0)
return null;
try
{
using (MemoryStream ms = new MemoryStream(bytes))
{
// Cargar imagen desde bytes
Bitmap bitmap = (Bitmap)System.Drawing.Image.FromStream(ms);
// Convertir Bitmap a Mat
Image<Bgr, byte> img = bitmap.ToImage<Bgr, byte>();
// Liberar recursos
bitmap.Dispose();
// Si las dimensiones no coinciden, redimensionar
if (img.Width != width || img.Height != height)
{
CvInvoke.Resize(img.Mat, img.Mat, new Size(width, height));
}
return img.Mat;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Error al reconstruir Mat: {ex.Message}");
return null;
}
}
// Sobrescribir los métodos de cambio de tamaño para limpiar la región capturada
public override void AnchoChanged(float newValue)
{
base.AnchoChanged(newValue);
//LimpiarRegionCapturada();
}
public override void AltoChanged(float newValue)
{
base.AnchoChanged(newValue);
// LimpiarRegionCapturada();
}
private void LimpiarRegionCapturada()
{
if (_capturedRegion != null)
{
_capturedRegion.Dispose();
_capturedRegion = null;
}
// Usar la propiedad para manejar la serialización
CapturedRegion = null;
RegionCapturada = false;
}
partial void OnExport_ocrChanged(bool value)
{
if (Export_ocr)
@ -211,6 +432,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
progressDialog.Show();
}
// Modificar el método BuscarCoincidenciasAsync para usar la región capturada si está disponible
private void BuscarCoincidenciasAsync(ProgressDialog progressDialog)
{
// Reset the Canvas children
@ -221,41 +443,69 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
{
_mainViewModel.MainCanvas.Children.Remove(shape);
}
if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo)
{
// Asegurarse de que la imagen origen está disponible
if (imagenDeFondo.Source is BitmapSource bitmapSource)
{
progressDialog.ReportProgress(10);
// Obtener los DPI de la imagen original
float originalDpiX = (float)bitmapSource.DpiX;
float originalDpiY = (float)bitmapSource.DpiY;
// Estándar DPI en el que el Canvas renderiza la imagen
float canvasDpiX = 96; // WPF usually renders at 96 DPI
float canvasDpiY = 96;
Mat templateMat;
int width, height;
float scaleFactorX, scaleFactorY;
bool deleteTemplateMat = false;
// Calcular el ratio de escala entre el Canvas y la imagen original
float scaleFactorX = originalDpiX / canvasDpiX;
float scaleFactorY = originalDpiY / canvasDpiY;
// Usar la región capturada si existe, de lo contrario capturar la región actual
if (CapturedRegion != null && RegionCapturada)
{
// Usar la región almacenada (ya deserializada)
templateMat = CapturedRegion.Clone();
deleteTemplateMat = true;
width = templateMat.Width;
height = templateMat.Height;
// Ajustar las coordenadas de recorte en función del ratio de escala
int x = (int)MeterToPixels(Left * scaleFactorX);
int y = (int)MeterToPixels(Top * scaleFactorY);
int width = (int)MeterToPixels(Ancho * scaleFactorX);
int height = (int)MeterToPixels(Alto * scaleFactorY);
// Para mantener la relación con la imagen original
float originalDpiX = (float)bitmapSource.DpiX;
float originalDpiY = (float)bitmapSource.DpiY;
float canvasDpiX = 96;
float canvasDpiY = 96;
scaleFactorX = originalDpiX / canvasDpiX;
scaleFactorY = originalDpiY / canvasDpiY;
}
else
{
// Obtener los DPI de la imagen original
float originalDpiX = (float)bitmapSource.DpiX;
float originalDpiY = (float)bitmapSource.DpiY;
// Validar y ajustar el tamaño del recorte para que se mantenga dentro de los límites de la imagen
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x;
if (y + height > bitmapSource.PixelHeight) height = bitmapSource.PixelHeight - y;
// Estándar DPI en el que el Canvas renderiza la imagen
float canvasDpiX = 96;
float canvasDpiY = 96;
// Recortar el área deseada utilizando las coordenadas ajustadas
CroppedBitmap croppedBitmap = new CroppedBitmap(bitmapSource, new Int32Rect(x, y, width, height));
// Calcular el ratio de escala entre el Canvas y la imagen original
scaleFactorX = originalDpiX / canvasDpiX;
scaleFactorY = originalDpiY / canvasDpiY;
// Convertir CroppedBitmap a Mat directamente
Mat templateMat = BitmapSourceToMat(croppedBitmap);
// Ajustar las coordenadas de recorte en función del ratio de escala
int x = (int)MeterToPixels(Left * scaleFactorX);
int y = (int)MeterToPixels(Top * scaleFactorY);
width = (int)MeterToPixels(Ancho * scaleFactorX);
height = (int)MeterToPixels(Alto * scaleFactorY);
// Validar y ajustar el tamaño del recorte para que se mantenga dentro de los límites de la imagen
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x;
if (y + height > bitmapSource.PixelHeight) height = bitmapSource.PixelHeight - y;
// Recortar el área deseada utilizando las coordenadas ajustadas
CroppedBitmap croppedBitmap = new CroppedBitmap(bitmapSource, new Int32Rect(x, y, width, height));
// Convertir CroppedBitmap a Mat directamente
templateMat = BitmapSourceToMat(croppedBitmap);
deleteTemplateMat = true;
}
int scale = 4;
@ -265,6 +515,9 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
Mat templateGrayResized = new Mat();
CvInvoke.Resize(templateGray, templateGrayResized, new Size(templateGray.Width / scale, templateGray.Height / scale), 0, 0, Inter.Linear);
progressDialog.ReportProgress(20);
// El resto del código permanece igual...
// Cargar la imagen principal completa en un Mat
Mat mainImageMat = BitmapSourceToMat(bitmapSource);
@ -293,9 +546,6 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
else
search_rectangles = new List<Rect>();
// Añadir el rectángulo usado por croppedBitmap a search_rectangles
//search_rectangles.Add(new Rect(x / scaleFactorX, y / scaleFactorY, width / scaleFactorX, height / scaleFactorY));
// Obtener los puntos que superan el umbral
float[] resultArray = result.GetData(false) as float[];
if (resultArray != null)
@ -342,18 +592,36 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
Coincidencias = ConteoPositivos;
progressDialog.ReportProgress(90);
if (ConteoPositivos > 20)
{
// Liberar recursos antes de salir
if (deleteTemplateMat) templateMat.Dispose();
templateGray.Dispose();
templateGrayResized.Dispose();
mainImageMat.Dispose();
mainImageGray.Dispose();
mainImageGrayResized.Dispose();
result.Dispose();
return;
}
}
}
}
PopularTagExtraction();
}
// Limpiar recursos
if (deleteTemplateMat) templateMat.Dispose();
templateGray.Dispose();
templateGrayResized.Dispose();
mainImageMat.Dispose();
mainImageGray.Dispose();
mainImageGrayResized.Dispose();
result.Dispose();
}
}
});
}
public void PopularTagExtraction()
{
var objetosSimulablesCopy = new List<osBase>(_mainViewModel.ObjetosSimulables);