Net enthält eine Klasse XmlSerializer
, die automatisch Instanzen von Typen von und nach XML über Reflexion von öffentlichen Eigenschaften serialisiert werden kann. Es unterstützt auch die IXmlSerializable
Schnittstelle, um Typen zu erlauben, ihr Standardverhalten zu überschreiben und vollständige Kontrolle darüber zu haben, wie sie in XML serialisiert werden.
Wie sich herausstellt, IntrinsicCameraParameters.IntrinsicMatrix
und IntrinsicCameraParameters.DistortionCoeffs
sind beide vom Typ Matrix<double>
deren Basisklasse CvArray<TDepth>
implementiert diese Schnittstelle. So Objekte dieses Typs serializeable sein sollte XML XmlSerializer
mit den folgenden Erweiterungsmethoden verwenden:
public static partial class XmlSerializationExtensions
{
public static void SerializeToXmlFile<T>(this T obj, string fileName)
{
var settings = new XmlWriterSettings { Indent = true };
using (var writer = XmlWriter.Create(fileName, settings))
{
new XmlSerializer(typeof(T)).Serialize(writer, obj);
}
}
public static T DeserializeFromXmlFile<T>(string fileName)
{
using (var reader = XmlReader.Create(fileName))
{
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
}
}
Dann können Sie einfach tun:
var fileName = "C:\\Video\\Cal\\CameraMatrix.xml";
ICP.IntrinsicMatrix.SerializeToXmlFile(fileName);
Und später, es wieder zu lesen, tun:
var newIntrinsicMatrix = XmlSerializationExtensions.DeserializeFromXmlFile<Matrix<double>>(fileName);
Zur Bestätigung, siehe the documentation für ein weiteres Beispiel für das Serialisieren einer Matrix von und nach XML.
Logischerweise sollte es auch möglich sein, die gesamten IntrinsicCameraParameters
in einer einzelnen XML-Datei mit der gleichen generischen Erweiterungsmethode zum Speichern und Wiederherstellen:
ICP.SerializeToXmlFile(fileName);
Leider gibt es ein Problem. Die Implementierung von ReadXml()
für CvArray<TDepth>
ist unterbrochen. Von Proper way to implement IXmlSerializable?
Die ReadXml Methode muss Ihr Objekt Rekonstitution unter Verwendung der Information, dass durch die WriteXml Methode geschrieben wurde.
Wenn diese Methode aufgerufen wird, wird der Leser zu Beginn des Element positioniert, das die Informationen für Ihre Art wickelt. Das heißt, kurz vor dem Start-Tag, das den Anfang eines serialisierten Objekts angibt. Wenn diese Methode zurückgibt, muss es das gesamte Element vom Anfang bis zum Ende gelesen haben, einschließlich seines gesamten Inhalts. Im Gegensatz zu der WriteXml-Methode behandelt das Framework das Wrapper-Element nicht automatisch. Ihre Implementierung muss dies tun.Bei Nichtbeachtung dieser Positionierungsregeln kann Code unerwartete Laufzeitausnahmen generieren oder Daten korrumpieren.
Und eine schnelle Überprüfung der source code für CvArray<TDepth>
zeigt, dass das Ende des Hüllenelementes ist nicht lesen. Dies führt dazu, dass alle Daten, die auf die erste CvArray<>
im XML folgen, nicht deserialisiert werden können.
Wenn Sie also eine Matrix<T>
in eine größere XML-Datei einbetten möchten, müssen Sie Serialisierungssurrogate-Typen (oder Datentransfer-Objekttypen, wenn Sie bevorzugen) einführen, wie folgt. (Beachten Sie die Einführung des Emgu.CV.SerializationSurrogates
Namespace):
namespace Emgu.CV.SerializationSurrogates
{
using Emgu.CV;
public class Matix<TDepth> where TDepth : new()
{
[XmlAttribute]
public int Rows { get; set; }
[XmlAttribute]
public int Cols { get; set; }
[XmlAttribute]
public int NumberOfChannels { get; set; }
[XmlAttribute]
public int CompressionRatio { get; set; }
public byte[] Bytes { get; set; }
public static implicit operator Emgu.CV.SerializationSurrogates.Matix<TDepth>(Emgu.CV.Matrix<TDepth> matrix)
{
if (matrix == null)
return null;
return new Matix<TDepth>
{
Rows = matrix.Rows,
Cols = matrix.Cols,
NumberOfChannels = matrix.NumberOfChannels,
CompressionRatio = matrix.SerializationCompressionRatio,
Bytes = matrix.Bytes,
};
}
public static implicit operator Emgu.CV.Matrix<TDepth>(Matix<TDepth> surrogate)
{
if (surrogate == null)
return null;
var matrix = new Emgu.CV.Matrix<TDepth>(surrogate.Rows, surrogate.Cols, surrogate.NumberOfChannels);
matrix.SerializationCompressionRatio = surrogate.CompressionRatio;
matrix.Bytes = surrogate.Bytes;
return matrix;
}
}
public class IntrinsicCameraParameters
{
[XmlElement("IntrinsicMatrix", Type = typeof(Emgu.CV.SerializationSurrogates.Matix<double>))]
public Emgu.CV.Matrix<double> IntrinsicMatrix { get; set; }
[XmlElement("DistortionCoeffs", Type = typeof(Emgu.CV.SerializationSurrogates.Matix<double>))]
public Emgu.CV.Matrix<double> DistortionCoeffs { get; set; }
public static implicit operator Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters(Emgu.CV.IntrinsicCameraParameters icp)
{
if (icp == null)
return null;
return new IntrinsicCameraParameters
{
DistortionCoeffs = icp.DistortionCoeffs,
IntrinsicMatrix = icp.IntrinsicMatrix,
};
}
public static implicit operator Emgu.CV.IntrinsicCameraParameters(Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters surrogate)
{
if (surrogate == null)
return null;
return new Emgu.CV.IntrinsicCameraParameters
{
DistortionCoeffs = surrogate.DistortionCoeffs,
IntrinsicMatrix = surrogate.IntrinsicMatrix,
};
}
}
}
Jetzt können Sie Ihre IntrinsicCameraParameters
mit folgenden Erweiterungsmethoden speichern und abrufen: Alle
public static class IntrinsicCameraParametersExtensions
{
public static void SerializeIntrinsicCameraParametersExtensionsToXmlFile(this IntrinsicCameraParameters icp, string fileName)
{
var surrogate = (Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters)icp;
surrogate.SerializeToXmlFile(fileName);
}
public static IntrinsicCameraParameters DeserializeIntrinsicCameraParametersFromXmlFile(string fileName)
{
var surrogate = XmlSerializationExtensions.DeserializeFromXmlFile<Emgu.CV.SerializationSurrogates.IntrinsicCameraParameters>(fileName);
return surrogate;
}
}
, dass gesagt wird, IntrinsicCameraParameters
ist marked as obsolete in der aktuellen Version :
[SerializableAttribute]
[ObsoleteAttribute("This class will be removed in the next release, please use separate camera matrix and distortion coefficient with the CvInvoke function instead.")]
public class IntrinsicCameraParameters : IEquatable<IntrinsicCameraParameters>
Sie möchten vielleicht diesen Entwurf neu denken.
übrigens eine nicht-gebrochene Version von CvArray<TDepth>.ReadXml()
würde wie folgt aussehen:
public virtual void ReadXml(System.Xml.XmlReader reader)
{
#region read properties of the matrix and assign storage
int rows = Int32.Parse(reader.GetAttribute("Rows")); // Should really be using XmlConvert for this
int cols = Int32.Parse(reader.GetAttribute("Cols"));
int numberOfChannels = Int32.Parse(reader.GetAttribute("NumberOfChannels"));
SerializationCompressionRatio = Int32.Parse(reader.GetAttribute("CompressionRatio"));
AllocateData(rows, cols, numberOfChannels);
#endregion
#region decode the data from Xml and assign the value to the matrix
if (!reader.IsEmptyElement)
{
using (var subReader = reader.ReadSubtree())
{
// Using ReadSubtree guarantees we don't read past the end of the element in case the <Bytes> element
// is missing or extra unexpected elements are included.
if (subReader.ReadToFollowing("Bytes"))
{
int size = _sizeOfElement * ManagedArray.Length;
if (SerializationCompressionRatio == 0)
{
Byte[] bytes = new Byte[size];
subReader.ReadElementContentAsBase64(bytes, 0, bytes.Length);
Bytes = bytes;
}
else
{
int extraHeaderBytes = 20000;
Byte[] bytes = new Byte[size + extraHeaderBytes];
int countOfBytesRead = subReader.ReadElementContentAsBase64(bytes, 0, bytes.Length);
Array.Resize<Byte>(ref bytes, countOfBytesRead);
Bytes = bytes;
}
}
}
}
// Consume the end of the wrapper element also.
reader.Read();
#endregion
}
[ 'IntrinsicCameraParameters.DistortionCoeffs'] (http://www.emgu.com/wiki/files/2.0.0.0/html /ecc3c8f8-9f92-10b1-96a2-b0b1ca6501e9.htm) implementiert tatsächlich ['IXmlSerializable'] (https://msdn2.microsoft.com/en-us/library/fhd7bk0a), also haben Sie einfach versucht,' XmlSerializer' zu verwenden ] (https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer (v = vs.110) .aspx) auf Ihrem ['IntrinsicCameraParameters'] (http: //www.emgu .com/wiki/files/2.0.0.0/html/1ad4e83e-3c4b-d128-cd44-c9e8a9da007f.htm)? – dbc
Ich habe das nicht versucht. Ich bin nicht sehr gut mit XML. Können Sie näher erläutern, wie XmlSerializer verwendet wird? –