diff --git a/App.xaml b/App.xaml
index d7b127d..7bf6453 100644
--- a/App.xaml
+++ b/App.xaml
@@ -2,6 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CtrEditor"
+ xmlns:os="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
StartupUri="MainWindow.xaml">
@@ -17,6 +18,8 @@
+
+
diff --git a/CtrEditor.csproj b/CtrEditor.csproj
index 92df0d6..9226bf9 100644
--- a/CtrEditor.csproj
+++ b/CtrEditor.csproj
@@ -66,6 +66,9 @@
+
+
+
diff --git a/MainWindow.xaml b/MainWindow.xaml
index d9b4ef6..615722a 100644
--- a/MainWindow.xaml
+++ b/MainWindow.xaml
@@ -178,8 +178,7 @@
ResizeDirection="Rows" VerticalAlignment="Center" />
-
+
@@ -231,6 +230,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ObjetosSim/Extraccion Datos/ucBuscarCoincidencias.xaml b/ObjetosSim/Extraccion Datos/ucBuscarCoincidencias.xaml
new file mode 100644
index 0000000..56e7ff4
--- /dev/null
+++ b/ObjetosSim/Extraccion Datos/ucBuscarCoincidencias.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
diff --git a/ObjetosSim/Extraccion Datos/ucBuscarCoincidencias.xaml.cs b/ObjetosSim/Extraccion Datos/ucBuscarCoincidencias.xaml.cs
new file mode 100644
index 0000000..a5085eb
--- /dev/null
+++ b/ObjetosSim/Extraccion Datos/ucBuscarCoincidencias.xaml.cs
@@ -0,0 +1,354 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CtrEditor.Simulacion;
+using System.IO;
+using System.Windows.Media.Imaging;
+using Tesseract;
+using Emgu.CV.CvEnum;
+using Emgu.CV.Structure;
+using Emgu.CV;
+using System.Drawing;
+using Image = System.Windows.Controls.Image;
+using Point = System.Drawing.Point;
+using Rectangle = System.Windows.Shapes.Rectangle;
+using Size = System.Drawing.Size;
+using Ookii.Dialogs.Wpf;
+
+
+namespace CtrEditor.ObjetosSim.Extraccion_Datos
+{
+ ///
+ /// Interaction logic for ucBuscarCoincidencias.xaml
+ ///
+ ///
+
+ public partial class osBuscarCoincidencias : osBase, IosBase
+ {
+ private osBase _osMotor = null;
+
+ private simTransporte SimGeometria;
+
+ public static string NombreClase()
+ {
+ return "Search Templates";
+ }
+ private string nombre = NombreClase();
+ public override string Nombre
+ {
+ get => nombre;
+ set => SetProperty(ref nombre, value);
+ }
+
+ [ObservableProperty]
+ bool search_templates;
+
+ partial void OnSearch_templatesChanged(bool oldValue, bool newValue)
+ {
+ if (Search_templates)
+ BuscarCoincidencias();
+ Search_templates = false;
+ }
+
+ public override void TopChanged(float value)
+ {
+ base.TopChanged(value);
+ Search_templates = false;
+ }
+
+ public override void LeftChanged(float value)
+ {
+ base.LeftChanged(value);
+ Search_templates = false;
+ }
+
+
+ [ObservableProperty]
+ public float ancho;
+
+ partial void OnAnchoChanged(float value)
+ {
+ Search_templates = false;
+ }
+
+ [ObservableProperty]
+ public float alto;
+
+ partial void OnAltoChanged(float value)
+ {
+ Search_templates = false;
+ }
+
+ public override void OnTimerAfterMovement()
+ {
+ }
+
+ [ObservableProperty]
+ public int n_Repeat_X;
+
+ [ObservableProperty]
+ public int n_Repeat_Y;
+
+ [ObservableProperty]
+ public float offset_Repeat_X;
+
+ [ObservableProperty]
+ public float offset_Repeat_Y;
+
+ [ObservableProperty]
+ public float angulo;
+
+ [ObservableProperty]
+ string tag_extract;
+
+ [ObservableProperty]
+ string clase;
+
+ [ObservableProperty]
+ string tag_name;
+
+ [ObservableProperty]
+ float opacity_oculto;
+
+ [ObservableProperty]
+ bool show_debug_ocr;
+
+ [ObservableProperty]
+ float threshold;
+
+ public osBuscarCoincidencias()
+ {
+ Ancho = 1;
+ Alto = 1;
+ Angulo = 0;
+ Opacity_oculto = 0.1f;
+ }
+
+ private void ShowPreviewWindow(Stream imageStream)
+ {
+ // Create a new window for preview
+ Window previewWindow = new Window
+ {
+ Title = "Preview Captured Image",
+ Width = 500,
+ Height = 500,
+ Content = new Image
+ {
+ Source = BitmapFrame.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad),
+ Stretch = Stretch.Uniform
+ }
+ };
+
+ previewWindow.ShowDialog();
+ }
+
+ private async void BuscarCoincidencias()
+ {
+ var progressDialog = new ProgressDialog
+ {
+ WindowTitle = "Procesando",
+ Text = "Buscando coincidencias...",
+ ShowTimeRemaining = true,
+ ShowCancelButton = false
+ };
+ progressDialog.DoWork += (sender, e) => BuscarCoincidenciasAsync(progressDialog);
+ progressDialog.RunWorkerCompleted += (sender, e) =>
+ {
+ if (e.Error != null)
+ {
+ MessageBox.Show(e.Error.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ };
+
+ progressDialog.Show();
+ }
+
+
+ private void BuscarCoincidenciasAsync(ProgressDialog progressDialog)
+ {
+ // Reset the Canvas children
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ var clearShapes = _mainViewModel.MainCanvas.Children.OfType().Where(s => s.Tag as string == "BuscarCoincidencias").ToList();
+ foreach (var shape in clearShapes)
+ {
+ _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;
+
+ // 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));
+
+ // Convertir CroppedBitmap a Mat directamente
+ Mat templateMat = BitmapSourceToMat(croppedBitmap);
+
+ int scale = 4;
+
+ // Convertir la plantilla a escala de grises y redimensionarla
+ Mat templateGray = new Mat();
+ CvInvoke.CvtColor(templateMat, templateGray, ColorConversion.Bgr2Gray);
+ Mat templateGrayResized = new Mat();
+ CvInvoke.Resize(templateGray, templateGrayResized, new Size(templateGray.Width / scale, templateGray.Height / scale), 0, 0, Inter.Linear);
+ progressDialog.ReportProgress(20);
+ // Cargar la imagen principal completa en un Mat
+ Mat mainImageMat = BitmapSourceToMat(bitmapSource);
+
+ // Convertir la imagen principal a escala de grises y redimensionarla
+ Mat mainImageGray = new Mat();
+ CvInvoke.CvtColor(mainImageMat, mainImageGray, ColorConversion.Bgr2Gray);
+ Mat mainImageGrayResized = new Mat();
+ CvInvoke.Resize(mainImageGray, mainImageGrayResized, new Size(mainImageGray.Width / scale, mainImageGray.Height / scale), 0, 0, Inter.Linear);
+
+ progressDialog.ReportProgress(50);
+
+ // Realizar la coincidencia de plantillas
+ Mat result = new Mat();
+ CvInvoke.MatchTemplate(mainImageGray, templateGray, result, TemplateMatchingType.CcoeffNormed);
+
+ // Establecer un umbral de coincidencia
+ if (Threshold < 0.4)
+ Threshold = 0.4f;
+ double threshold = Threshold;
+
+ int ConteoPositivos = 0;
+
+ // Obtener los puntos que superan el umbral
+ float[] resultArray = result.GetData(false) as float[];
+ if (resultArray != null)
+ {
+ for (int i = 0; i < resultArray.Length; i++)
+ {
+ if (resultArray[i] >= threshold)
+ {
+ int row = i / result.Cols;
+ int col = i % result.Cols;
+ // Crear y agregar el rectángulo al Canvas (ajustando por la escala)
+
+ Rectangle matchRect = new Rectangle
+ {
+ Stroke = new SolidColorBrush(Colors.Red),
+ StrokeThickness = 2,
+ Width = width / scaleFactorX,
+ Height = height / scaleFactorY,
+ Tag = "BuscarCoincidencias"
+ };
+ Canvas.SetLeft(matchRect, col / scaleFactorX);
+ Canvas.SetTop(matchRect, row / scaleFactorY);
+ Canvas.SetZIndex(matchRect, 40);
+ _mainViewModel.MainCanvas.Children.Add(matchRect);
+ ConteoPositivos++;
+ progressDialog.ReportProgress(90);
+ if (ConteoPositivos > 20)
+ return;
+ }
+ }
+ }
+ }
+ }
+ });
+ }
+
+ // Método para convertir BitmapSource a Mat
+ private Mat BitmapSourceToMat(BitmapSource bitmapSource)
+ {
+ Bitmap bitmap;
+ using (MemoryStream outStream = new MemoryStream())
+ {
+ BitmapEncoder enc = new BmpBitmapEncoder();
+ enc.Frames.Add(BitmapFrame.Create(bitmapSource));
+ enc.Save(outStream);
+ bitmap = new Bitmap(outStream);
+ }
+ return bitmap.ToMat();
+ }
+
+ public override void ucLoaded()
+ {
+ // El UserControl ya se ha cargado y podemos obtener las coordenadas para
+ // crear el objeto de simulacion
+ base.ucLoaded();
+
+ }
+
+ }
+
+ public partial class ucBuscarCoincidencias : UserControl, IDataContainer
+ {
+ public osBase? Datos { get; set; }
+
+ public ucBuscarCoincidencias()
+ {
+ InitializeComponent();
+ this.Loaded += OnLoaded;
+ this.Unloaded += OnUnloaded;
+ }
+ private void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ Datos?.ucLoaded();
+ }
+ private void OnUnloaded(object sender, RoutedEventArgs e)
+ {
+ Datos?.ucUnLoaded();
+ }
+ public void Resize(float width, float height)
+ {
+ if (Datos is osBuscarCoincidencias datos)
+ {
+ datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width);
+ datos.Alto = PixelToMeter.Instance.calc.PixelsToMeters(height);
+ }
+ }
+ public void Move(float LeftPixels, float TopPixels)
+ {
+ if (Datos != null)
+ {
+ Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels);
+ Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
+ }
+ }
+ public void Rotate(float Angle)
+ {
+ if (Datos != null)
+ if (Datos is osBuscarCoincidencias datos)
+ datos.Angulo = Angle;
+ }
+ public void Highlight(bool State) { }
+ public int ZIndex()
+ {
+ return 1;
+ }
+
+ }
+}
+
+
+
diff --git a/ObjetosSim/Extraccion Datos/ucExtraccionTag.xaml b/ObjetosSim/Extraccion Datos/ucExtraccionTag.xaml
index 1ff145e..bdbac16 100644
--- a/ObjetosSim/Extraccion Datos/ucExtraccionTag.xaml
+++ b/ObjetosSim/Extraccion Datos/ucExtraccionTag.xaml
@@ -5,16 +5,17 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
- mc:Ignorable="d">
+ mc:Ignorable="d"
+ Visibility="{Binding Show_on_this_page, Converter={StaticResource BoolToVisibilityConverter}}">