¿Por qué los arrays VectorOfKeyPoint y Mat están siendo sobrescritos por los nuevos resultados del detector SIFT?
During execution of PictureBox1_Click(object sender, EventArgs e)
:
using Emgu.CV;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
static VectorOfKeyPoint _templateKeyPoints = new VectorOfKeyPoint();
static Mat _templateDescriptor = new Mat();
VectorOfKeyPoint[] templateKeyPoints = new VectorOfKeyPoint[2];
Mat[] templateDescriptor = new Mat[2];
Bitmap[] croppedImage = new Bitmap[2];
public Form1()
{
InitializeComponent();
pictureBox1.Load("https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_960_720.jpg");
pictureBox2.Load("https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_960_720.jpg");
croppedImage[0] = (Bitmap)pictureBox1.Image.Clone();
croppedImage[1] = (Bitmap)pictureBox2.Image.Clone();
}
private void PictureBox1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 2; i++)
{
try
{
var processTemplate = ProcessTemplate(croppedImage[i].ToImage());
templateKeyPoints[i] = processTemplate.tempKeyPoints;
templateDescriptor[i] = processTemplate.tempDescriptor;
}
catch(Exception exp)
{
MessageBox.Show(exp.Message);
}
}
}
public static (VectorOfKeyPoint tempKeyPoints, Mat tempDescriptor)
ProcessTemplate(Image template)
{
try
{
SIFT detector = new SIFT();
detector.DetectAndCompute(template, null, _templateKeyPoints, _templateDescriptor, false);
}
catch (Exception exp)
{
MessageBox.Show(exp.Message);
}
return (_templateKeyPoints, _templateDescriptor);
}
}
}
Durante la primera iteración:
Cuando
templateKeyPoints[0]
ytemplateDescriptor[0]
poblada, obtengo los resultados correctos.Durante la segunda iteración:
Los nuevos resultados de
processTemplate.tempKeyPoints
yprocessTemplate.tempDescriptor
ser sobrescrito al primero elementos detemplateKeyPoints[i]
ytemplateDescriptor[i]
, respectivamente (no como se desee) y también se poblan a su segundo elemento respectivo (como deseado). ¿Por qué ocurre esta sobreescritura?
Pregunta hecha hace 3 años, 4 meses, 29 días - Por codecraftsman32c9
3 Respuestas:
-
Resolví el problema. Esto fue porque no estaba creando un nuevo
VectorOfKeyPoint
y 'Mat' instancia cuando llamoProcessTemplate()
método. Así que me mudéVectorOfKeyPoint _templateKeyPoints = new VectorOfKeyPoint();
yMat _templateDescriptor = new Mat();
al método como sigue:public static (VectorOfKeyPoint tempKeyPoints, Mat tempDescriptor) ProcessTemplate(Image
template) { VectorOfKeyPoint _templateKeyPoints = new VectorOfKeyPoint(); Mat _templateDescriptor = new Mat(); try { SIFT detector = new SIFT(); detector.DetectAndCompute(template, null, _templateKeyPoints, _templateDescriptor, false); } catch (Exception exp) { MessageBox.Show(exp.Message); } return (_templateKeyPoints, _templateDescriptor); } Respondida el Dec 17, 2020 a las 04:05 - por devdynamox
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando se debe a que estás utilizando variables estáticas (templateKeyPoints y _templateDescriptor) en tu método ProcessTemplate para almacenar los puntos clave y descriptores SIFT. Al ser estáticas, estas variables conservan su valor entre las llamadas al método, lo que significa que en cada iteración del bucle en PictureBox1Click estás sobrescribiendo las mismas variables estáticas _templateKeyPoints y _templateDescriptor con los resultados de la detección de SIFT de la imagen actual, causando que los resultados se guarden en la misma ubicación de memoria y se reflejen en todos los índices de templateKeyPoints y templateDescriptor.
Para resolver este problema, te recomendaría que elimines las variables estáticas templateKeyPoints y _templateDescriptor, y en su lugar, declares y uses variables locales dentro del método ProcessTemplate. De esta manera, cada llamada al método creará nuevas instancias de los resultados de SIFT que no se sobrescribirán entre iteraciones del bucle en el evento PictureBox1Click.
Aquí te dejo una versión modificada del código para que puedas implementar esta solución:
csharp using Emgu.CV; using Emgu.CV.Features2D; using Emgu.CV.Structure; using Emgu.CV.Util; using System; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form1 : Form { VectorOfKeyPoint[] templateKeyPoints = new VectorOfKeyPoint[2]; Mat[] templateDescriptor = new Mat[2]; Bitmap[] croppedImage = new Bitmap[2]; public Form1() { InitializeComponent(); pictureBox1.Load("https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_960_720.jpg"); pictureBox2.Load("https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_960_720.jpg"); croppedImage[0] = (Bitmap)pictureBox1.Image.Clone(); croppedImage[1] = (Bitmap)pictureBox2.Image.Clone(); } private void PictureBox1_Click(object sender, EventArgs e) { for (int i = 0; i < 2; i++) { try { var processTemplate = ProcessTemplate(croppedImage[i].ToImage
()); templateKeyPoints[i] = processTemplate.tempKeyPoints; templateDescriptor[i] = processTemplate.tempDescriptor; } catch (Exception exp) { MessageBox.Show(exp.Message); } } } public static (VectorOfKeyPoint tempKeyPoints, Mat tempDescriptor) ProcessTemplate(Image template) { VectorOfKeyPoint tempKeyPoints = new VectorOfKeyPoint(); Mat tempDescriptor = new Mat(); try { SIFT detector = new SIFT(); detector.DetectAndCompute(template, null, tempKeyPoints, tempDescriptor, false); } catch (Exception exp) { MessageBox.Show(exp.Message); } return (tempKeyPoints, tempDescriptor); } } } Con esta modificación, cada llamada a ProcessTemplate creará nuevos vector de puntos clave y matriz de descriptores que serán independientes entre sí y no se sobrescribirán entre iteraciones del bucle en el evento PictureBox1_Click.
Respondida el Dec 18, 2020 a las 04:05 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El problema surge porque estás utilizando variables estáticas (
_templateKeyPoints
y_templateDescriptor
) dentro de la funciónProcessTemplate
. Esto significa que estas variables se comparten entre todas las instancias de la función, por lo que cuando se llaman por segunda vez, las sobrescribe con los nuevos resultados.Para resolver este problema, debes pasar las variables
_templateKeyPoints
y_templateDescriptor
como parámetros a la funciónProcessTemplate
en lugar de utilizar variables estáticas. De esta forma, cada llamada a la función tendrá su propio conjunto de variables y no se sobrescribirán entre sí.Aquí tienes el código modificado:
csharp public static (VectorOfKeyPoint tempKeyPoints, Mat tempDescriptor) ProcessTemplate(Image
template, VectorOfKeyPoint templateKeyPoints, Mat templateDescriptor) { try { SIFT detector = new SIFT(); detector.DetectAndCompute(template, null, templateKeyPoints, templateDescriptor, false); } catch (Exception exp) { MessageBox.Show(exp.Message); } return (templateKeyPoints, templateDescriptor); } Y en el método
PictureBox1_Click
:csharp private void PictureBox1_Click(object sender, EventArgs e) { for (int i = 0; i < 2; i++) { try { var processTemplate = ProcessTemplate(croppedImage[i].ToImage
(), new VectorOfKeyPoint(), new Mat()); templateKeyPoints[i] = processTemplate.tempKeyPoints; templateDescriptor[i] = processTemplate.tempDescriptor; } catch(Exception exp) { MessageBox.Show(exp.Message); } } } Ahora, cada llamada a
ProcessTemplate
utilizará su propio conjunto de variablestemplateKeyPoints
ytemplateDescriptor
, y no se sobrescribirán entre sí.Respondida el Dec 18, 2020 a las 04:07 - por Gemini
Votos positivos: 0 | Votos negativos: 0